Python OpenCVで円の検出を最適化する方法は?
How Optimize Circle Detection With Python Opencv
解決:
通常、円の検出は、しきい値処理+輪郭検出、ハフ円、輪郭フィッティングなどの従来の画像処理方法を使用して実行できますが、円は オーバーラップ/タッチ 、流域セグメンテーションの方が良い場合があります。ここに良いリソースがあります。
import cv2 import numpy as np from skimage.feature import Peak_local_max from skimage.morphology import watershed from scipy import ndimage#画像を読み込み、グレースケールに変換し、大津のしきい値画像= cv2.imread( '1.jpg')gray = cv2 .cvtColor(image、cv2.COLOR_BGR2GRAY)thresh = cv2.threshold(gray、0、255、cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]#輪郭領域を使用してフィルタリングすることにより小さなノイズを除去しますcnts = cv2.findContours(thresh、cv2 .RETR_TREE、cv2.CHAIN_APPROX_SIMPLE)cnts = cnts [0] if len(cnts)== 2 else cnts [1] for c in cnts:if cv2.contourArea(c)<1000: cv2.drawContours(thresh,[c], 0, (0,0,0), -1) cv2.imshow('thresh', thresh) # Compute Euclidean distance from every binary pixel # to the nearest zero pixel then find peaks distance_map = ndimage.distance_transform_edt(thresh) local_max = peak_local_max(distance_map, indices=False, min_distance=20, labels=thresh) # Perform connected component analysis then apply Watershed markers = ndimage.label(local_max, structure=np.ones((3, 3)))[0] labels = watershed(-distance_map, markers, mask=thresh) # Iterate through unique labels for label in np.unique(labels): if label == 0: continue # Create a mask mask = np.zeros(gray.shape, dtype='uint8') mask[labels == label] = 255 # Find contours and determine contour area cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] c = max(cnts, key=cv2.contourArea) cv2.drawContours(image, [c], -1, (36,255,12), -1) cv2.imshow('image', image) cv2.waitKey()
注意が必要な主なパラメータは次のとおりです。minDist、minRadiusとmaxRadius。
最初に半径を分析します。幅12円、高さ8円の画像があります。これにより、おおよその直径が得られます。各円の幅/ 12、または半径(幅/ 12)/ 2。使用した制約により、アルゴリズムは必要以上に大きいまたは小さい円を検出できるため、画像により適したパラメーター化を使用する必要があります。この場合、私は間隔を使用しました[0.9 *半径、1.1 *半径]。
重なりがないので、2つの円の間の距離は少なくとも直径であると言えます。minDistは次のように設定できます2 * minRadius。
この実装は基本的にあなたのものと同じですが、これらの3つのパラメーターを更新するだけです。
%matplotlib inline import cv2 import numpy as np import matplotlib.pyplot as plt image = cv2.imread( 'data / balls.jpg')output = image.copy()height、width = image.shape [:2] maxRadius = int (1.1 *(幅/ 12)/ 2)minRadius = int(0.9 *(幅/ 12)/ 2)灰色= cv2.cvtColor(画像、cv2.COLOR_BGR2GRAY)円= cv2.HoughCircles(画像=灰色、方法= cv2 .HOUGH_GRADIENT、dp = 1.2、minDist = 2 * minRadius、param1 = 50、param2 = 50、minRadius = minRadius、maxRadius = maxRadius)円がNoneでない場合:#円の(x、y)座標と半径をに変換しますintegers circlesRound = np.round(circles [0、:])。astype( 'int')#circlesRound:cv2.circle内の(x、y、r)の円の(x、y)座標と半径をループします(output、(x、y)、r、(0、255、0)、4)plt.imshow(output)else:print( '円が見つかりません')結果は次のとおりです。