2017-05-08 3 views
0

J'essaie de détecter de petits cercles dans cette image recadrée à l'aide de houghcircles(). J'ai essayé de changer ses paramètres, mais il obtient des erreurs quand je param2 augmenter au-dessus de 50 et maxRadius reçoit aussi des erreurs lorsque sa valeur est inférieure à 100. Maintenant, il fonctionne mais avec une mauvaise performance Ceci est l'image originale: enter image description hereDétection de petits cercles à l'aide de houghCircles (OpenCV)

Et ceci est l'image de résultat: enter image description here

Et voici mon code:

from imutils.perspective import four_point_transform 
from imutils import contours 
import numpy as np 
import argparse 
import imutils 
import cv2 

im = cv2.imread('crop.png') 
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) 
ret,thresh = cv2.threshold(imgray, 200, 255,cv2.THRESH_BINARY) 
cimg = cv2.cvtColor(thresh,cv2.COLOR_GRAY2BGR) 

c = cv2.HoughCircles(thresh, cv2.HOUGH_GRADIENT, 0.5, 41, param1=70, 
param2=30, minRadius=10,maxRadius=175) 
c = np.uint16(np.around(c)) 

for i in c[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.namedWindow('img',cv2.WINDOW_NORMAL) 
cv2.resizeWindow('img', 800,800) 
cv2.imshow('img',cimg) 
cv2.waitKey(0) 
cv2.destroyAllWindows() 

S'il vous plaît, comment dois-je modifier les paramètres?

Répondre

2

Il vous faudra beaucoup de temps pour résoudre ceci si vous essayez de faire varier les paramètres sans comprendre ce qu'ils font.

Cette description est de here

minDist: Minimum distance between the center (x, y) coordinates of detected circles. If the minDist is too small, multiple circles in the same neighborhood as the original may be (falsely) detected. If the minDist is too large, then some circles may not be detected at all.

param1: Gradient value used to handle edge detection in the Yuen et al. method.

param2: Accumulator threshold value for the cv2.HOUGH_GRADIENT method. The smaller the threshold is, the more circles will be detected (including false circles). The larger the threshold is, the more circles will potentially be returned.

minRadius: Minimum size of the radius (in pixels).

maxRadius: Maximum size of the radius (in pixels).

Vous pouvez clairement voir que les cercles dans l'image ont un rayon fixe et ont min distance qui les sépare. Si vous définissez ces deux, vous pouvez améliorer vos résultats. Il est donc important de lire les documents.

Et à propos de votre problème, Si vous avez besoin d'utiliser spécifiquement Houghcircles allez-y et affinez-le. Les choses que vous pourriez faire pour améliorer sont, pré-traiter en utilisant gaussianblur, utilisez adaptivethreshold au lieu de simplement le seuil.

S'il n'est pas nécessaire d'utiliser des cercles Hough, je vous suggère plutôt d'utiliser des contours. Parce qu'il est plus robuste et généralise bien aux différentes images. Voici les résultats que j'ai obtenus en utilisant des contours. Les cercles apparaissent plus petits parce que j'ai utilisé l'érosion pour 6 itérations et la dilatation seulement pour 3 itérations.

finding circles using contours

Voici le code je.

import numpy as np 
import cv2 

image_color= cv2.imread("Ye3gs.png") 
image_ori = cv2.cvtColor(image_color,cv2.COLOR_BGR2GRAY) 

lower_bound = np.array([0,0,10]) 
upper_bound = np.array([255,255,195]) 

image = image_color 

mask = cv2.inRange(image_color, lower_bound, upper_bound) 

# mask = cv2.adaptiveThreshold(image_ori,255,cv2.ADAPTIVE_THRESH_MEAN_C,\ 
#    cv2.THRESH_BINARY_INV,33,2) 

kernel = np.ones((3, 3), np.uint8) 

#Use erosion and dilation combination to eliminate false positives. 
#In this case the text Q0X could be identified as circles but it is not. 
mask = cv2.erode(mask, kernel, iterations=6) 
mask = cv2.dilate(mask, kernel, iterations=3) 

closing = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) 

contours = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, 
     cv2.CHAIN_APPROX_SIMPLE)[0] 
contours.sort(key=lambda x:cv2.boundingRect(x)[0]) 

array = [] 
ii = 1 
print len(contours) 
for c in contours: 
    (x,y),r = cv2.minEnclosingCircle(c) 
    center = (int(x),int(y)) 
    r = int(r) 
    if r >= 6 and r<=10: 
     cv2.circle(image,center,r,(0,255,0),2) 
     array.append(center) 

cv2.imshow("preprocessed", image_color) 
cv2.waitKey(0) 

Hope this helps :)

+0

Merci d'aider, mais il me donne une erreur: 'contours.sort (key = lambda x: cv2.boundingRect (x) [0]) TypeError: ' clé » est un argument de mot-clé non valide pour cette fonction ' –

+1

Merci beaucoup, il a travaillé pour moi quand j'ai ajouté cette fonction 'def get_contour_precedence (contour, CLO): tolerance_factor = 10 origine = cv2.boundingRect (contour) retour ((origine [1] // tolerance_factor) * tolerance_factor) * cols + origine [0] ' –

+0

Je suggère d'utiliser les contours + minEnclosingC fonction de cercle, puis comparez la limite/surface du cercle avec le contour détecté pour filtrer les contours non circulaires – Micka