web-dev-qa-db-ja.com

opencvを使用した堅牢な(色およびサイズ不変の)円検出の記述(ハフ変換またはその他の機能に基づく)

次の非常に簡単なpythonコードを書いて、画像内の円を見つけます。

import cv
import numpy as np

WAITKEY_DELAY_MS = 10
STOP_KEY = 'q'

cv.NamedWindow("image - press 'q' to quit", cv.CV_WINDOW_AUTOSIZE);
cv.NamedWindow("post-process", cv.CV_WINDOW_AUTOSIZE);

key_pressed = False
while key_pressed != STOP_KEY:

    # grab image
    orig = cv.LoadImage('circles3.jpg')

    # create tmp images
    grey_scale = cv.CreateImage(cv.GetSize(orig), 8, 1)
    processed = cv.CreateImage(cv.GetSize(orig), 8, 1)


    cv.Smooth(orig, orig, cv.CV_GAUSSIAN, 3, 3)

    cv.CvtColor(orig, grey_scale, cv.CV_RGB2GRAY)

    # do some processing on the grey scale image
    cv.Erode(grey_scale, processed, None, 10)
    cv.Dilate(processed, processed, None, 10)
    cv.Canny(processed, processed, 5, 70, 3)
    cv.Smooth(processed, processed, cv.CV_GAUSSIAN, 15, 15)

    storage = cv.CreateMat(orig.width, 1, cv.CV_32FC3)

    # these parameters need to be adjusted for every single image
    HIGH = 50
    LOW = 140

    try: 
        # extract circles
        cv.HoughCircles(processed, storage, cv.CV_HOUGH_GRADIENT, 2, 32.0, HIGH, LOW)

        for i in range(0, len(np.asarray(storage))):
            print "circle #%d" %i
            Radius = int(np.asarray(storage)[i][0][2])
            x = int(np.asarray(storage)[i][0][0])
            y = int(np.asarray(storage)[i][0][1])
            center = (x, y)

            # green dot on center and red circle around
            cv.Circle(orig, center, 1, cv.CV_RGB(0, 255, 0), -1, 8, 0)
            cv.Circle(orig, center, Radius, cv.CV_RGB(255, 0, 0), 3, 8, 0)

            cv.Circle(processed, center, 1, cv.CV_RGB(0, 255, 0), -1, 8, 0)
            cv.Circle(processed, center, Radius, cv.CV_RGB(255, 0, 0), 3, 8, 0)

    except:
        print "nothing found"
        pass

    # show images
    cv.ShowImage("image - press 'q' to quit", orig)
    cv.ShowImage("post-process", processed)

    cv_key = cv.WaitKey(WAITKEY_DELAY_MS)
    key_pressed = chr(cv_key & 255)

次の2つの例からわかるように、「円の検出品質」は非常に大きく異なります。

ケース1:

input1detection1post-processed1

CASE2:

input2detection2post-processed2

Case1とCase2は基本的に同じ画像ですが、それでもアルゴリズムは異なる円を検出します。異なるサイズの円を含む画像をアルゴリズムに提示すると、円の検出が完全に失敗することさえあります。これは主に、新しい画像ごとに個別に調整する必要があるHIGHおよびLOWパラメータによるものです。

したがって私の質問:このアルゴリズムをより堅牢にするさまざまな可能性は何ですか?異なる色と異なるサイズの異なる円が検出されるように、サイズと色が不変である必要があります。ハフ変換を使用することは、物事を行う最良の方法ではないでしょうか?より良いアプローチはありますか?

47
memyself

以下は、視覚研究者としての私の経験に基づいています。あなたの質問から、機能するコードだけではなく、可能なアルゴリズムと方法に興味があるようです。最初に、サンプル画像用の手っ取り早い汚いPythonスクリプトと、問題を解決できる可能性があることを証明するための結果をいくつか示します。堅牢な検出アルゴリズムに関する。

クイック結果

