線がほぼ直線の場合は、ハフ変換を使用してすべての線を検索し、ハフ変換の円バージョンを使用してすべての円/楕円を検索します(境界の円/楕円が検出されたかどうか、およびどの線が内側にあるかを確認できます)たとえば)。
線が真っ直ぐでない場合:線ではなく「細長い領域」を意味しますよね?:)スケルトン化する必要があります(おそらく最初にしきい値)。役立つチュートリアル:「OpenCVを使用したスケルトン化-Python」。幅(=スケルトンからエッジまでの距離)も必要なので、skimage.morphology.medial_axis(...、return_distance = True)を使用します。また、各スケルトンのブランチを調べて短いブランチをトリミングする方法も必要になる可能性があります(すでにそれを行っている既製のものはありません、申し訳ありません)。
Haarタイプのアプローチはまったく機能せず、相対的な位置と形状が固定されているフィーチャでのみ(理論的にも)機能します。画像認識ではなく、ある種の幾何学的特徴抽出アルゴリズムが必要です。
編集: Pythonのサンプルコード:
import numpy, scipy, scipy.ndimage, skimage.morphology, matplotlib.pyplot
img = scipy.ndimage.imread("test.png")
# quick and dirty threshold
binary_img = img[:,:,0] < 0.1
# skeletonize
skel_binary, skel_distances = skimage.morphology.medial_axis(binary_img, return_distance=True)
# find individual lines
structure_element = scipy.ndimage.generate_binary_structure(2,2)
skel_labels, num_skel_labels = scipy.ndimage.measurements.label(skel_binary, structure=structure_element)
for n in range(1, num_skel_labels + 1):
# make a binary label for this line
line = (skel_labels == n)
# calculate width from skeleton
mean_width = 2 * numpy.mean( skel_distances[ line ] )
print "line %d: width %f" % (n, mean_width)
# you need some way to find the ends of a line
# perhaps the most distant pair of points?
# show the labels
# the circle is also labelled
# you need some way to check which label is the circle and exclude that
matplotlib.pyplot.imshow(skel_labels)
matplotlib.pyplot.show()
これにより、上記で投稿した画像、および(線の太さが機能することを確認するために)10倍に拡大されたバージョンの画像で妥当な結果が得られます。交差する線は処理しません。そのためにグラフアルゴリズムを実行できるかもしれません。また、何らかの方法で外側の円を除外する必要があります(ラベル付けは左上から行われ、最初にラベル付けされた領域が円であるため、常にn = 1のように見えます)。
編集:しきい値を設定する方法(または設定するかどうか)は興味深い質問です。おそらく大津の方法に基づいて、またはガウス混合に基づいて、自動しきい値処理を試すことができます(例)。背景と前景の色と明るさのある種の統計モデルを、局所的に適応可能なしきい値と組み合わせることで、おそらく最良の結果が得られると思います。本当にあなたの画像の性質に依存します。