Detección de un círculo en datos de imágenes ruidosas

17

Tengo una imagen que se parece a la siguiente: ingrese la descripción de la imagen aquí

Estoy tratando de encontrar el radio (o diámetro) del círculo. Intenté usar la transformación circular de Hough (a través de Matlab imfindcircles(bw,[rmin rmax],'ObjectPolarity','bright')), y al ajustarla a un círculo o una elipse (función hecha en casa que funciona bastante bien para datos menos ruidosos, ver más abajo).

También probé un procesamiento de imágenes para obtener un círculo más claro, por ejemplo, vea a continuación:

se = strel('disk', 2);
bw = imdilate(bw, se);
bw = bwareaopen(bw,100000); 
bw =  edge(bw); 

ingrese la descripción de la imagen aquí

Sin embargo, cuando introduzco la imagen procesada en cualquiera de las técnicas (ajuste de Hough y circle \ ellipse), ninguna de ellas logra detectar el círculo de manera decente.

Aquí hay un fragmento de código del buscador de círculos que escribí (matlab) [row col] = find (bw); contour = bwtraceboundary (bw, fila (1), col (1)], 'N', conectividad, num_points);

    x = contour(:,2);
    y = contour(:,1);

    % solve for parameters a, b, and c in the least-squares sense by
    % using the backslash operator
    abc = [x y ones(length(x),1)] \ -(x.^2+y.^2);
    a = abc(1); b = abc(2); c = abc(3);

    % calculate the location of the center and the radius
    xc = -a/2;
    yc = -b/2;
    radius  =  sqrt((xc^2+yc^2)-c);

Se apreciarán enfoques alternativos ...

bla
fuente
Hough transform busca un círculo, no un disco lleno. primero debería hacer una detección de bordes para convertir el disco lleno en un círculo vacío. ¿Cuáles son las propiedades de tus círculos? es el tamaño constante? pueden ser elipses? ¿Se pueden distribuir los puntos de manera diferente?
endolito el
Lo intenté (ver ejemplo editado), ¿es demasiado ruidoso o no lo suficientemente circular? Además, el tamaño es constante y puede tener una elipticidad mínima (aunque en realidad es una ventana perfectamente circular) debido a un error en el ángulo de la cámara.
bla
si el tamaño y la forma son constantes, puede intentar algo como la correlación cruzada de una plantilla de disco llena con la imagen de punto original
endolito el
Además de mi respuesta, creo que podría estar tratando de hacer esto en una etapa demasiado posterior de su tubería de procesamiento de imágenes. ¿Podría contarnos más sobre el problema y mostrar algunos pasos anteriores?
Andrey Rubshtein, el

Respuestas:

13

Aquí está mi solución, está cerca de la idea de @ Yoda, pero cambié algunos pasos.

  • Marque todos los píxeles de manera que haya al menos 6 píxeles en su vecindario 7x7
  • Eliminar todos los blobs, pero el más grande
  • Llenar agujeros
  • Aplicar detección de bordes
  • Encontrar círculo usando la transformación de Hough

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Aquí está el código relevante de Matlab. Estoy usando Hough transform para el archivo círculos .m en mi código.

function FindCircle()
    close all;
    im = imread('C:\circle.png');
    im = im(:,:,2);

    ims = conv2(double(im), ones(7,7),'same');
    imbw = ims>6;
    figure;imshow(imbw);title('All pixels that there are at least 6 white pixels in their hood');

    props = regionprops(imbw,'Area','PixelIdxList','MajorAxisLength','MinorAxisLength');
    [~,indexOfMax] = max([props.Area]);
    approximateRadius =  props(indexOfMax).MajorAxisLength/2;

    largestBlobIndexes  = props(indexOfMax).PixelIdxList;
    bw = false(size(im));
    bw(largestBlobIndexes) = 1;
    bw = imfill(bw,'holes');
    figure;imshow(bw);title('Leaving only largest blob and filling holes');
    figure;imshow(edge(bw));title('Edge detection');

    radiuses = round ( (approximateRadius-5):0.5:(approximateRadius+5) );
    h = circle_hough(edge(bw), radiuses,'same');
    [~,maxIndex] = max(h(:));
    [i,j,k] = ind2sub(size(h), maxIndex);
    radius = radiuses(k);
    center.x = j;
    center.y = i;

    figure;imshow(edge(bw));imellipse(gca,[center.x-radius  center.y-radius 2*radius 2*radius]);
    title('Final solution (Shown on edge image)');

    figure;imshow(im);imellipse(gca,[center.x-radius  center.y-radius 2*radius 2*radius]);
    title('Final solution (Shown on initial image)');

