Python Opencv – Detección de manchas o detección de círculos

Estoy teniendo problemas para detectar áreas circulares. Lo intenté con la función HoughCircles de opencv. Sin embargo, a pesar de que las imágenes son bastante similares, los parámetros para la función tienen que ser diferentes para detectar los círculos.

Otro enfoque que probé fue iterar sobre cada píxel y verificar si el píxel actual es blanco. Si este es el caso, verifique si hay un objeto de blob en el área (distancia al centro de blob más pequeño que un umbral). Si existe, agregue el píxel al blob, si no, cree un nuevo blob. Esto tampoco funcionó correctamente.

¿Alguien tiene una idea de cómo puedo hacer que esto funcione (detección del 90%)? Adjunté una imagen de ejemplo y otra imagen donde marqué los círculos. ¡Gracias!

ejemplo

ejemplo con flechas

ACTUALIZACIÓN: ¡ Gracias por la ayuda hasta ahora! Este es el código donde adquiero los contornos y los filtro por área:

im = cv2.imread('extract_blue.jpg') imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) im_gauss = cv2.GaussianBlur(imgray, (5, 5), 0) ret, thresh = cv2.threshold(im_gauss, 127, 255, 0) # get contours contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) contours_area = [] # calculate area and filter into new array for con in contours: area = cv2.contourArea(con) if 1000 < area < 10000: contours_area.append(con) 

Esto funciona bastante bien. Los dibujé en la imagen: contornos_filtrados_area

Esta es la parte donde filtré por circularidad, va directamente debajo del código donde filtro por área:

 contours_cirles = [] # check if contour is of circular shape for con in contours_area: perimeter = cv2.arcLength(con, True) area = cv2.contourArea(con) if perimeter == 0: break circularity = 4*math.pi*(area/perimeter*perimeter) print circularity if 0.8 < circularity < 1.2: contours_cirles.append(con) 

Sin embargo, la nueva lista ‘contours_cirles’ está vacía. Imprimí ‘circularidad’ en el bucle y los valores están entre 10 000 y 100 000.

ACTUALIZACIÓN # 2: ¡ Después de corregir los corchetes que faltan está funcionando ahora!

 contours_cirles = [] # check if contour is of circular shape for con in contours_area: perimeter = cv2.arcLength(con, True) area = cv2.contourArea(con) if perimeter == 0: break circularity = 4*math.pi*(area/(perimeter*perimeter)) print circularity if 0.7 < circularity < 1.2: contours_cirles.append(con) 

¡Muchas gracias chicos! 🙂

example_done

Como punto de partida puedes comenzar con:

  • Encuentra todos los contornos en la imagen dada usando cv2.findContours()
  • Iterar sobre cada contorno:
    • calcule el área, si el área del contorno está en un rango determinado, digamos 70 < area < 150 . Esto filtrará algunos contornos extremadamente pequeños y grandes.
    • Después de filtrar los contornos con el umbral del área, debe verificar el número de bordes del contorno, lo que se puede hacer usando: cv2.approxPolyDP() , para un círculo len (aproximado) debe ser> 8 pero <23. O puede Aplica algunas operaciones más sofisticadas para detectar círculos aquí.

Debe intentar implementar este enfoque y actualizar la pregunta con el código que escribirá a partir de ahora.

EDITAR: Como lo sugiere @Miki, hay una forma mejor y más limpia de detectar si una forma geométrica es de forma circular usando circularidad = 4pi (área / perímetro ^ 2) , y decidir un umbral como 0.9, para verificar si la forma es circular Para circularity == 1 perfecta círculo circularity == 1 . Puede ajustar este umbral según sus necesidades.

Puede consultar arcLength para encontrar el perímetro del contorno y contourArea para obtener el área del contorno que se requiere para calcular la circularidad.

También podríamos probar Hough Transformation para detectar los círculos en la imagen y jugar con los umbrales para obtener el resultado deseado (círculos detectados en las líneas de límite verdes con puntos rojos como centros):

 import cv2 import numpy as np img = cv2.imread('rbv2g.jpg',0) img = cv2.medianBlur(img,5) cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR) circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,10, param1=50,param2=12,minRadius=0,maxRadius=20) circles = np.uint16(np.around(circles)) for i in circles[0,:]: # draw the outer circle cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2) # draw the center of the circle cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3) cv2.imshow('detected circles',cimg) cv2.waitKey(0) cv2.destroyAllWindows() 

introduzca la descripción de la imagen aquí