ノイズの多い画像データでの円の検出


17

次のような画像があります。 ここに画像の説明を入力してください

円の半径(または直径)を見つけようとしています。(matlab'sを介して)円形のハフ変換を使用imfindcircles(bw,[rmin rmax],'ObjectPolarity','bright')して、円または楕円(ノイズの少ないデータで非常にうまく機能する自家製の関数、以下を参照)に適合させてみました。

また、より明確な円を得るためにいくつかの画像処理を試しました。たとえば、以下を参照してください。

se = strel('disk', 2);
bw = imdilate(bw, se);
bw = bwareaopen(bw,100000); 
bw =  edge(bw); 

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

ただし、処理された画像をいずれかの手法(ハフと円\楕円のフィッティング)にフィードすると、どちらも適切な方法で円を検出できません。

これが、私が書いたサークルファインダーのコードスニペットです(matlab)[row col] = find(bw); contour = bwtraceboundary(bw、row(1)、col(1)]、 'N'、接続性、num_points);

    x = contour(:,2);
    y = contour(:,1);

    % solve for parameters a, b, and c in the least-squares sense by
    % using the backslash operator
    abc = [x y ones(length(x),1)] \ -(x.^2+y.^2);
    a = abc(1); b = abc(2); c = abc(3);

    % calculate the location of the center and the radius
    xc = -a/2;
    yc = -b/2;
    radius  =  sqrt((xc^2+yc^2)-c);

代替アプローチが高く評価されます...


ハフ変換は、塗りつぶされたディスクではなく、円を探します。満たされたディスクを空の円に変換するには、まずエッジ検出を行う必要があります。サークルの特性は何ですか?サイズは一定ですか?彼らは楕円になることができますか?ドットは異なって分布できますか?
エンドリス

私は試しました(編集された例を参照)、それはノイズが多すぎるか、十分に円形ではありませんか?さらに、サイズは一定であり、カメラの角度誤差により、実際には完全に円形のウィンドウであるにもかかわらず、微小な楕円率を持つ場合があります。
-bla

大きさや形状が一定であれば、あなたは、元のドットイメージで満たされたディスクテンプレートの相互相関のようなものを試してみてください
endolith

私の答えに加えて、画像処理パイプの遅すぎる段階でこれを行おうとしているのではないかと思います。問題について詳しく教えて、前の手順をいくつか示してください。
アンドレイRubshtein

回答:


13

これが私の解決策です。@ Yodaのアイデアに近いですが、いくつかの手順を変更しました。

  • 7x7近傍に少なくとも6ピクセルあるようにすべてのピクセルをマークします
  • すべてのブロブを削除しますが、最大のもの
  • 穴を埋める
  • エッジ検出を適用する
  • ハフ変換を使用して円を見つける

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

関連するMatlabコードは次のとおりです。私は、コードでcircles .mファイルにハフ変換を使用しています。

function FindCircle()
    close all;
    im = imread('C:\circle.png');
    im = im(:,:,2);

    ims = conv2(double(im), ones(7,7),'same');
    imbw = ims>6;
    figure;imshow(imbw);title('All pixels that there are at least 6 white pixels in their hood');

    props = regionprops(imbw,'Area','PixelIdxList','MajorAxisLength','MinorAxisLength');
    [~,indexOfMax] = max([props.Area]);
    approximateRadius =  props(indexOfMax).MajorAxisLength/2;

    largestBlobIndexes  = props(indexOfMax).PixelIdxList;
    bw = false(size(im));
    bw(largestBlobIndexes) = 1;
    bw = imfill(bw,'holes');
    figure;imshow(bw);title('Leaving only largest blob and filling holes');
    figure;imshow(edge(bw));title('Edge detection');

    radiuses = round ( (approximateRadius-5):0.5:(approximateRadius+5) );
    h = circle_hough(edge(bw), radiuses,'same');
    [~,maxIndex] = max(h(:));
    [i,j,k] = ind2sub(size(h), maxIndex);
    radius = radiuses(k);
    center.x = j;
    center.y = i;

    figure;imshow(edge(bw));imellipse(gca,[center.x-radius  center.y-radius 2*radius 2*radius]);
    title('Final solution (Shown on edge image)');

    figure;imshow(im);imellipse(gca,[center.x-radius  center.y-radius 2*radius 2*radius]);
    title('Final solution (Shown on initial image)');

end

1
ここで実行しているハフ変換は何を解決し、青い円を見つけますか?画像上のさまざまな位置にさまざまな半径の多くの円を投影し、最適な円を見つけていますか?
スペイシー

@Mohammad、それは通常の円検出器です。ビニングと投票を使用します。
アンドレイRubshtein

この回答の最初のステップの後に、高速放射対称変換(FRST)を使用することもできます。
Geniedesalpages 14年

10

画像処理を使用してそれを行うことはかなり簡単です。以下はMathematicaの概念実証です。MATLABに変換する必要があります。

  • まず、軸をトリムし、その画像部分のみを保持します。この変数を呼び出しますimg
  • 画像を二値化して膨張させ、続いて塗りつぶし変換を行います。また、メインBLOBに接続されていない浮遊小型コンポーネントも削除します。次のように表示されます。

    filled = Binarize@img ~Dilation~ 3 // FillingTransform // DeleteSmallComponents
    

  • 次に、このblobの図心とそれに相当するblobのディスク半径を見つけます(openCV、MATLABにはこれを行うための同等のコマンドがあります)

    {center, radius} = 1 /. ComponentMeasurements[filled, {"Centroid", "EquivalentDiskRadius"}]
    
  • それでおしまい!元の画像と上記の中心と半径を持つ円をプロットして、どのように適合するかを確認します。

    Show[img, Graphics[{Red, Circle[center, radius]}]]
    


素晴らしい答え!膨張と充填の変換を拡大していただけますか?
スペイシー

@Mohammad Dilationは基本的な操作であり、wiki記事で簡単に説明できます。塗りつぶし変換は、「穴」、つまり高い値のピクセルに囲まれたピクセルのセットを塗りつぶします。「詳細」を参照してくださいここに
Loremのイプサム

ああ、タイプミス。私は膨張変換にやや精通していますが、実際には「充填変換」を拡張できるかどうか疑問に思っていました。それが正確に使用しているルールセットは何ですか?私はそれに関連する情報を見つけることができないようです。おそらく別の名前で行くのでしょうか?
スペイシー

@yoda、答えてくれてありがとう、でも質問を読んだら気づいたと思いますが、私は膨張とフィッティングを試しました。エッジを検出する前に生成された画像は、あなたのものに似ています。私はある程度フィットしますが、正確ではありません。フィットについても同様です。フィットした円の上部が大きすぎることがわかります。これは、おそらく円の上部のノイズの多い点を考慮するためです。また、楕円をフィットしようとしました(質問で述べたように)、問題はフィットが十分ではないということです。多分もっと良い方法は、円のより良い部分(円弧)を使ってフィットすることだと思います。
bla

@nate「近似円の上部」と「円のより良い部分」の意味がわかりません。さまざまなメトリックを使用できます...境界ボックス、長軸の長さ、短軸の長さ、重心からの平均距離、重心からの距離の中央値など。それはすべてあなたが望むものに依存します。
Loremイプサム
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.