end
Andrey Rubshtein
fuente
1
¿Qué está haciendo la transformación de Hough aquí que hace que resuelva y encuentre el círculo azul? ¿Proyecta muchos círculos de diferentes radios en diferentes posiciones de la imagen y encuentra el que mejor se ajusta?
Spacey
@Mohammad, es el detector de círculo habitual. Utiliza binning y votación.
Andrey Rubshtein
También puede usar la Transformación rápida de simetría radial (FRST) después del primer paso en esta respuesta.
Geniedesalpages
10

Es bastante sencillo hacerlo usando el procesamiento de imágenes. La siguiente es una prueba de concepto en Mathematica . Tendrás que traducirlo a MATLAB.

  • Primero, recorte los ejes y mantenga solo la parte de la imagen. Yo llamo a esta variable img.
  • Binariza la imagen y dilata, seguido de una transformación de relleno. También elimino componentes pequeños perdidos que no están conectados al blob principal. Debería darte algo como lo siguiente:

    filled = Binarize@img ~Dilation~ 3 // FillingTransform // DeleteSmallComponents
    

  • Luego, encuentre el centroide de este blob y el radio de disco equivalente del blob (openCV, MATLAB tienen comandos equivalentes para hacer esto)

    {center, radius} = 1 /. ComponentMeasurements[filled, {"Centroid", "EquivalentDiskRadius"}]
    
  • ¡Eso es! Ahora dibuje la imagen original y un círculo con el centro y el radio anteriores para ver cómo encaja:

    Show[img, Graphics[{Red, Circle[center, radius]}]]
    

Lorem Ipsum
fuente
Respuesta impresionante! ¿Puedes por favor ampliar la transformación de dilatación y llenado?
Spacey
@Mohammad La dilatación es una operación básica y se explica fácilmente por el artículo del wiki. La transformación de relleno llena los "agujeros" o, en otras palabras, conjuntos de píxeles rodeados por píxeles de mayor valor. Vea la sección "Más información" aquí
Lorem Ipsum
Ah lo siento, escribí mal. Estoy un poco familiarizado con la transformación de dilatación, en realidad me preguntaba si podría ampliar la 'transformación de llenado'. ¿Qué conjunto de reglas está usando exactamente? Parece que no puedo encontrar información relacionada con eso. Tal vez va por otro nombre?
Spacey
@yoda, gracias por la respuesta, pero si lees la pregunta notarías que he intentado la dilatación y la adaptación. La imagen producida antes de detectar bordes es similar a la suya. Me pongo en forma, no es exacto. Lo mismo es para su ajuste, puede ver que la parte superior del círculo ajustado es demasiado grande, presumiblemente porque tiene en cuenta el punto ruidoso en la parte superior sobre el círculo. También he tratado de ajustar una elipse (como se indica en la pregunta), el problema es que el ajuste no es lo suficientemente bueno. Creo que la mejor forma sería usar la mejor parte del círculo (un arco) para hacer el ajuste.
bla
@nate No entiendo qué quieres decir con "parte superior del círculo ajustado" y "mejor parte del círculo". Puede usar diferentes métricas ... cuadro delimitador, longitud del eje mayor, longitud del eje menor, distancia media desde el centroide, distancia media desde el centroide, etc. Todo depende de lo que desee.
Lorem Ipsum el