4

円/楕円形の内側の線のような特徴を認識するアプリケーションに取り組んでいます。形状は次のようになります(ここに2つ表示されています)。

形

  • 形状自体は、円と楕円の間でわずかに異なる場合があります。
  • 図形の内側には最大5つの線があり、すべての図形のほぼ同じ領域にあります。
  • これらの線は、長さ、太さ、回転、および曲率がわずかに異なる場合があります。
  • 線がわずかに接触/交差する場合があります。
  • 通常は正確に5つありますが、行が完全に欠落している場合もあります。
  • 私は色を気にしません、白黒のしきい値は問題ありません。

(100以上の)各​​オブジェクトは、ビデオによって個別にキャプチャされます。キャプチャは手動/物理プロセスです(つまり、毎回カメラを持っています)。私はカメラを完全に制御できるので、キャプチャごとに一貫してカメラを配置できます。

現在、OpenCVを使用して認識を行おうとしています。サンプルの「顔認識」アプリを変更して、別のHaar識別子XMLファイルを使用することができましたが、これは外側の円/楕円の検出のみを処理するようです。

サンプルごとにオブジェクトを生成して、さらに処理するための5つの内線を記述することに興味があります。

{
    1: { length: 20, avg_thick: 2.3 },
    2: { length: 4, avg_thick: 2.0 },
    3: { length: 9.1, avg_thick: 2.1 },
    4: { length: 2, avg_thick: 1.9 },
    5: { length: 17, avg_thick: 2.1 }
}

これは、画像認識を含む私の最初のプロジェクトです。これを達成するためにどのアルゴリズムまたは手順を使用/調査する必要がありますか?ありがとう!

アップデート:

画像は手作業で撮影するため、純粋な白黒ではありません。しきい値を適用しようとすると、図形内の(かすかな)線が消えることがあります。しきい値処理の結果を改善するにはどうすればよいですか?

4

2 に答える 2

5

線がほぼ直線の場合は、ハフ変換を使用してすべての線を検索し、ハフ変換の円バージョンを使用してすべての円/楕円を検索します(境界の円/楕円が検出されたかどうか、およびどの線が内側にあるかを確認できます)たとえば)。

線が真っ直ぐでない場合:線ではなく「細長い領域」を意味しますよね?:)スケルトン化する必要があります(おそらく最初にしきい値)。役立つチュートリアル:「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のように見えます)。

編集:しきい値を設定する方法(または設定するかどうか)は興味深い質問です。おそらく大津の方法に基づいて、またはガウス混合に基づいて、自動しきい値処理を試すことができます()。背景と前景の色と明るさのある種の統計モデルを、局所的に適応可能なしきい値と組み合わせることで、おそらく最良の結果が得られると思います。本当にあなたの画像の性質に依存します。

于 2013-01-02T07:04:44.277 に答える
1
  1. 画像をスケルトン化し、各行を追跡すると、行の数とそれぞれの長さがわかります。
  2. 各線について、面積を計算し(元の白黒画像の黒いピクセルの数を数えます)、それを長さで割って平均の厚さを求めます。
于 2013-01-02T06:31:39.513 に答える