2

最近、解決できないような問題に遭遇しました。小さな「ローカル」グループで画像全体に広がる多数のピクセルを含む処理済み画像があります。各グループの「中心」を見つけて、各グループの代表として出力画像に1つのピクセルを配置したいと思います。グループ化は、それらの間にピクセルゼロの間隔がない緊密に編成されたグループ、またはそれらの間に数個(4〜5ピクセル未満)しかない小さな広がりのあるグループのいずれかです。私の最初の考えは、形態学的侵食の線に沿って何かを使用することでしたが、これは、ピクセルのグループがわずかに広がっている場合を考慮していません。誰かが私を正しい方向に向けることができるかどうか知りたいだけです。以下は私がやりたいことの例です: ローカルグループ 左側の画像は入力を示し(大きな黒い点は間にゼロがないピクセルのグループを表します)、右側の画像は出力または処理された画像のタイプの例です。最後に、MATLABを使用しており、入力画像はバイナリ画像であると想定できます(黒が1または0のいずれかで、ロジックは同じである必要があります)。

どうもありがとうございました!

編集:みんなの意見に感謝します-私は翌日かそこらでさまざまな解決策を試し、終わったらみんなに返信しようと思います。洞察に満ちたご意見をありがとうございました。ありがとうございました。

4

4 に答える 4

2

あなたが説明している問題は、一般的にクラスタリングまたはクラスター分析と呼ばれます。データセットと分析の制約によっては、非常に難しい場合があります。ただし、あなたの場合、使用するしきい値(5ピクセル)が難しいため、簡単です。

Aardvarkkはすでに優れたソリューションを発表していますが、クラスタリングのプロセスを実際に示しているわけではありません。これは、データをクラスター化してほぼ同じ結果を得ることができる非常に簡単な方法です。

  1. ポイント間のペアワイズ距離を計算します。Nポイントの場合、これはNxN行列になります
  2. そのマトリックスのしきい値
  3. 行列の行を反復処理します

各反復は次のようになります。

  • iすでにクラスター化されている場合は、続行します
  • がクラスター内にない場合iは、新しいクラスターを作成して割り当てiます
  • ( 1に等しいi行の列)に近い他のすべてのポイントを検索しますi
  • それらのポイントのいずれかがすでにクラスター内にあるかどうかを確認してください
  • はいの場合、設定され、すべてのポイントが最小クラスターIDにi近いi
  • セットがなく、すべてのポイントがクラスターiに近い場合ii's

これが私が作った簡単な例です:

%Generate random points
nPts = 300;
clustId = zeros(nPts,1);
clusterCount = 0;
x = randi(3, [1, nPts])*10+ randn(1, nPts);
y = randi(3, [1, nPts])*10 + randn(1, nPts);

%Compute the distance matrix  from http://goo.gl/8mAoC
dist = distance([x;y], [x;y]);

maxDist = 5;
binDist = dist <= maxDist;


for i = 1:nPts
    % if this point is already clustered skip it
    if clustId(i) ~= 0
        continue;
    end

    %if the current point isn't in a cluster, create a new cluster and add
    %the point to that cluster
    if clustId(i) == 0
        clusterCount = clusterCount+1;
        clustId(i) = clusterCount;
        fprintf('New point, creating cluster:%d\n', clusterCount);
    end

    % get the indices of the points that collide with the i
    idx = binDist(:,i);

    % check to see if idx contains points that already belong to another clustered
    % if it doesn't collisionIdx will be equal to i
    collisionIdx = idx & clustId>0;

    %get the smallest cluster from collisionIdx
    mergeClustId = min(clustId(collisionIdx));

    %assing all the original points to that cluster
    clustId(idx) = mergeClustId;
end

クラスターIDを繰り返し処理して、重心を計算します。

cx = [];
cy = [];
for i = 1:clusterCount
    idx = clustId == i;
    cx(i) = mean(x(idx));
    cy(i) = mean(y(idx));
end

次に、結果を次のようにプロットします。

figure; 
plot(cx,cy,'c.', 'markersize', 50); hold on;
plot(x,y,'.');

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

于 2012-08-01T15:03:59.570 に答える
2

形態学的閉鎖とそれに続く連結成分分析を含むアプローチをお勧めします。「良いドット」は価値が高く、「悪い背景」は黒であるように、問題を逆にしたことに注意してください。これは、モルフォロジー操作の予想される定義とより密接に適合します。

path = 'yourimage.png'
space = 5; % you can change this to make it accept bigger spacings

input = imcomplement(rgb2gray(imread(path))) > 0;
input = imclose(input, strel('disk', space));
[labels, num] = bwlabel(input, 8);
output = logical(zeros(size(input)));
for i = 1:num
   [r, c] = find(labels==i); 
   x = round(mean(c))
   y = round(mean(r))
   output(y,x) = 1;
end

imshow(output)

結果は次のようになります。

結果

私にはあなたが探しているものがあるようです!

于 2012-08-01T14:51:49.770 に答える
0

slaytonが指摘しているように、これはクラスタリングの問題です。

クラスターの分離は非常に明確であるため、単純なグラフベースのアプローチを使用できます。グラフアルゴリズムライブラリ(多くのバインディングが存在するboost ::graphなど)にアクセスできる場合、次のアプローチは非常に簡単です。

  1. エッジの重みを距離として使用して、ポイントの完全グラフを作成します。
  2. たとえば、プリムアルゴリズムを使用して最小スパニングツリーを計算します
  3. ツリーから長さのしきい値を超えるエッジを削除します
  4. 残りの接続されたコンポーネントを見つける
于 2012-08-02T07:14:48.283 に答える
0

この場合、最初に領域拡大法を使用して、固定されたピクセルを結合し、次に侵食を使用することができます。あなたが知っているなら、それはクラスター間の距離がクラスター自体よりも大きいことを知っているなら、うまくいくでしょう。おそらく、重心を使用して、領域が成長した後の各ブロブの中央を決定します。

于 2012-08-01T14:03:39.957 に答える