検出された円を含むいくつかのサンプル画像(あなた以外のすべての画像はflickr.comからダウンロードされ、CCライセンスされています)(パラメーターを変更/調整せずに、すべての画像の円を抽出するために正確に次のコードが使用されます): detected blobs in the sample image 1detected blobs in the sample image 2lots of circlesblobs in the flickr image 1

コード(MSER Blob Detectorに基づく)

そして、ここにコードがあります:

import cv2
import math
import numpy as np

d_red = cv2.cv.RGB(150, 55, 65)
l_red = cv2.cv.RGB(250, 200, 200)

orig = cv2.imread("c.jpg")
img = orig.copy()
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

detector = cv2.FeatureDetector_create('MSER')
fs = detector.detect(img2)
fs.sort(key = lambda x: -x.size)

def supress(x):
        for f in fs:
                distx = f.pt[0] - x.pt[0]
                disty = f.pt[1] - x.pt[1]
                dist = math.sqrt(distx*distx + disty*disty)
                if (f.size > x.size) and (dist<f.size/2):
                        return True

sfs = [x for x in fs if not supress(x)]

for f in sfs:
        cv2.circle(img, (int(f.pt[0]), int(f.pt[1])), int(f.size/2), d_red, 2, cv2.CV_AA)
        cv2.circle(img, (int(f.pt[0]), int(f.pt[1])), int(f.size/2), l_red, 1, cv2.CV_AA)

h, w = orig.shape[:2]
vis = np.zeros((h, w*2+5), np.uint8)
vis = cv2.cvtColor(vis, cv2.COLOR_GRAY2BGR)
vis[:h, :w] = orig
vis[:h, w+5:w*2+5] = img

cv2.imshow("image", vis)
cv2.imwrite("c_o.jpg", vis)
cv2.waitKey()
cv2.destroyAllWindows()

