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

Este ejemplo muestra cómo utilizar para detectar automáticamente círculos o 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 chips plásticos redondos 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 sucediendo en esta imagen desde un punto de vista de detección de círculo:

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

  2. Observe cómo algunos chips están uno encima del otro y otros que están cerca juntos y casi se tocan entre sí. Los límites de objetos solapados y la oclusión de objetos suelen ser escenarios desafiantes para la detección de objetos.

Paso 2: Determine 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 ajustarse 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 más grande de 20-25 píxeles sólo para estar seguro. Antes de eso, quite 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 o más 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 los chips son más oscuros que el fondo. Pero, de forma predeterminada, encuentra objetos circulares que son más brillantes que el fondo.imfindcircles Por lo tanto, establezca el parámetro ' ObjectPolarity ' en ' Dark ' para buscar círculos oscuros.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.imfindcirclesdetectorimfindcirclesdetection threshold En términos simples significa que la confianza del detector en una cierta detección (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 consecuentemente, la sensibilidad del algoritmo.validimfindcircles Un valor más alto de ' sensibilidad ' 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 del hogar.

Paso 4: aumente la sensibilidad de detección

Volviendo a la imagen del chip, es posible que en el nivel de sensibilidad predeterminado todos los círculos son más bajos que el umbral interno, por lo que no se detectaron círculos. De forma predeterminada, ' SENSITIVITY ', 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.1315  297.0081
  243.9893  166.4538
  271.5873  280.8920

radii = 8×1

   23.1604
   22.5710
   22.9576
   23.7356
   22.9551
   22.9929
   22.9055
   23.0298

Esta vez encontramos algunos círculos-ocho para ser precisos. contiene las ubicaciones de los centros circulares 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 colocados y sus radios correspondientes parecen coincidir bien con los chips reales. Pero todavía se perdieron algunas fichas. Intente aumentar la ' sensibilidad ' aún más, 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. Trace estos círculos en la imagen de nuevo.

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

Paso 6: Utilice el segundo método (dos etapas) para buscar 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 usó para detectar círculos.phase coding Hay otro método, popularmente llamado el método, que está disponible en.two-stageimfindcircles 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 por fases es típicamente más rápido y ligeramente más robusto al 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, digamos 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 para encontrar los centros y radios de los chips parcialmente visibles (ocludido) con precisión.imfindcircles

Paso 7: ¿por qué algunos círculos todavía están siendo extrañado?

Mirando el último resultado, es curioso que no encuentra los chips amarillos en la imagen.imfindcircles Los chips amarillos no tienen un fuerte contraste con el fondo. De hecho, parecen tener intensidades muy similares como el fondo. ¿Es posible que los chips amarillos no sean realmente ' más oscuros ' 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: encuentra círculos ' brillantes ' en la imagen

Los chips amarillos son casi la misma intensidad, tal vez incluso más brillante, 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: dibuja círculos ' brillantes ' con diferentes colores

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

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

Tenga en cuenta que tres de los chips amarillos faltantes fueron encontrados, pero todavía falta un chip amarillo. Estos chips amarillos son difíciles de encontrar porque no tan bien como otros en este fondo.stand out

Paso 10: baje el valor de ' EdgeThreshold '

Hay otro parámetro en el que puede ser útil aquí, a saber, ' EdgeThreshold '.imfindcircles Para buscar círculos, utiliza solo los píxeles del borde de la imagen.imfindcircles Estos píxeles de borde son esencialmente píxeles con alto valor de degradado. 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 e incluido en el cálculo.high Un valor alto (más cercano a 1) para este parámetro permitirá que solo se incluyan 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 más bajos) en el cálculo. En el caso del chip amarillo que falta, ya que el contraste es bajo, algunos de los píxeles de contorno (en la circunferencia del chip) se espera que tengan valores de gradiente bajos. Por lo tanto, baje el parámetro ' EdgeThreshold ' para asegurarse de que la mayor parte de los píxeles del 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: dibuja círculos ' oscuros ' y ' brillantes ' juntos

Ahora encuentra todos los amarillos, y uno verde también.imfindcircles Dibuje estos chips en azul, junto con los otros chips 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 intercambio 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 falsas alarmas).

¡ Feliz cacería de círculos!

Consulte también

|

Temas relacionados