web-dev-qa-db-ja.com

Python / Opencvを使用してバイナリイメージの破線を接続する方法

これらの線をターゲットポイントで接続するにはどうすればよいですか?画像はスケルトン化プロセスの結果です。

Resulting Image From Skeletonization

Points That I Need To Connect

Watershed Transformを使用して、各ラインを領域としてセグメント化しようとしています。

10
Thiago Resende

MikeE の答えは非常に優れています。膨張と収縮のモルフォロジー演算を使用すると、このコンテキストで多くの助けになります。
手元にある画像の特定の構造を利用して、少し改善を提案したいと思います。一般的なカーネルで膨張/収縮を使用する代わりに、水平カーネルを使用して、水平線の端点を接続しますが、隣接するカーネルは接続しませんお互いに線。

以下はコードのスケッチです(入力画像がbw numpy 2D配列に格納されていると仮定しています):

import cv2, numpy as np

kernel = np.ones((1,20), np.uint8)  # note this is a horizontal kernel
d_im = cv2.dilate(bw, kernel, iterations=1)
e_im = cv2.erode(d_im, kernel, iterations=1) 

あなたが得るものは膨張した画像です:
enter image description here

明確な水平線を維持しながら、ギャップがどのように閉じているかに注意してください

そして侵食された画像:
enter image description here

拡張/収縮によって作成されたアーティファクトを削除するには、スケルトンをもう一度抽出することをお勧めします。
侵食された画像にスケルトンのモルフォロジー演算をさらに適用すると、次の結果が得られます。
enter image description here

カーブを接続したら、流域セグメンテーションを使用する必要はありませんが、接続されたコンポーネントを使用して各カーブにラベルを付けます。

12
Shai

画像はすでに単色なので、モルフォロジー変換を使用して破線を閉じることができます。

例が必要な場合は、 http://docs.opencv.org/2.4/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.html#closing のドキュメントに例があります。

これは、最初に画像の白い領域を拡張し、次に同じ量を侵食することで機能します。白い領域の穴を効果的に塞ぐ。詳細と例はここにあります: http://docs.opencv.org/2.4/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html

この戦略では、破線のギャップが隣接する線間の距離よりも小さいことが必要です。

線が交差している場合、または線が互いに近すぎる場合は機能しません。しかし、私はあなたの例ではかなりうまくいくと思います。

関数erodeを使用して、3行目より下のアーティファクトを削除することもできます。

4
Mike E

私は同様の問題に取り組んでいますが、それはより複雑であり、いくつかのスポットでは線が非常に近いため、形態学的変換がそれらをマージすることになります。誰か他の方法を知っている場合は提案してください。前もって感謝します!

あなたの問題に来る。モルフォロジー演算も必要ないでしょう。すでに画像のスケルトンを作成しているので、距離とスロープ(微分)を基準として使用して、線が壊れる点を検出し、それらの点を結合するカーネルを設計できます。 100%動作するかどうかはわかりませんが、試してみてください。

0
Devansh Sharma