Pomóż zrozumieć transformację Hougha

19

Próbuję uzyskać transformację Hougha do pracy w MATLAB, ale mam problemy. Mam naprawdę zły sposób na wykrywanie pików, które należy naprawić, ale wcześniej muszę mieć możliwość odwrócenia transformacji Hougha, aby ponownie poprawnie utworzyć linie. Oto rodzaj rzeczy, które teraz otrzymuję:

wprowadź opis zdjęcia tutaj

wygląda na obróconą o 90 stopni, ale nie jestem pewien dlaczego. Nie jestem pewien, czy to moja przestrzeń Hougha jest zła, czy też to sposób, w jaki de-Hougha i rysuję linie. Czy ktoś mógłby również poprawić moje wykrywanie pików? Obrazy użyte w kodzie są tutaj

%% load a sample image; convert to grayscale; convert to binary

%create 'x' image (works well)
a = eye(255);
b = flipud(eye(255));
x = a + b;
x(128,128) = 1;

%image = rgb2gray(imread('up.png')) < 255;
%image = rgb2gray(imread('hexagon.png')) < 255;
%image = rgb2gray(imread('traingle.png')) < 255;
%%% these work
%image = x;
%image = a;
image = b;    

%% set up variables for hough transform
theta_sample_frequency = 0.01;                                             
[x, y] = size(image);
rho_limit = norm([x y]);                                                
rho = (-rho_limit:1:rho_limit);
theta = (0:theta_sample_frequency:pi);
num_thetas = numel(theta);
num_rhos = numel(rho);
hough_space = zeros(num_rhos, num_thetas);

%% perform hough transform
for xi = 1:x
    for yj = 1:y
        if image(xi, yj) == 1 
            for theta_index = 1:num_thetas
                th = theta(theta_index);
                r  = xi * cos(th) + yj * sin(th);
                rho_index = round(r + num_rhos/2);                      
                hough_space(rho_index, theta_index) = ...
                     hough_space(rho_index, theta_index) + 1;
            end
        end
    end
end  

%% show hough transform
subplot(1,2,1);
imagesc(theta, rho, hough_space);
title('Hough Transform');
xlabel('Theta (radians)');
ylabel('Rho (pixels)');
colormap('gray');

%% detect peaks in hough transform
r = [];
c = [];
[max_in_col, row_number] = max(hough_space);
[rows, cols] = size(image);
difference = 25;
thresh = max(max(hough_space)) - difference;
for i = 1:size(max_in_col, 2)
   if max_in_col(i) > thresh
       c(end + 1) = i;
       r(end + 1) = row_number(i);
   end
end

%% plot all the detected peaks on hough transform image
hold on;
plot(theta(c), rho(r),'rx');
hold off;


%% plot the detected line superimposed on the original image
subplot(1,2,2)
imagesc(image);
colormap(gray);
hold on;

for i = 1:size(c,2)
    th = theta(c(i));
    rh = rho(r(i));
    m = -(cos(th)/sin(th));
    b = rh/sin(th);
    x = 1:cols;
    plot(x, m*x+b);
    hold on;
end

Powiązane: Jak wykonać De-Houghing obrazu Hougha przekształconego?

waspinator
źródło
czy udało ci się rozwiązać problem? Mam podobny problem. dzięki
Erez Posner
transformacja hous sous matlab dla detektora plus elipsy użytkownika

Odpowiedzi:

11

Po pierwsze, Matlab ma wbudowaną transformację Hougha : nie trzeba wymyślać koła na nowo.

[H,T,R] = hough(BW,'RhoResolution',0.5,'Theta',-90:0.5:89.5);

Chociaż twój obraz niekoniecznie wymaga wykrycia krawędzi, możesz poprawić czas przetwarzania i efektywność algorytmu przy jego użyciu. Twój trójkąt ma grube obszary bieli i czerni. Idealnie byłoby, gdyby trójkąt miał grubość 1 piksela, oznaczając krawędzie trójkąta. Użyj wykrywania Canny Edge

BW = edge(Image,'canny');

90<θ<900<θ<1800<θ<π90π/2

Istnieje możliwość wyboru niewłaściwego piku, ponieważ istnieją sąsiednie piki, które mogą być większe w matrycy akumulatora. Chociaż istnieje tutaj wiele algorytmów, jeden z nich widziałem w przeszłości w Hough Transforms:

