7

凸面ポリゴンと非凸面ポリゴンの両方を含む画像がいくつかあります。各画像には、ポリゴンが 1 つだけ含まれています。角の座標を検出し、時計回りまたは反時計回りに並べ替える必要があります。凸多角形の場合、コーナーの検出にはハリス コーナー検出を使用し、ポイントの並べ替えには凸包を使用します。しかし、凸でないポリゴンをソートする方法についてはわかりません。私の入力は画像であるため、ポリゴンの端に沿って移動することで、画像処理テクニックがそれらを整理するのに役立つと思います。複雑さが最も少ない方法はありますか?

画像例:

コーナーにランダムに名前を付けました。

ここに画像の説明を入力

期待される出力:

コーナー座標は次の順序 1 3 5 9 4 2 8 7 6 10またはであると予想され1 10 6 7 8 2 4 9 5 3ます。いつでも開始できますが、必ずしもそうである必要はありません1

編集1:

すべての凸多角形と一部の非凸多角形で機能するrayryengのソリューションの後、彼のアルゴリズムではうまくいかない非凸多角形がいくつかあります。

ここに例があります

ここに画像の説明を入力

4

2 に答える 2

6

これは、画像処理でよくある問題です。典型的な答えは、形状の重心を見つけ、重心と各角点の間の角度を見つけることです。[0,360)角度が度の間の範囲になるように表現されていることを確認してください。これを取得したら、角度を並べ替え、結果の順序を使用してポイントの順序を決定します。

あなたが提示した画像には、作業を開始できるように、少し前処理が必要です。StackOverflow から直接画像を読み込み、黒い星が白くなるように画像を反転します。数字も削除する必要があるため、bwareaopenテキストの小さな領域を削除します。それが完了したら、 を介してこの画像のコーナー検出を実行し、を 0.3cornerに設定して、10 個のコーナーを検出できるようにします。QualityFactor非常に具体的に:

%// Read image from StackOverflow
im = rgb2gray(imread('http://i.stack.imgur.com/dpbpP.jpg'));

%// Threshold the image and area open it
im_thresh = im <= 100;
im_open = bwareaopen(im_thresh, 50);

%// Detect corner points
out = corner(im_open, 'QualityLevel', 0.3);

%// Show the image with the corner points
imshow(im_open);
hold on
plot(out(:,1), out(:,2), 'r.')

im_open最終的に処理された画像が含まれています。これは私が得るものです:

ここに画像の説明を入力


では、重心を求めましょう。これは、ゼロ以外の位置の座標を見つけ、各次元の平均を見つけることで簡単に実行できます。

[rows, cols] = find(im_open);
cenX = mean(cols);
cenY = mean(rows);

cenX画像の重心の位置がcenY含まれます。(x,y)正しいことを確認するために:

imshow(im_open);
hold on;
plot(cenX, cenY, 'r.', 'MarkerSize', 18);

我々が得る:

ここに画像の説明を入力

非常に素晴らしい。さて、out前のコードに(x,y)はコーナーポイントのポイントが含まれています。重心から各角点までの角度を決定し、角度を並べ替えるだけです。この並べ替え順序を使用してコーナー ポイントを再配置し、配置したポイントを取得します。時計回りにしたい場合は、値を昇順で並べ替える必要があります。反時計回りにしたい場合は、降順でソートする必要があります。何を決定するかはあなたにお任せしますが、両方を実行できるコードを書きます。したがって、単純に次のようにします。

%// Determine angles (in degrees)
angles = atan2d(out(:,2) - cenY, out(:,1) - cenX);

%// Any negative angles, add 360 degrees to convert to positive
angles(angles < 0) = 360 + angles(angles < 0);

%// Sort the angles
[~,ind] = sort(angles); %// clockwise
%[~,ind] = sort(angles, 'descend'); %// counter-clockwise

%// Re-arrange the corner points to respect the order
out_reorder = out(ind,:);

最後のテストは、これらの点をプロットし、各点の横に数値をプロットして、それが正しいかどうかを確認することです. これは次の方法で実行できます。

%// Show image
imshow(im_open);
hold on;
%// Show points
plot(out_reorder(:,1), out_reorder(:,2), 'r.', 'MarkerSize', 18);

%// Place a textbox at each point and show a sequence number
for idx = 1 : size(out_reorder,1)
    text(out_reorder(idx,1), out_reorder(idx,2), num2str(idx), 'FontSize', 24, 'Color', 'green');
end

我々が得る:

ここに画像の説明を入力

は、私にはよく見えますよ!そのout_reorderため、コーナー ポイントが時計回りまたは反時計回りの順序に従うように指定します。連続して遭遇する各行は、求める時計回りまたは反時計回りの順序に自然に従う次のポイントを提供します。

また、番号付けの開始位置にも注意してください。角度 0 は、重心に対して東を指す水平線によって定義されます。したがって、昇順で開始しているため、0 に最も近いポイントは、数字の 1 が表示されている場所です。1 の後、角のポイントがなくなるまで時計回りにスイープすることがわかります。

于 2015-03-29T04:49:11.217 に答える