Tengo problemas para detectar áreas circulares. Lo probé con la función HoughCircles de opencv. Sin embargo, aunque las imágenes son bastante similares, los parámetros de la función deben 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 blob en el área (la distancia al centro del blob es menor que un umbral). Si lo hay, 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 (90% de detección)? Adjunté una imagen de ejemplo y otra imagen donde marqué los círculos. ¡Gracias!
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:
Esta es la parte donde filtré por circularidad, va directamente debajo del código donde filtré 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 ciclo y los valores están todos entre 10 000 y 100 000.
ACTUALIZACIÓN #2: ¡Después de corregir los corchetes que faltan, ahora está funcionando!
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! :)
Como punto de partida, puede comenzar con:
- Encuentre 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 dado, digamos
70 < area < 150
. Esto filtrará algunos contornos extremadamente pequeños y grandes.- Después de filtrar los contornos con el umbral de área, debe verificar la cantidad de bordes del contorno, lo que se puede hacer usando:
cv2.approxPolyDP()
, para un círculo, la longitud (aprox.) debe ser > 8 pero < 23. O puede aplique 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á de ahora en adelante.
EDITAR: como sugirió @Miki, hay una forma mejor y más limpia de detectar si una forma geométrica tiene forma circular usando circularity = 4pi(area/perimeter^2) , y decidir un umbral como 0.9, para verificar si la forma es circular Para 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 la Hough Transformation
para detectar los círculos en la imagen y jugar con los umbrales para obtener el resultado deseado (círculos detectados en 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()