Ayuda a comprender la transformación de Hough

19

Estoy tratando de hacer que una transformación de Hough funcione en MATLAB, pero tengo problemas. Tengo una forma realmente mala de detectar picos que deben corregirse, pero antes de eso necesito poder revertir la transformación de hough para crear las líneas de nuevo correctamente. Este es el tipo de cosas que estoy recibiendo ahora:

ingrese la descripción de la imagen aquí

parece que ha girado 90 grados, pero no estoy seguro de por qué. No estoy seguro de si es mi espacio Hough lo que está mal, o si es la forma en que elimino Hough y dibujo las líneas. ¿Alguien podría ayudarme a mejorar mi detección de picos? Las imágenes utilizadas en el código están aquí.

%% 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

Vinculado: ¿Cómo hacer el deshuesado de una imagen transformada de Hough?

Waspinator
fuente
¿lograste resolver tu problema? Estoy enfrentando un problema similar. gracias
Erez Posner
transformación de hough sous matlab pour détecter plusieurs elipses

Respuestas:

11

En primer lugar, Matlab tiene una transformación Hough incorporada : no es necesario reinventar la rueda.

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

Aunque su imagen no requiere necesariamente la detección de bordes, podría mejorar el tiempo de procesamiento y la efectividad del algoritmo que uso. Tu triángulo tiene regiones gruesas de blanco y negro. Idealmente, el triángulo tendría 1px de grosor marcando los bordes del triángulo. Utilice la detección de bordes de Canny

BW = edge(Image,'canny');

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

Existe la posibilidad de que elija el pico incorrecto porque hay picos vecinos que pueden ser más grandes en la matriz del acumulador. Si bien hay muchos algoritmos, aquí hay uno que he visto usado en Hough Transforms en el pasado:

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.

Mire en HoughLines para mostrar las líneas de transformación de hough, resultados:

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

Efectos del uso de Canny Edge Detector

La detección de bordes puede potencialmente convertir cada lado del triángulo en dos líneas.

El objetivo de la detección de bordes afilados es producir bordes máximos / angostos máximos mediante el uso de supresión no máxima

Canny Edge Detection in a Nutshell (Fuente: Procesamiento de imagen digital, 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
fuente
gracias por la respuesta. Lo hago desde cero para entenderlo mejor. La detección de bordes caninos todavía da 2 triángulos. uno para el borde interno y afuera para el borde externo. Aprendí la teoría de Wikipedia, que establece que theta es 0: pi. Sé que la función incorporada usa -pi / 2: pi / 2, pero ¿no debería haber una diferencia real?
waspinator
De buenas a primeras, el rango no debería hacer una diferencia. (¿puede distinguir la diferencia entre una línea que se ha girado 180 grados?) SIN EMBARGO, esto hace una diferencia si está utilizando la transformación hough para algoritmos de corrección de imagen. (Significaría la diferencia entre una imagen al derecho y al revés)
CyberMen
¿La detección de bordes no produciría 2 líneas donde desea encontrar solo 1? Algo que encuentre el centro de una línea gruesa sería mejor.
endolito
@endolith Incluyó un poco de discusión sobre la detección de bordes en la publicación original
CyberMen
'No hay necesidad de reinventar la rueda'? Dile eso a mi instructor ;-)
Nathan Schwermann
3
    if image(xi, yj) == 1 

necesita ser cambiado a

    if image(yj, xi) == 1 

para que las líneas funcionen en la profundidad

Waspinator
fuente
1

La respuesta usando los 3 bucles es menos que óptima y podría mejorarse, aquí hay más de un enfoque / punto de vista intuitivo:

Cada par de puntos válidos establece un a & b único de y = ax + b. Una línea tendrá muchos pares con el mismo valor de a & b, por lo que habrá una línea larga como pico. Esto también es cierto para las coordenadas polares r & teta.

En lugar de tratar cada punto por separado, use pares de puntos. Si puede almacenar todos los puntos (generalmente escasos) en una lista separada, es mejor, pero no es obligatorio.

  1. Tome cada par y calcule su a y b. (redondeado a valores discretos)
  2. Vaya al lugar específico en la matriz y agregue 1.

Línea larga -> muchos pares con el mismo a, b.
Puntos esporádicos -> recuento pequeño en celdas específicas -> más como desorden.


Otra forma de verlo es desde el punto de vista del radón / proyectivo.

  • Una línea se proyectará fuertemente a una "línea de recolección" perpendicular, por lo que tiene una puntuación alta.
  • Si el ángulo entre la línea y la "línea de recolección" no es 90 grados o la línea de recolección no recolecta todos los puntos de línea proyectados en esta "línea de recolección", habrá una puntuación más baja.
Ilan sinai
fuente