方法:画像内のピクセルパックから代表的なポイント座標(x、y)


7

左側の次の図に示すように、画像(グレースケールまたはバイナリ)があるとします。目標は、ポイントのリスト、つまり(x、y)の形式の座標のリストを生成することです。画像の暗いピクセル。
これを行うための適切な画像処理ツールは何ですか?それらはどこで利用できますか?

ポイント座標へのピクセルパック


更新:
1) ここでは、問題の詳細を確認できます。(パックのサイズの違いに注意してください)

細部

それぞれの凸包境界を計算するパックを検出してから、代表的な重心を見つけることをお勧めします{詳細はこちらを参照}

中心点への凸包へのピクセルパック


2)
以下は、距離変換(「Libor」が推奨)を適用した結果です。図の注釈に注意してください。この方法は有望だったため機能しません!

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

3)
侵食は小さなパックを排除します!

from __future__ import division
from scipy import zeros, ndimage as dsp
from pylab import subplot,plot,matshow,show

img = zeros((30,30))
img[10:14,10:14] = 1
img[16:17,16:17] = 1
img[19:23,19] = 1
img[19,19:23] = 1

subplot(221)
matshow(img,0)

subplot(222)
y = dsp.binary_erosion(img,[[1,1],[1,1]])
matshow(y,0)

subplot(223)
y = dsp.binary_erosion(img,[[0,1,0],[1,1,1],[0,1,0]])
matshow(y,0)

subplot(224)
y = dsp.binary_erosion(img,[[1,1,1],[1,1,1],[1,1,1]])
matshow(y,0)

show()

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

4)
さて、ここにPython(つまり、愛の言語:))の実装のラベル付けのアイデア(以下の「Jean-Yves」によっても提案されています):

subplot(221)
l,n = dsp.label(img)
sl = dsp.find_objects(l)
for s in sl:
    x = (s[1].start+s[1].stop-1)/2
    y = (s[0].start+s[0].stop-1)/2
    plot(x,y,'wo')

そして結果:

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

Scipyのパフォーマンスのため、Pythonでは非常に高速に行われますが、label関数のバックグラウンドプロシージャは、繰り返しの多い処理であることに注意してください。これはトレードオフと見なすことができます。しばらくの間、私はより効率的なアルゴリズムを模索することに熱心に取り組んでいます。また、上記のコードでは、ジオメトリの中心が非常に単純に見つかりましたが、複雑な形状や非対称の形状の場合、位置が偏る可能性があることに注意してください。つまり、進行中の作業です;)。

5)
ここから取り込んだ複雑なケース(実像)で、ここでラベリング案が適用されているが、あなたは結果を参照してください。ラベル付けやオブジェクトの検索を含む手順全体でわずか0.015秒しかかかりませんでした。Scipyのみんな、とてもうまくいきました。うわー!{画像を右クリックし、画像をクリックしてフル解像度で表示}

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


知っていますか:1)パックの数。2)パックの最大/最小xサイズ。3)パックの最大/最小Yサイズ。
Spacey

@Mohammad Givenはイメージにすぎません。したがって、あなたが言及した必要な情報はどれも利用できません。
開発者

パックのを検出できれば、それを一般的なk平均アルゴリズムの「k」の値として使用します。kの値を指定すると、各クラスターの中心に収束します。ただし、「k」の値をどのように決定できるかはわかりません。それをどのように判断しますか?
Spacey

小さなパッチ(例:2x2)で最大値を検出するには、距離変換/収縮のサブピクセル精度が必要です。最大値がありますが、サンプリングでスキップしているため検出できません。距離変換の場合、画像を2倍にアップサンプリングするか、サブピクセル位置(0.0、0.5、1.0、1.5 ...)の変換を計算できます。侵食の場合は、PDEベースの形態(反復)を使用して実装できます。
Libor

SO上で私のこの質問@Developer参考になります。stackoverflow.com/questions/4087919/...
イヴォFlipse

回答:


4

単純な提案:コンポーネントのラベル付けについて知っていますか?

この技術は、「感動」ピクセルの塊を見つけ、それらにラベルを割り当てることについてです例えば整数。次に、各隙間を個別に調べ、同じラベルを共有するピクセルを探します。

MATLABでは、これは簡単にそれを行う関数です:bwlabel


提案をありがとう。私はすでにこの方法に取り組みましたが、あなたが言ったように、Pythonでの実装で投稿を更新しました。私は中にラベルの使用に関するいくつかの問題浮上更新4
開発者

これは問題を解決するための別のアプローチなので、これを支持しました。共有してくれてありがとう:)
開発者

アップデート4を明確にしていただけませんか?私はあなたがトレードオフと疲労によって何を意味するのかわかりません。
Jean-Yves

ラベリングを行うことは反復的な仕事であり、多くの計算を必要とします。しかし、Scipyの連中はすぐにそれを行うために素晴らしい仕事(またはいくつかのトリック!)を行いました。私は実際に複雑なケースを評価に使用しましたが、それは0.015秒でしか機能しませんでした。すごくないですか?2番目の部分、つまり検出されたパックの中心を見つけることはまだ問題であることに注意してください。このような一連のパックに凸包を適用することはお勧めできません。
開発者

