Main Content

Esta página aún no se ha traducido para esta versión. Puede ver la versión más reciente de esta página en inglés.

Detectar y medir objetos circulares en una imagen

En este ejemplo se muestra cómo utilizar para detectar automáticamente círculos u objetos circulares en una imagen.imfindcircles También muestra el uso de para visualizar los círculos detectados.viscircles

Paso 1: Cargar imagen

Este ejemplo utiliza una imagen de virutas de plástico redondas de varios colores.

rgb = imread('coloredChips.png'); imshow(rgb)

Además de tener un montón de círculos para detectar, hay algunas cosas interesantes que suceden en esta imagen desde un punto de vista de detección de círculos:

  1. Hay fichas de diferentes colores, que tienen diferentes contrastes con respecto al fondo. En un extremo, los azules y rojos tienen un fuerte contraste en este fondo. En el otro extremo, algunas de las fichas amarillas no contrastan bien con el fondo.

  2. Observe cómo algunas fichas están una encima de la otra y otras que están juntas y casi tocándose entre sí. Los límites de objetos superpuestos y la oclusión de objetos suelen ser escenarios desafiantes para la detección de objetos.

Paso 2: Determinar el rango de radio para buscar círculos

necesita un rango de radio para buscar los círculos.imfindcircles Una forma rápida de encontrar el rango de radio adecuado es utilizar la herramienta interactiva para obtener una estimación aproximada de los radios de varios objetos.imdistline

d = imdistline;

crea una herramienta arrastrable que se puede mover para caber a través de un chip y los números se pueden leer para obtener una estimación aproximada de su radio.imdistline La mayoría de los chips tienen radio en el rango de 21-23 píxeles. Utilice un rango de radio ligeramente mayor de 20-25 píxeles para estar seguro. Antes de eso, retire la herramienta.imdistline

delete(d)

Paso 3: Intento inicial de encontrar círculos

Llame a esta imagen con el radio de búsqueda de [20 25] píxeles.imfindcircles Antes de eso, es una buena práctica preguntar si los objetos son más brillantes u oscuros que el fondo. Para responder a esa pregunta, mire la versión en escala de grises de esta imagen.

gray_image = rgb2gray(rgb); imshow(gray_image)

El fondo es bastante brillante y la mayoría de las fichas son más oscuras que el fondo. Pero, de forma predeterminada, busca objetos circulares que son más brillantes que el fondo.imfindcircles Por lo tanto, establezca el parámetro 'ObjectPolarity' en 'dark' en para buscar ojeras.imfindcircles

[centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark')
centers =       []   radii =       [] 

Tenga en cuenta que las salidas y están vacías, lo que significa que no se encontraron círculos.centersradii Esto sucede con frecuencia porque es un círculo, y similar a la mayoría de los detectores, tiene un interno que determina su sensibilidad.imfindcirclesDetectorimfindcirclesumbral de detección En términos simples significa que la confianza del detector en una detección determinada (círculo) tiene que ser mayor que un cierto nivel antes de que se considere una detección. tiene un parámetro 'Sensibilidad' que se puede utilizar para controlar este umbral interno, y en consecuencia, la sensibilidad del algoritmo.Válidoimfindcircles Un valor de "Sensibilidad" más alto establece el umbral de detección más bajo y conduce a la detección de más círculos. Esto es similar al control de sensibilidad en los detectores de movimiento utilizados en los sistemas de seguridad en el hogar.

Paso 4: Aumentar la sensibilidad de detección

Volviendo a la imagen del chip, es posible que en el nivel de sensibilidad predeterminado todos los círculos sean más bajos que el umbral interno, por lo que no se detectaron círculos. De forma predeterminada, 'Sensibilidad', que es un número entre 0 y 1, se establece en 0,85. Aumente la 'Sensibilidad' a 0,9.

[centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', ...     'Sensitivity',0.9)
centers = 8×2

  146.1895  198.5824
  328.8132  135.5883
  130.3134   43.8039
  175.2698  297.0583
  312.2831  192.3709
  327.1316  297.0077
  243.9893  166.4538
  271.5873  280.8920

radii = 8×1

   23.1604
   22.5710
   22.9576
   23.7356
   22.9551
   22.9995
   22.9055
   23.0298

Esta vez encontró algunos círculos - ocho para ser precisos. contiene las ubicaciones de los centros de círculo y contiene los radios estimados de esos círculos.imfindcirclescentersradii

Paso 5: Dibuja los círculos en la imagen

La función se puede utilizar para dibujar círculos en la imagen.viscircles Las variables de salida y desde se pueden pasar directamente a .centersradiiimfindcirclesviscircles

imshow(rgb) h = viscircles(centers,radii);

Los centros circulares parecen correctamente posicionados y sus radios correspondientes parecen coincidir bien con las fichas reales. Pero todavía se perdieron bastantes fichas. Intente aumentar aún más la "Sensibilidad", a 0,92.

[centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', ...     'Sensitivity',0.92);  length(centers)
ans = 16 

Así que aumentar la "sensibilidad" nos hace aún más círculos. Vuelva a trazar estos círculos en la imagen.

delete(h)  % Delete previously drawn circles h = viscircles(centers,radii);

Paso 6: Utilice el segundo método (dos etapas) para encontrar círculos

Este resultado se ve mejor. tiene dos métodos diferentes para encontrar círculos.imfindcircles Hasta ahora, el método predeterminado, llamado método, se utilizó para detectar círculos.codificación de fase Hay otro método, popularmente llamado el método, que está disponible en .dos etapasimfindcircles Utilice el método de dos etapas y muestre los resultados.

[centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', ...           'Sensitivity',0.92,'Method','twostage');  delete(h) h = viscircles(centers,radii);

El método de dos etapas está detectando más círculos, en la Sensibilidad de 0.92. En general, estos dos métodos son complementarios en que tienen diferentes fortalezas. El método de codificación de fase suele ser más rápido y ligeramente más robusto para el ruido que el método de dos etapas. Pero también puede necesitar niveles más altos de "sensibilidad" para obtener el mismo número de detecciones que el método de dos etapas. Por ejemplo, el método de codificación de fase también encuentra los mismos chips si el nivel de "Sensibilidad" se eleva más alto, por ejemplo, a 0,95.

[centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', ...           'Sensitivity',0.95);  delete(h) viscircles(centers,radii);

Tenga en cuenta que ambos métodos en la búsqueda de los centros y radios de los chips parcialmente visibles (ocluidos) con precisión.imfindcircles

Paso 7: ¿Por qué algunos círculos todavía se pierden?

Mirando el último resultado, es curioso que no encuentre los chips amarillos en la imagen.imfindcircles Las fichas amarillas no tienen un fuerte contraste con el fondo. De hecho, parecen tener intensidades muy similares a las del fondo. ¿Es posible que las fichas amarillas no sean realmente "más oscuras" que el fondo como se suponía? Para confirmar, vuelva a mostrar la versión en escala de grises de esta imagen.

imshow(gray_image)

Paso 8: Encontrar círculos 'brillantes' en la imagen

Las virutas amarillas son casi de la misma intensidad, tal vez incluso más brillantes, en comparación con el fondo. Por lo tanto, para detectar los chips amarillos, cambie 'ObjectPolarity' a 'bright'.

[centersBright,radiiBright] = imfindcircles(rgb,[20 25], ...     'ObjectPolarity','bright','Sensitivity',0.92);

Paso 9: Dibujar círculos 'brillantes' con diferentes colores

Dibuje los círculos en un color diferente, cambiando el parámetro 'Color' en .Brillanteviscircles

imshow(rgb)  hBright = viscircles(centersBright, radiiBright,'Color','b');

Tenga en cuenta que se encontraron tres de las fichas amarillas que faltan, pero todavía falta un chip amarillo. Estas fichas amarillas son difíciles de encontrar porque no lo hacen tan bien como otras en este fondo.destacar

Paso 10: Reduzca el valor de 'EdgeThreshold'

Hay otro parámetro en el que puede ser útil aquí, a saber, 'EdgeThreshold'.imfindcircles Para buscar círculos, solo utiliza los píxeles de borde de la imagen.imfindcircles Estos píxeles de borde son esencialmente píxeles con un valor de degradado alto. El parámetro 'EdgeThreshold' controla cómo debe ser el valor de degradado en un píxel antes de que se considere un píxel de borde y se incluya en el cálculo.Alto Un valor alto (más cercano a 1) para este parámetro permitirá incluir solo los bordes fuertes (valores de degradado más altos), mientras que un valor bajo (más cercano a 0) es más permisivo e incluye incluso los bordes más débiles (valores de degradado inferiores) en el cálculo. En el caso de que falte el chip amarillo, ya que el contraste es bajo, se espera que algunos de los píxeles de límite (en la circunferencia del chip) tengan valores de degradado bajos. Por lo tanto, baje el parámetro 'EdgeThreshold' para asegurarse de que la mayoría de los píxeles de borde para el chip amarillo se incluyen en el cálculo.

[centersBright,radiiBright,metricBright] = imfindcircles(rgb,[20 25], ...     'ObjectPolarity','bright','Sensitivity',0.92,'EdgeThreshold',0.1);  delete(hBright) hBright = viscircles(centersBright, radiiBright,'Color','b');

Paso 11: Dibujar círculos 'oscuros' y 'brillantes' juntos

Ahora encuentra todos los amarillos, y uno verde también.imfindcircles Dibuja estas fichas en azul, junto con las otras fichas que se encontraron anteriormente (con 'ObjectPolarity' establecido en 'dark'), en rojo.

h = viscircles(centers,radii);

Se detectan todos los círculos. Una última palabra - debe tenerse en cuenta que cambiar los parámetros para ser más agresivo en la detección puede encontrar más círculos, pero también aumenta la probabilidad de detectar círculos falsos. Hay un equilibrio entre el número de círculos verdaderos que se pueden encontrar (tasa de detección) y el número de círculos falsos que se encuentran con ellos (tasa de falsa alarma).

¡Feliz cacería!

Consulte también

|

Temas relacionados