1) Define a region shape (typically its square) 
2) Define an accumulator threshold  
3) Select one pixel in the accumulator matrix
4) If it is a peak (i.e., larger than neighboring values above a threshold)
       a) look at the points within the region shape.
       b) If there is a larger value
              this is not a peak
          Else
              this is a peak
 5) Move to next pixel in accumulator matrix.

Zajrzyj do HoughLines, aby wyświetlić linie przekształcenia Hougha, wyniki:

http://www.mathworks.com/help/toolbox/images/ref/houghlines.html

Efekty korzystania z Canny Edge Detector

Wykrywanie krawędzi może potencjalnie zmienić każdą stronę trójkąta w dwie linie.

Wykrywanie ostrych krawędzi ma na celu uzyskanie maksymalnie cienkich / wąskich krawędzi przy użyciu nie maksymalnego tłumienia

Wykrywanie Canny Edge w pigułce (źródło: cyfrowe przetwarzanie obrazu, Gonazalez)

1) Smooth input Image using a Gaussian Filter
2) Compute the Gradient magnitude and angle (Sobel, Perwitt or robert cross filters)
3) Apply Nonmaxima suppression (this is where the thinning happens) 
   a) Figure out which direction the edge is
   b) If the edge's magnitude is smaller than one of its two neighbors in the direction of the edge
          set the edge point to zero
      Else
          leave it alone
4) Use double thresholding and connectivity analysis to detect and link edges
CyberMen
źródło
Dziękuję za odpowiedź. Robię to od zera, aby lepiej to zrozumieć. Wykrywanie ostrych krawędzi wciąż daje 2 trójkąty. jeden na wewnętrzną krawędź i na zewnętrzną krawędź. Nauczyłem się teorii z wikipedii, która mówi, że theta wynosi 0: pi. Wiem, że wbudowana funkcja używa -pi / 2: pi / 2, ale nie powinno być żadnej różnicy?
waspinator,
Od samego początku zasięg nie powinien mieć znaczenia. (czy potrafisz odróżnić linię, która została obrócona o 180 stopni?) JEDNAK to robi różnicę, jeśli używasz transformacji Hougha dla algorytmów korekcji obrazu. (Oznaczałoby to różnicę między obrazem w górę a obrazem w górę)
CyberMen
Czy wykrywanie krawędzi nie stworzy 2 linii, w których chcesz znaleźć tylko 1? Lepiej byłoby znaleźć coś, co znajdzie środek grubej linii.
endolith
@endolith Zawierał trochę dyskusji na temat wykrywania krawędzi w oryginalnym poście
CyberMen
„nie musisz wymyślać koła od nowa”? Powiedz to mojemu instruktorowi ;-)
Nathan Schwermann
3
    if image(xi, yj) == 1 

należy zmienić na

    if image(yj, xi) == 1 

aby linie zadziałały na dehough

waspinator
źródło
1

Odpowiedź przy użyciu 3 pętli jest mniej niż optymalna i można ją poprawić, oto bardziej intuicyjne podejście / punkt widzenia:

Każda para ważnych punktów określa unikalny a & b y = ax + b. Linia będzie miała wiele par o tej samej wartości a & b, więc długa linia będzie występować jako szczyt. Dotyczy to również biegunowych współrzędnych r & teta.

Zamiast traktować każdy punkt osobno, użyj par kropek. Jeśli możesz przechowywać wszystkie (zwykle rzadkie) punkty na osobnej liście, to lepiej, ale nie jest to konieczne.

  1. Weź każdą parę i oblicz jej a & b. (w zaokrągleniu do wartości dyskretnych)
  2. Przejdź do określonego miejsca w tablicy i dodaj 1.

Długa linia -> wiele par z tym samym a, b.
Sporadyczne punkty -> małe liczenie w określonych komórkach -> bardziej jak bałagan.


Innym sposobem spojrzenia na to jest z punktu widzenia Radona / rzutowania.

  • Linia będzie silnie rzutować na prostopadłą „linię zbierającą”, dzięki czemu uzyska wysoki wynik.
  • Jeśli kąt między linią a „linią zbierającą” nie wynosi 90 stopni lub linia zbierająca nie zbiera wszystkich punktów linii rzutowanych na tę „linię zbierającą”, wynik będzie niższy.
Ilan Synaj
źródło