私は同意しません:接続コンポーネントのラベル付けは拡張的ではありません。最近のほとんどの実装では線形時間で実行され、マルチスレッドで実行することもできます。
Jean-Yves、

3

画像で距離変換を実行してから、極大値を検出することもできます(3x3ピクセルパッチ内のすべてのピクセルの最高/最低値を持つピクセルを検索-元のブロブ間の予想最小距離によっては大きくなる場合があります)。

1〜3ピクセルのサイズの特徴を検出するには、サンプリング周波数を2倍にする必要があることに注意してください(ソース画像を拡大するか、サブピクセル精度で距離変換/収縮を実行します)。

更新:

距離変換と侵食の両方のアプローチは、検出する特徴が凸状であることを前提としています。たとえば、U字型のものは、検出器で数回発砲する可能性があります。

このようなセグメンテーションのより複雑な方法は、レベルセットアクティブな輪郭に基づいています。それはあなたの特徴に繰り返し適応される大きな閉曲線から始まります。この方法は、私の大学で細胞を数え、顕微鏡画像で染色体を検出するために使用されています。


あなたのアイデアの私の実装の結果は、セクションUpdates:2で確認できます。期待どおりに動作しないようです:(
開発者

はい、答えを広げました。
Libor 2012

これは問題を解決するための別のアプローチなので、これを支持しました。共有してくれてありがとう:)
開発者

2

1つのオプションは、画像が完全に侵食されるまで繰り返される形態学的侵食を適用することです。その時点で、上記のブロブはそれぞれ1つのピクセルに縮小されます。これらのピクセルの位置を、探している点のリストにすることができます。


いくつかのポイント:1)反復を停止するには?2)それらのパックが小さい場合、表示されなくなることがあります。3)データセット全体に反復が必要であるため、計算が非常に集中しているように見えます。画像が大きくなる可能性があることに注意してください。
開発者

私はすぐにあなたのアイデアを現在の形で実装しましたが、うまくいきませんでした。小さなパックを排除します。以前のすべてのコメントが適用されます。
開発者

「小さなパック」の意味がわかりません。例の画像に表示されているものはありますか?
Jason R

さて、示されているように、パックはさまざまなサイズと形状であり、反復浸食(Python:Scipy:Spatial:Erosion)を適用すると、小さい(または狭い)パックが消えました。実際の場合、入力画像のパックは1ピクセルから非常に大きい範囲になる可能性があることに注意してください。
開発者

@開発者事前に「パック」の数を知っていますか?たとえば、ここには6があります
。– Spacey

2

これを行うためにどのような方法を選択しても、ターゲットをクラスターに割り当てるにはイメージを(少なくとも1回)実行する必要があるため、簡単ではありません。

ポイントを取得することは、2つのうちのより簡単な問題だと思います(たとえば、既に何らかの形のしきい値処理を適用している可能性があります)。

ポイントがグループ化されているクラスターを回復して高速に実行するには、四分木セルの領域の周りにある「接続されたピクセルのチェーン」を保持する四分木構造を作成できます。

このようにして、画像を反復処理し、ターゲットであるピクセルに出会ったら、四分木構造に「プッシュ」することができます。

この「プッシュ」操作は、特定のピクセルが存在するセル(つまり、画像の特定の領域)を返す反復プロセスを開始します。次に、そのセルに割り当てられているすべてのピクセルチェーンを反復処理して、ピクセルをピクセルチェーンに(再度)プッシュします。ピクセルチェーンは、既に割り当てられているいずれかのピクセルに少なくとも1ピクセル近い場合、新しいピクセルを受け入れます。新しいピクセルを受け入れないピクセルチェーンがない場合は、このセルに新しいピクセルチェーンを作成し、新しいピクセルを割り当てます。

ここの四分木は、最も近いピクセルチェーンの検索を制限する方法であり、ピクセルチェーンのプッシュ操作が高速に行われるように、画像が大きくターゲットが多数ある場合に必要です。多数のターゲットを処理しないことがわかっている場合は、クワッドツリーをスキップして、単純な「ピクセルチェーンのリスト」を維持することもできます。「ターゲット」に遭遇するたびに、リストを反復処理して、ピクセルを「プッシュ」することを試みることができます。リストにピクセルが「採用」されていない場合は、新しいリストを作成してピクセルを割り当てます。

どちらの方法を選択する場合でも、このプロセスの最後に、一連の接続された「ピクセルチェーン」(クラスター)が得られます。これは、プログラムの別の部分に渡すことができ、プログラムの別の部分に渡されます。ロケーション。これは、凸包、モデルフィッティング(楕円体など)、または単にx、y座標の平均/中央値にすることができます。

これがお役に立てば幸いです。


これは問題を解決するための別のアプローチなので、これを支持しました。共有してくれてありがとう:)
開発者
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.