ご覧のとおり、これは [〜#〜] mser [〜#〜] blob Detectorに基づいています。コードは、グレースケールへの単純なマッピングを除き、画像を前処理しません。したがって、画像にこれらのかすかな黄色の塊がないことが予想されます。

理論

簡単に言うと、2つのサンプル画像だけを提供し、それらの説明を付けないこと以外は、問題について知っていることを教えてはなりません。ここで、私が謙虚な意見で、問題を攻撃するための効率的な方法を尋ねる前に、問題についてより多くの情報を得ることが重要である理由を説明します。

主な質問に戻ります。この問題の最良の方法は何ですか?これを検索の問題として見てみましょう。議論を簡単にするために、特定のサイズ/半径の円を探していると仮定します。したがって、問題はセンターを見つけることに要約されます。すべてのピクセルは候補中心であるため、検索スペースにはすべてのピクセルが含まれます。

P = {p1, ..., pn} 
P: search space
p1...pn: pixels

この検索問題を解決するには、他の2つの関数を定義する必要があります。

E(P) : enumerates the search space
V(p) : checks whether the item/pixel has the desirable properties, the items passing the check are added to the output list

アルゴリズムの複雑さは重要ではないと仮定すると、Eがすべてのピクセルを取得してVに渡す徹底的検索または総当たり検索を使用できます。リアルタイムアプリケーションでは、検索スペースを削減し、Vの計算効率を最適化することが重要です。

主な質問に近づいています。 Vを定義する方法、より正確に候補の特性を測定する方法、および候補を望ましいものと望ましくないものに分割する二分法の問題を解決する方法。最も一般的なアプローチは、プロパティの測定に基づいて単純な決定ルールを定義するために使用できるいくつかのプロパティを見つけることです。これはあなたが試行錯誤をしていることです。肯定的な例と否定的な例から学習することにより、分類器をプログラミングしています。これは、使用しているメソッドが何をしたいかわからないためです。二分法問題の方法で使用される(望ましい候補の)プロパティの変動が小さくなるように、決定ルールのパラメーターを調整/調整し、データを前処理する必要があります。機械学習アルゴリズムを使用して、特定のサンプルセットの最適なパラメーター値を見つけることができます。この問題に使用できる決定木から遺伝的プログラミングまで、学習アルゴリズムは多数あります。また、学習アルゴリズムを使用して、複数の円検出アルゴリズムの最適なパラメーター値を見つけ、どれがより正確かを確認することもできます。これは、サンプル画像を収集するために必要な学習アルゴリズムの主な負担となります。

しばしば見落とされがちな堅牢性を改善する他のアプローチは、簡単に入手できる余分な情報を利用することです。実質的に余分な手間をかけずに円の色を知っていれば、検出器の精度を大幅に改善できます。平面上の円の位置を知っていて、画像化された円を検出したい場合は、これら2つの位置セット間の変換が2Dホモグラフィによって記述されることを覚えておく必要があります。また、ホモグラフィは4つのポイントのみを使用して推定できます。次に、堅牢性を改善して、堅実な方法を使用できます。ドメイン固有の知識の価値はしばしば過小評価されています。このように見てください。最初のアプローチでは、限られた数のサンプルに基づいていくつかの決定ルールを近似しようとします。 2番目のアプローチでは、決定ルールを知っており、それらをアルゴリズムで効果的に利用する方法を見つける必要があります。

概要

まとめると、ソリューションの精度/堅牢性を改善するための2つのアプローチがあります。

  1. ツールベース:より使いやすいアルゴリズムを見つける/より少ないパラメーター数で/アルゴリズムを調整する/機械学習アルゴリズムを使用してこのプロセスを自動化する
  2. 情報ベース:すぐに入手できる情報をすべて使用していますか?質問では、問題について知っていることについては言及しません。

共有したこれらの2つの画像には、HTメソッドではなくblob検出器を使用します。背景の減算では、円の色は変化するが変化しない2つの画像のように、背景の色を推定することをお勧めします。そして、ほとんどの領域がむき出しになっています。

36
fireant

これは素晴らしいモデリングの問題です。次の推奨事項/アイデアがあります。

  1. 画像をRGBに分割してから処理します。
  2. 前処理。
  3. 動的パラメーター検索。
  4. 制約を追加します。
  5. 検出しようとしているものについて確認してください。

さらに詳細に:

1:他の回答で述べたように、グレースケールにストレートに変換すると、多くの情報が破棄されます-背景と同じ明るさの円は失われます。カラーチャネルを単独で、または別のカラースペースで検討することをお勧めします。ここには、2つの方法があります。前処理された各チャネルで単独でHoughCirclesを実行し、結果を結合するか、チャネルを処理してから結合し、HoughCirclesを操作します。以下の試みでは、RGBチャンネルに分割し、処理してから結合する2番目の方法を試しました。結合する際に画像が飽和しすぎることに注意してください。cv.Andを使用してこの問題を回避します(この段階では、私の円は常に白い背景の黒いリング/ディスクです)。

2:前処理は非常に注意が必要です。多くの場合、これをいじるのが最善です。 AdaptiveThresholdを使用しました。これは、ローカル平均に基づいてピクセルのしきい値を設定することにより、画像のエッジを強調できる非常に強力な畳み込み手法です(哺乳類の視覚システムの初期経路でも同様のプロセスが発生します)。これは、ノイズを減らすためにも役立ちます。 dilate/erodeを1回のパスで使用しました。そして、私はあなたがそれらを持っている方法の他のパラメータを保持しました。 Cannyの前にHoughCirclesを使用すると、「塗りつぶされた円」を見つけるのに大いに役立つので、おそらくそれを維持するのが最善です。この前処理はかなり重く、やや誤検知につながる可能性がありますより多くの「ブロブサークル」ですが、私たちの場合、これはおそらく望ましいですか?

3:HoughCirclesのパラメーターparam2(パラメーターLOW)に注意したように、実際には から最適なソリューションを得るために画像ごとに調整する必要がありますdocs

小さいほど、より多くの偽の円が検出される可能性があります。

問題は、画像ごとにスイートスポットが異なることです。ここでの最良のアプローチは、条件を設定し、この条件が満たされるまで異なるparam2値を検索することだと思います。画像には重ならない円が表示され、param2が低すぎると、重なる円の負荷が通常発生します。そこで、以下を検索することをお勧めします。

重複しない、含まれていない円の最大数

したがって、これが満たされるまで、param2の異なる値でHoughCirclesを呼び出し続けます。以下の例では、param2をしきい値の仮定に達するまでインクリメントするだけでこれを行います。バイナリ検索を実行してこれが満たされた場合を見つけると、はるかに高速になります(かなり簡単になります)が、opencvはparam2の無害な値に対してエラーをスローすることが多いため、例外処理に注意する必要があります(少なくとも私のインストールでは)。一致させるのに非常に役立つ別の条件は、円の数です。

4:モデルに追加できる制約はありますか?モデルに伝えることができるものが多くなればなるほど、サークルを検出するためのタスクを簡単に行うことができます。たとえば、次のことを知っていますか?

  • サークルの数。 -上限または下限も役立ちます。
  • 円、背景、または「非円」の可能な色。
  • サイズ。
  • 画像内のどこにあるか。

5:画像内の一部のブロブは、おおまかに円としか呼べません! 2番目の画像の2つの「非円形の塊」を考えてみましょう、私のコードはそれらを見つけることができません(良い!)、しかし...私がそれらを「フォトショップ」してより円形にすると、私のコードはそれらを見つけることができます...円ではないものを検出したい場合は、Tim Lukinsなどの別のアプローチの方が良いかもしれません。

問題

重い前処理AdaptiveThresholdingと `Canny 'を実行すると、画像内のフィーチャに多くの歪みが発生する可能性があり、誤った円の検出や誤った半径の報告につながる可能性があります。たとえば、処理後の大きな固体ディスクはリングに見える可能性があるため、HughesCirclesは内側のリングを見つけることができます。さらに、ドキュメントでも次のことに注意してください。

...通常、関数は円の中心を適切に検出しますが、正しい半径を見つけることができない場合があります。

より正確な半径検出が必要な場合は、次のアプローチを推奨します(実装されていません):

  • 元の画像で、報告された円の中心からの光線追跡、拡大する十字線(4本の光線:上/下/左/右)
  • これを各RGBチャンネルで個別に行います
  • 賢明な方法で各光線の各チャネルのこの情報を組み合わせます(つまり、必要に応じて反転、オフセット、スケールなど)。
  • 各光線の最初の数ピクセルの平均値を取得し、これを使用して光線に大きな偏差が発生する場所を検出します。
  • これらの4つのポイントは、円周上のポイントの推定値です。
  • これらの4つの推定値を使用して、より正確な半径と中心位置(!)を決定します。
  • これは、4つの光線の代わりに拡張リングを使用することで一般化できます。

結果

終了時のコードは非常に多くの場合非常によく機能します。これらの例は、次のようにコードを使用して行われました。

最初の画像のすべての円を検出します:enter image description here

キャニーフィルターが適用される前の前処理画像の外観(異なる色の円が非常に目立ちます):enter image description here

2番目の画像で2つ(blob)を除くすべてを検出します。enter image description here

変更された2番目の画像(blobは円になり、大きな楕円形はより円形になり、検出が改善されます)、すべて検出されました: enter image description here

このカンディンスキーの絵の中心を検出するのに非常にうまくいきます(境界条件のために同心円を見つけることができません)。 enter image description here

コード:

import cv
import numpy as np

output = cv.LoadImage('case1.jpg')
orig = cv.LoadImage('case1.jpg')

# create tmp images
rrr=cv.CreateImage((orig.width,orig.height), cv.IPL_DEPTH_8U, 1)
ggg=cv.CreateImage((orig.width,orig.height), cv.IPL_DEPTH_8U, 1)
bbb=cv.CreateImage((orig.width,orig.height), cv.IPL_DEPTH_8U, 1)
processed = cv.CreateImage((orig.width,orig.height), cv.IPL_DEPTH_8U, 1)
storage = cv.CreateMat(orig.width, 1, cv.CV_32FC3)

def channel_processing(channel):
    pass
    cv.AdaptiveThreshold(channel, channel, 255, adaptive_method=cv.CV_ADAPTIVE_THRESH_MEAN_C, thresholdType=cv.CV_THRESH_BINARY, blockSize=55, param1=7)
    #mop up the dirt
    cv.Dilate(channel, channel, None, 1)
    cv.Erode(channel, channel, None, 1)

def inter_centre_distance(x1,y1,x2,y2):
    return ((x1-x2)**2 + (y1-y2)**2)**0.5

def colliding_circles(circles):
    for index1, circle1 in enumerate(circles):
        for circle2 in circles[index1+1:]:
            x1, y1, Radius1 = circle1[0]
            x2, y2, Radius2 = circle2[0]
            #collision or containment:
            if inter_centre_distance(x1,y1,x2,y2) < Radius1 + Radius2:
                return True

def find_circles(processed, storage, LOW):
    try:
        cv.HoughCircles(processed, storage, cv.CV_HOUGH_GRADIENT, 2, 32.0, 30, LOW)#, 0, 100) great to add circle constraint sizes.
    except:
        LOW += 1
        print 'try'
        find_circles(processed, storage, LOW)
    circles = np.asarray(storage)
    print 'number of circles:', len(circles)
    if colliding_circles(circles):
        LOW += 1
        storage = find_circles(processed, storage, LOW)
    print 'c', LOW
    return storage

def draw_circles(storage, output):
    circles = np.asarray(storage)
    print len(circles), 'circles found'
    for circle in circles:
        Radius, x, y = int(circle[0][2]), int(circle[0][0]), int(circle[0][1])
        cv.Circle(output, (x, y), 1, cv.CV_RGB(0, 255, 0), -1, 8, 0)
        cv.Circle(output, (x, y), Radius, cv.CV_RGB(255, 0, 0), 3, 8, 0)

#split image into RGB components
cv.Split(orig,rrr,ggg,bbb,None)
#process each component
channel_processing(rrr)
channel_processing(ggg)
channel_processing(bbb)
#combine images using logical 'And' to avoid saturation
cv.And(rrr, ggg, rrr)
cv.And(rrr, bbb, processed)
cv.ShowImage('before canny', processed)
# cv.SaveImage('case3_processed.jpg',processed)
#use canny, as HoughCircles seems to prefer ring like circles to filled ones.
cv.Canny(processed, processed, 5, 70, 3)
#smooth to reduce noise a bit more
cv.Smooth(processed, processed, cv.CV_GAUSSIAN, 7, 7)
cv.ShowImage('processed', processed)
#find circles, with parameter search
storage = find_circles(processed, storage, 100)
draw_circles(storage, output)
# show images
cv.ShowImage("original with circles", output)
cv.SaveImage('case1.jpg',output)

cv.WaitKey(0)
28
fraxel

ああ、はい...円問題の古い色/サイズ不変式(別名ハフ変換はあまりにも具体的で堅牢ではありません)...

以前は、OpenCVの 構造および形状分析 関数にはるかに依存してきました。可能性のある「samples」フォルダから非常に良いアイデアを得ることができます-特にfitellipse.pyおよびsquares.py

説明のために、これらの例のハイブリッドバージョンを、元のソースに基づいて提示します。検出された輪郭は緑色で、適合した楕円は赤色で表示されます。

enter image description here

まだ完全ではありません:

  • 前処理ステップでは、より弱い円を検出するために少し調整する必要があります。
  • 輪郭をさらにテストして、円かどうかを判断できます...

がんばろう!

import cv
import numpy as np

# grab image
orig = cv.LoadImage('circles3.jpg')

# create tmp images
grey_scale = cv.CreateImage(cv.GetSize(orig), 8, 1)
processed = cv.CreateImage(cv.GetSize(orig), 8, 1)

cv.Smooth(orig, orig, cv.CV_GAUSSIAN, 3, 3)

cv.CvtColor(orig, grey_scale, cv.CV_RGB2GRAY)

# do some processing on the grey scale image
cv.Erode(grey_scale, processed, None, 10)
cv.Dilate(processed, processed, None, 10)
cv.Canny(processed, processed, 5, 70, 3)
cv.Smooth(processed, processed, cv.CV_GAUSSIAN, 15, 15)

#storage = cv.CreateMat(orig.width, 1, cv.CV_32FC3)
storage = cv.CreateMemStorage(0)

contours = cv.FindContours(processed, storage, cv.CV_RETR_EXTERNAL)
# N.B. 'processed' image is modified by this!

#contours = cv.ApproxPoly (contours, storage, cv.CV_POLY_APPROX_DP, 3, 1) 
# If you wanted to reduce the number of points...

cv.DrawContours (orig, contours, cv.RGB(0,255,0), cv.RGB(255,0,0), 2, 3, cv.CV_AA, (0, 0)) 

def contour_iterator(contour):
  while contour:
    yield contour
    contour = contour.h_next()

for c in contour_iterator(contours):
  # Number of points must be more than or equal to 6 for cv.FitEllipse2
  if len(c) >= 6:
    # Copy the contour into an array of (x,y)s
    PointArray2D32f = cv.CreateMat(1, len(c), cv.CV_32FC2)

    for (i, (x, y)) in enumerate(c):
      PointArray2D32f[0, i] = (x, y)

    # Fits ellipse to current contour.
    (center, size, angle) = cv.FitEllipse2(PointArray2D32f)

    # Convert ellipse data from float to integer representation.
    center = (cv.Round(center[0]), cv.Round(center[1]))
    size = (cv.Round(size[0] * 0.5), cv.Round(size[1] * 0.5))

    # Draw ellipse
    cv.Ellipse(orig, center, size, angle, 0, 360, cv.RGB(255,0,0), 2,cv.CV_AA, 0)

# show images
cv.ShowImage("image - press 'q' to quit", orig)
#cv.ShowImage("post-process", processed)
cv.WaitKey(-1)

編集:

これらすべての答えの主なテーマは、circular 。私自身の答えは、低レベルの前処理でも高レベルの幾何学的フィッティングでも、これを装っていません。多くの円は、描画方法や画像の非アフィン/投影変換、およびレンダリング/キャプチャ方法の他のプロパティ(色、ノイズ、照明、エッジの厚さ)-すべて1つの画像内に任意の数の候補円ができます。

より高度な技術があります。しかし、彼らはあなたに費用がかかります。個人的には、アダプティブしきい値を使用する@fraxelのアイデアが好きです。これは、高速で信頼性が高く、かなり堅牢です。次に、楕円軸の単純な比率テストを使用して、最終輪郭(たとえば、Huモーメントを使用)またはフィッティングをさらにテストできます。 if((min(size)/ max(size))> 0.7)。

これまでと同じように、Computer Visionには、プラグマティズム、原則、およびs音の間の緊張があります。私は、CVは簡単だと思う人に話すのが好きなので、そうではありません。実際、有名なのは AI complete 問題です。これ以外でよく期待できるのは、ほとんどの場合うまくいくものです。

12
tiluki

コードを見ると、次のことに気付きました。

  • グレースケール変換。私はあなたがそれをしている理由を理解していますが、あなたがそこに情報を捨てていることを理解しています。 「後処理」画像に見られるように、黄色の円は背景と同じ強度であり、色が異なっています。

  • ノイズ除去後のエッジ検出(消去/膨張)。これは必要ないはずです。キャニーはこれを大事にするべきです。

  • キャニーエッジの検出。 「開いた」円には、内側と外側の2つのエッジがあります。それらはかなり近いため、Canny gaussフィルターはそれらを一緒に追加する場合があります。そうでない場合は、2つのエッジが互いに近くなります。つまりキャニーの前に、あなたは開いて塗りつぶされた円を持っています。その後、それぞれ0/2と1つのエッジがあります。ハフは再びキャニーを呼び出すため、最初のケースでは、2つのエッジが(初期幅に応じて)滑らかになります。これが、コアハフアルゴリズムが開いた円と塗りつぶされた円を同じように処理できる理由です。

したがって、最初の推奨事項は、グレースケールマッピングを変更することです。強度を使用せず、色相/彩度/値を使用します。また、差分アプローチを使用します-エッジを探しています。したがって、HSV変換を計算し、コピーを平滑化してから、元のコピーと平滑化されたコピーの差を取ります。これにより、dH, dS, dV値(各点の色相、彩度、値の局所変動)。すべてのエッジ(内側と外側)の近くにピークがある、1次元画像を取得するために四角と足します。

2番目の推奨事項はローカル正規化ですが、それが必要かどうかはわかりません。アイデアは、出たEdge信号の正確な値を特に気にする必要はないということです。とにかく実際にはバイナリである必要があります(Edgeかどうか)。したがって、ローカル平均(ローカルはEdgeサイズの大きさ)で割ることにより、各値を正規化できます。

9
MSalters

ハフ変換は、「モデル」を使用して、ご存知のように(通常)エッジ検出画像の特定の特徴を見つけます。 HoughCirclesの場合、そのモデルは完全な円です。これは、おそらく、誤検出の数を増やすことなく、画像内のより不規則で楕円形の円を検出するパラメーターの組み合わせが存在しないことを意味します。一方、基本的な投票メカニズムにより、閉じていない完全な円または「へこみ」のある完全な円が一貫して表示される場合があります。そのため、期待される出力に応じてこのメソッドを使用する場合と使用しない場合があります。

そうは言っても、この機能を使用する際に役立つ可能性のあることがいくつかあります。

  1. HoughCirclesは内部でCannyを呼び出します。そのため、その呼び出しは省略できます。
  2. _param1_(HIGHと呼びます)は通常、_200_の値を中心に初期化されます。 Cannycv.Canny(processed, cannied, HIGH, HIGH/2)への内部呼び出しのパラメーターとして使用されます。このように自分でCannyを実行すると、HIGHの設定がHough変換で処理されるイメージにどのように影響するかを確認するのに役立つ場合があります。
  3. _param2_(LOWと呼ぶ)は通常、値_100_を中心に初期化されます。これは、ハフ変換のアキュムレーターの投票しきい値です。高く設定すると、偽陰性が多くなり、偽陽性が少なくなります。あなたがいじり始めたいのはこれが最初だと思います。

参照: http://docs.opencv.org/3.0-beta/modules/imgproc/doc/feature_detection.html#houghcircles

更新:塗りつぶされた円:ハフ変換で円の形状が見つかったら、境界色をサンプリングして比較することで塗りつぶされているかどうかをテストできます想定される円内の1つまたは複数のポイントへ。または、想定される円内の1つ以上のポイントを特定の背景色と比較できます。前の比較が成功した場合は円が塗りつぶされ、失敗した場合は代替比較の場合は塗りつぶされます。

6
Eric

画像を見てください。 **Active Contours**を使用することをお勧めします

  • アクティブな輪郭 アクティブな輪郭の良いところは、与えられた形状にほぼ完全に適合することです。正方形でも三角形でも、あなたの場合は完璧な候補です。
  • 円の中心を抽出できれば、それは素晴らしいことです。アクティブな輪郭は、開始するポイントを常に必要とし、そこからフィットするように拡大または縮小できます。センターが常にセンターに揃っている必要はありません。少しのオフセットでも大丈夫です。
  • そして、あなたの場合、輪郭を中心から外側に向かって成長させると、円の境界線上に置かれます。
  • 成長または収縮するアクティブな輪郭は バルーンエネルギー を使用することに注意してください。つまり、輪郭の方向を内側または外側に設定できます。
  • おそらく、グレースケールのグラデーション画像を使用する必要があります。それでも、色で試してみることができます。うまくいけば!
  • また、中心を提供しない場合は、アクティブな輪郭をたくさん入れてから、拡大/縮小します。落ち着いた輪郭は維持され、不安定な輪郭は捨てられます。これはブルートフォースアプローチです。 CPUを集中的に使用します。ただし、正しい輪郭を残して、悪い輪郭を捨てるには、より注意深い作業が必要になります。

この方法で問題を解決できることを願っています。

2
user349026