4

OpenCV(OpenCV 2.3.1とPythonを使用しています)でcv.FindContours関数を使用して輪郭を作成するときに、輪郭の意味と保存される値を理解しようとしていました。テストには次の簡単な画像を使用しました。

ここに画像の説明を入力してください

輪郭を見つけた後、ipythonで次のコマンドを適用しました。

In [8]: contour
Out[8]: <cv2.cv.cvseq at 0x90a31a0>

In [10]: list(contour)
Out[10]: 
 [(256, 190),
  (255, 191),
  (112, 191),
  (255, 191),
  (256, 190),
  (257, 191),
  (257, 190)]

最初のコマンドは、contourはcvSeqオブジェクトであると言います。

画像にこれらのポイントをマークすると、次の画像が表示されます(赤いマークの付いた円がポイントです)。

ここに画像の説明を入力してください

どういう意味かわかりません。

だから私の質問は、2番目のコマンド(つまり、list(contour))の結果の値は何を示しているのですか?


編集:以下は私が使用したコードです。

import cv
img = cv.LoadImage('simple.jpeg')
imgg = cv.LoadImage('simple.jpeg',cv.CV_LOAD_IMAGE_GRAYSCALE)
storage = cv.CreateMemStorage(0)
contours = cv.FindContours(imgg,storage,cv.CV_RETR_TREE,cv.CV_CHAIN_APPROX_SIMPLE,(0,0))
print list(contours)
for i in list(contours):
    cv.Circle(img,i,5,(0,0,255),1)
cv.ShowImage('img',img)
cv.WaitKey(0)
4

2 に答える 2

4

list(contour)上記のmathically.coffeeによる回答に基づいて、輪郭について理解するために、の出力についてさらにいくつかの作業を行いました。

1)テスト画像を間違えました。バイナリ画像だと思いましたが、実際は他の色のグレースケール画像でもありました。(mathically.coffeeに感謝します)。そこで、画像を純粋な白黒のみの画像に変更して、輪郭を1つだけ取得し、再度テストしました。今回list(contour)は、4つの値の結果が得られました。これらの値は、画像に描画すると、そのボックスの4つの角になります。

問題の画像の新しい出力

したがって、「cv.DrawContours」関数を使用すると、これらすべての頂点を結ぶ線が描画されます。そこで、cv.FindContoursが、実際にはポリゴンである輪郭の頂点の位置を格納していると仮定しました。

2)もう一度テストするために、T字型の別の画像を撮りました。

test-image-2

このために、Tの8つのコーナーである8つの値のリストを期待します。

画像2の出力

`list(contour)'は、10個の値を含む次のリストを出力します。(2つの余分な値は、私の図面のエラーが原因である可能性があります)

[(92, 58), (92, 108), (174, 108), (175, 109), (175, 239), (225, 239), (225, 109), (226, 108), (285, 108), (285, 58)]

これは、cv.FindContoursがcvseqオブジェクトを作成することを意味します。その中に私が上で仮定したように値を保存します。

3)上記の例では、輪郭が1つだけ見つかります。複数の輪郭が見つかった場合の状態はどうなりますか?数学.coffeeで説明されているように、複数のリンクされたシーケンスの概念を明確に理解していませんでした。それをテストするために、私は3番目の画像を撮りました。

テスト画像3

これで、cv.FindContoursは3つの輪郭を検索します。各輪郭はボックスの4つの角のリストであることを忘れないでください。これらの3つのリストは、単一のcvseqオブジェクトに格納され、ポインタは最初の輪郭のみ、つまり最初のボックスの頂点のリストのみを指します。したがって、上記のコードでは、1つのボックスのコーナーのみが描画されます。

2番目の頂点のリストを取得するには、contour.h_next関数を使用します(mathically.coffeeのおかげで、今までその関数を知りませんでした)。これで、2番目のボックスの輪郭を指します。したがって、その中のすべてのリストを繰り返し処理します。

そこで、次のように単純なwhileループを追加しました。

while contours:
   print list(contours)
   for i in list(contours):
       cv.Circle(img,i,5,(0,0,255),3)
   contours = contours.h_next()

そして、私は3つのボックスのコーナーに対応する3つのリストを取得しました。

[(196, 237), (196, 279), (357, 279), (357, 237)]
[(141, 136), (141, 201), (346, 201), (346, 136)]
[(33, 39), (33, 92), (206, 92), (206, 39)]

そして出力画像:

画像3の出力

したがって、「頂点の数が多い」円の出力が期待できます。

さて、今はすべてが簡単です。等高線の値がわかりませんでした。だから、このすべての混乱。ありがとう。

更新-1:

cv2新しいモジュールの輪郭の詳細については、こちらをご覧ください:輪郭-1:はじめに

更新-2:

これらの説明はすべて、cv2.CHAIN_APPROX_SIMPLEに関して正しいものです。ただし、代わりにcv2.CHAIN_APPROX_NONEを使用すると、輪郭上のすべてのポイントが取得されます。この記事の例で詳細に説明されています:輪郭-5:階層

于 2012-01-30T15:22:14.903 に答える
4

わかりました、私はあなたの写真を見ました、そしてあなた各地域の頂点を手に入れています。私はcv2インターフェースを使用しているので、解決するのに少し時間がかかりましたcv

いくつかのこと:

  • 入力画像simple.jpegには、0と255以外に複数のグレースケール値が含まれています。これは、おそらくjpeg圧縮が原因です。
  • したがって、さまざまなグレーレベルに対して、から複数の領域を取得します。FindContours
  • cv.FindContours複数のリンクされたシーケンスを返します。すべてのecontourを取得するには、それらを反復処理する必要があります。
  • あなたがあなたの例のために出す輪郭は、境界線のものの1つです。

実例を示すために、すべての輪郭を描きましょう。

contours = cv.FindContours(imgg,storage,cv.CV_RETR_TREE,cv.CV_CHAIN_APPROX_SIMPLE,(0,0))
colours = [ (0,255,0,0),   # green
            (255,0,0,0),   # blue
            (255,255,0,0), # cyan
            (0,255,255,0), # yellow
            (255,0,255,0), # magenta
            (0,0,255,0)]   # red 
i=0
while contours:
    cv.DrawContours(img, contours, colours[i], colours[i], 0, thickness=-1)
    i = (i+1) % len(colours)
    contours = contours.h_next() # go to next contour
cv.ShowImage('img',img)
cv.WaitKey(0)

描かれた輪郭

したがって、元の質問で最初に使用した輪郭list(contours)は、正方形の下部にある小さな緑色の帯であり、取得した点はその頂点に対応していることがわかります。

長方形のエッジの周りとコーナーにこれらの奇妙な小さな輪郭がすべてある理由は、画像をJPEGとして保存することによって導入された圧縮アーティファクトの(おそらく)損失があるためです。正方形をロスレス形式(PNGやTIFFなど)で保存した場合、長方形の角で定義される輪郭は1つだけになります。

学んだ教訓:

  • cv.FindContours 各輪郭の「頂点」を提供します
  • contours = contours.h_next()各輪郭を反復処理する必要があります
  • JPEGとして保存すると、アーティファクトが発生します。代わりにTIFF/PNG /ロスレスのものを使用してください!
于 2012-01-30T09:05:56.617 に答える