2016-08-11 5 views
5

私は現在、このような画像のサークル検出を行っていますが、いくつかのドロップがマージしていくつかの不規則な形状(元画像の赤いマーク)を形成します。私はopencvで円を検出するためにhoughcircle関数を使用しています。これらの不規則な形状の場合、関数はいくつかの小さな円としてしか検出できませんが、実際に大きな形状の不規則な形状を考慮し、出力画像を描画するような大きな円を描きたいと思っています。houghcircle関数を使って不規則な形が検出されました。opencv python

Original image

Output image

私のコードは、すべての円を検出し、それらの直径を取得します。それでもHoughCircles機能を使用したい場合は、あなただけの二つの円が重なるかどうかを確認し、それらのうちの新しいサークルを作ることができ

def circles(filename, p1, p2, minR, maxR): 
# print(filename) 
img = cv2.imread(filename, 0) 
img = img[0:1000, 0:1360] 
l = len(img) 
w = len(img[1]) 

cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR) 

circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 25, 
          param1 = int(p1) ,param2 = int(p2), minRadius = int(minR), maxRadius = int(maxR)) 

diameter = open(filename[:-4] + "_diamater.txt", "w") 
diameter.write("Diameters(um)\n") 
for i in circles[0,:]: 
    diameter.write(str(i[2] * 1.29 * 2) + "\n") 

count = 0 
d = [] 
area = [] 
for i in circles[0,:]: 
    cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2) 
    cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3) 
    count += 1 
    d += [i[2]*2] 
    area += [i[2]*i[2]*pi*1.286*1.286] 

f = filename.split("/")[-1] 
cv2.imwrite(filename[:-4] + "_circle.jpg", cimg) 

# cv2.imwrite("test3/edge.jpg", edges) 
print "Number of Circles is %d" % count 

diaM = [] 
for i in d: 
    diaM += [i*1.286] 

bWidth = range(int(min(diaM)) - 10, int(max(diaM)) + 10, 2) 

txt = ''' 
Sample name: %s 
Average diameter(um): %f  std: %f 
Drop counts: %d 
Average coverage per drop(um^2): %f  std: %f 
''' % (f, np.mean(diaM), np.std(diaM), count, np.mean(area), np.std(area)) 

fig = plt.figure() 
fig.suptitle('Histogram of Diameters', fontsize=14, fontweight='bold') 
ax1 = fig.add_axes((.1,.4,.8,.5)) 
ax1.hist(diaM, bins = bWidth) 
ax1.set_xlabel('Diameter(um)') 
ax1.set_ylabel('Frequency') 
fig.text(.1,.1,txt) 
plt.savefig(filename[:-4] + '_histogram.jpg') 
plt.clf() 

print "Total area is %d" % (w*l) 
print "Total covered area is %d" % (np.sum(area)) 

rt = "Number of Circles is " + str(count) + "\n" + "Coverage percent is " + str(np.divide(np.sum(area), (w*l))) + "\n" 
return rt 

答えて

1

は、ここに私のコードです。

+0

直径によって

  • 赤字
  • 拡張モートンの広がりが、そこお互いのすぐ隣には他の多くのサークルがあります。それで、それはうまく動作しません。とにかくありがとう。 –

  • 1

    これにはminEnclosingCircleを使用できます。画像の輪郭を見つけて、その輪郭を円として検出する機能を適用します。

    以下は、C++コードを使用した簡単な例です。あなたのケースでは、ハフ・サークルとminEnclosingCircleの組み合わせを使用する必要があると感じます。イメージ内のいくつかの円は互いに非常に近いため、単一の輪郭として検出される可能性があります。

    入力画像:

    input

    円:

    output

    Mat im = imread("circ.jpg"); 
    Mat gr; 
    cvtColor(im, gr, CV_BGR2GRAY); 
    Mat bw; 
    threshold(gr, bw, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); 
    
    vector<vector<Point>> contours; 
    vector<Vec4i> hierarchy; 
    findContours(bw, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); 
    for(int idx = 0; idx >= 0; idx = hierarchy[idx][0]) 
    { 
        Point2f center; 
        float radius; 
        minEnclosingCircle(contours[idx], center, radius); 
    
        circle(im, Point(center.x, center.y), radius, Scalar(0, 255, 255), 2); 
    } 
    
    0

    あなたは、このような美しいよく分離と対比パターンを持っている場合は、最も簡単な方法は、形状インデックスを使用することです。 this paperまたはthis posterを参照してください。いずれの場合も、シェイプインデックスのリストがあります。

    おかげでインデックスを形作るために、あなたは何に従うことができます。

    • バイナリ画像
    • 各パターンに
    • 計算形状インデックスを分離するために(それらのほとんどは、基本的な対策を使用)
    • 連結成分のラベル付け
    • は、形状インデックス値に従ってパターンを分類します。

    ラウンド形状が完全にラウンドしている特定の場合のように、私は次のような形状のインデックスを使用します。

    • 円形=>ちょうど半径使って、あなたのケースで計算し、完璧にそう最も簡単。
    • あなたのケースでは完璧ですが、ミニボールの計算はすべてのライブラリで利用できるわけではありません。
    • 等視性欠損=>実際には計算が簡単ですが、周長のため円形度より少し安定しません。

    また、あなたのケースで動作します。

    • ギャップ内接ディスク
    • は、私はそのようにしようとした
    関連する問題