2017-02-13 2 views
8

Je rencontre des problèmes pour détecter des zones de cercle. Je l'ai essayé avec la fonction HoughCircles d'opencv. Cependant, même si les images sont assez similaires, les paramètres de la fonction doivent être différents afin de détecter les cirles.python opencv - détection de blobs ou détection de cercle

Une autre approche que j'ai essayée était d'itérer sur chaque pixel et de vérifier si le pixel courant est blanc. Si c'est le cas, vérifiez s'il y a un objet blob dans la zone (distance au centre de blob inférieure à un seuil). Si c'est le cas, ajoutez le pixel au blob, sinon créez un nouveau blob. Cela n'a pas fonctionné correctement.

Quelqu'un at-il une idée de comment je peux faire ce travail (détection de 90%)? J'ai joint une image d'exemple et une autre image où j'ai marqué les cirles. Merci!

example

example with arrows

MISE À JOUR: Nous vous remercions de l'aide à ce jour! Ce est le code où je les contours et acquiers les filtrer par région:

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) 

Cela fonctionne assez propre. Je les ai dessiné sur l'image: contours_filtered_area

Ceci est la partie où je Filtré par circularité, il va directement en dessous du code où je filtre par zone:

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) 

Cependant, la nouvelle liste « contours_cirles » est vide. J'ai imprimé « circularité » dans la boucle et les valeurs sont tous entre 10 000 et 100 000.

MISE À JOUR # 2: Après avoir corrigé les supports manquants, il travaille maintenant!

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) 

Merci beaucoup les gars! :)

example_done

+0

Très ancien code. Mais vous pouvez vérifier cela. https://github.com/bipul21/Colored-Ball-Tracking –

+0

'(zone/périmètre * périmètre)' cela me semble étrange. Etes-vous sûr, vous n'avez pas oublié les crochets? – Moritz

+0

oui, vous avez raison. circularity = 4 * math.pi * (zone/(périmètre * périmètre)) – cmplx96

Répondre

4

Comme point de départ, vous pouvez commencer par:

  • Trouver tous les contours de l'image donnée à l'aide cv2.findContours()
  • itérer sur chaque contour:
    • calculer la superficie, si la zone de contour est dans une plage donnée, par exemple 70 < area < 150. Cela permettra de filtrer certains grands contours extrêmement petits et .
    • Après avoir filtré les contours avec le seuil de surface, vous devez vérifier le nombre d'arêtes du contour, ce qui peut être fait en utilisant: cv2.approxPolyDP(), pour un cercle len (environ) doit être> 8 mais < 23. Ou vous pouvez appliquer des opérations plus sophistiquées pour détecter des cercles ici.

Vous devriez essayer de mettre en œuvre cette approche et mettre à jour la question avec le code que vous écrirez désormais.

EDIT: Comme suggéré par @Miki, il existe un moyen meilleur et plus propre à détecter si une forme géométrique est de forme circulaire en utilisant circularité = 4pi (aire/périmètre^2), et décider d'un seuil comme 0.9, pour vérifier si la forme est circulaire. Pour un cercle parfait circularity == 1. Vous pouvez affiner ce seuil selon vos besoins.

Vous pouvez consulter arcLength pour trouver le périmètre du contour et contourArea pour obtenir l'aire du contour qui est nécessaire pour calculer la circularité.

+4

J'utiliserais _circularity_ pour mesurer à quel point une forme est un cercle: "La circularité est définie comme: A mesure la proximité d'un cercle par rapport à la forme, par exemple un hexagone régulier a une circularité plus élevée que par exemple un carré. (\ frac {4 * \ pi * Zone} {périmètre * périmètre}) Cela signifie qu'un cercle a une circularité de 1, la circularité d'un carré est de 0,785, et ainsi de suite. " – Miki

+1

Merci beaucoup @Miki – ZdaR

1

Nous pourrions essayer Hough Transformation aussi pour détecter les cercles dans l'image et de jouer avec les seuils pour obtenir le résultat souhaité (cercles détectés dans les lignes de démarcation vert avec des points rouges comme centres):

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() 

enter image description here