8

図1のような画像があります。ここに画像の説明を入力このバイナリ イメージをキャップ付きの長方形 (図 2)ここに画像の説明を入力 に合わせて把握しようとしています。

  1. 方向 (長軸と水平軸の間の角度)
  2. オブジェクトの長さ (l) と半径 (R)。それを行う最良の方法は何ですか?助けてくれてありがとう。

私の非常に素朴な考えは、これらの情報を見つけるために最小二乗法を使用することですが、キャップされた長方形の方程式がないことがわかりました。matlabには、四角形と呼ばれる関数があり、キャップ付きの四角形を完全に作成できますが、プロットの目的だけのようです。

4

2 に答える 2

16

私はこの2つの異なる方法を解決し、以下の各アプローチに関するメモを持っています. 各方法は複雑さが異なるため、アプリケーションに最適な取引を決定する必要があります。

最初のアプローチ: 最小二乗最適化: ここでは、Matlab の fminunc() 関数による制約のない最適化を使用しました。Matlab のヘルプを見て、最適化の前に設定できるオプションを確認してください。このアプローチを機能させるために、いくつかのかなり単純な選択をしました。

要約すると、L、W、およびシータのパラメーターの関数として、おおわれた四角形のモデルをセットアップします。必要に応じて R を含めることができますが、個人的には必要ないと思います。各エッジの半円との連続性を調べることで、モデルのジオメトリを調べて、R = W にするだけで十分だと思います。これにより、最適化パラメーターの数も 1 つ減ります。

ブール値レイヤーを使用してキャップ付き四角形のモデルを作成しました。以下の cappedRectangle() 関数を参照してください。その結果、L、W、およびシータに関するモデルの有限差分勾配を計算する関数が必要でした。これらの勾配を fminunc() に提供しない場合、これらを推定しようとしますが、このアプリケーションでは Matlab の推定がうまく機能しないことがわかったので、fminunc によって呼び出されるエラー関数の一部として独自のものを提供しました。 () (下記参照)。

最初はあなたのデータを持っていなかったので、上の画像を右クリックしてダウンロードしました: 'aRIhm.png'

データを読み取るために、私はこれを行いました(変数を作成しますcdata):

image = importdata('aRIhm.png');
vars = fieldnames(image);
for i = 1:length(vars)
    assignin('base', vars{i}, image.(vars{i}));
end

次に、double 型に変換し、正規化してデータを「クリーンアップ」しました。注:この前処理は、最適化を適切に機能させるために重要であり、生データがなかったため必要だった可能性があります(前述のように、この質問のWebページから画像をダウンロードしました):

data = im2double(cdata); 
data = data / max(data(:));
figure(1); imshow(data); % looks the same as your image above

画像サイズを取得します。

nY = size(data,1);
nX = size(data,2);

注 #1:最適化パラメーターとして、キャップされた四角形の中心 (xc,yc) を追加することを検討してください。これらの余分な自由度は、全体的なフィッティング結果に違いをもたらします (以下の最終誤差関数値に関するコメントを参照してください)。ここでは設定しませんでしたが、L、W、シータに使用したアプローチに従って、有限差分勾配を使用してその機能を追加できます。また、(xc,yc) の関数としてキャップ付き四角形モデルを設定する必要があります。

編集:好奇心から、キャップされた長方形の中心に最適化を追加しました。下部の結果を参照してください。

注 #2:キャップされた四角形の両端の「連続性」については、R = W とします。必要に応じて、L、W、シータの例に従って、後で R を明示的な最適化パラメーターとして含めることができます。各エンドポイントで変数として R1 と R2 を言いたいと思うかもしれません。

以下は、最適化の例を簡単に説明するために使用した任意の開始値です。申請書にどの程度の情報が含まれているかはわかりませんが、一般的には、できる限り最善の初期見積もりを提供するようにしてください

L = 25;
W = L;
theta = 90;
params0 = [L W theta]; 

最初の見積もりに基づいて異なる結果が得られることに注意してください。

次に、最初の見積もりを表示します (cappedRectangle() 関数は後で定義されます)。

capRect0 = reshape(cappedRectangle(params0,nX,nY),nX,nY);
figure(2); imshow(capRect0);

エラー メトリックの無名関数を定義します (errorFunc() は以下にリストされています)。

f = @(x)errorFunc(x,data);

% Define several optimization parameters for fminunc():
options = optimoptions(@fminunc,'GradObj','on','TolX',1e-3, 'Display','iter');

% Call the optimizer:
tic
[x,fval,exitflag,output] = fminunc(f,params0,options);
time = toc;
disp(['convergence time (sec) = ',num2str(time)]);

% Results:
disp(['L0 = ',num2str(L),'; ', 'L estimate = ', num2str(x(1))]);
disp(['W0 = ',num2str(W),'; ', 'W estimate = ', num2str(x(2))]);
disp(['theta0 = ',num2str(theta),'; ', 'theta estimate = ', num2str(x(3))]);
capRectEstimate = reshape(cappedRectangle(x,nX,nY),nX,nY);

figure(3); imshow(capRectEstimate);

以下は fminunc からの出力です (各列の詳細については、Matlab のヘルプを参照してください)。

 Iteration        f(x)          step          optimality   CG-iterations
     0           0.911579                       0.00465                
     1           0.860624             10        0.00457           1
     2           0.767783             20        0.00408           1
     3           0.614608             40        0.00185           1

     .... and so on ...

    15           0.532118     0.00488281       0.000962           0
    16           0.532118      0.0012207       0.000962           0
    17           0.532118    0.000305176       0.000962           0

最終的なエラー メトリック値が開始値に比べてそれほど減少していないことがわかります。これは、モデル関数にはおそらくデータを実際に「適合」させるのに十分な自由度がないことを示しているため、追加を検討してください。前に説明したように、追加の最適化パラメータ (例: 画像の中心)。

編集:キャップされた長方形の中心に最適化を追加しました。下部の結果を参照してください。

結果を印刷します (2011 Macbook Pro を使用):

Convergence time (sec) = 16.1053
    L0 = 25;      L estimate = 58.5773
    W0 = 25;      W estimate = 104.0663
theta0 = 90;  theta estimate = 36.9024

結果を表示します。

ここに画像の説明を入力

編集: 上記のフィッティング結果の誇張された「厚さ」は、モデルが中心を固定したままデータをフィッティングしようとするため、W の値が大きくなるためです。下部の更新された結果を参照してください。

データを最終推定値と比較すると、比較的単純なモデルでもデータにかなりよく似ていることがわかります。

さらに進んで、独自のモンテカルロ シミュレーションを設定して、ノイズやその他の劣化要因の関数としての精度を確認することにより、推定値のエラー バーを計算できます (シミュレートされたデータを生成するために生成できる既知の入力を使用)。

以下は、キャップ付きの四角形に使用したモデル関数です (注: 画像の回転を行う方法は、数値的には大ざっぱで、有限差分に対してはあまり堅牢ではありませんが、迅速で汚れていて、うまくいきます):

function result = cappedRectangle(params, nX, nY)
[x,y] = meshgrid(-(nX-1)/2:(nX-1)/2,-(nY-1)/2:(nY-1)/2);
L = params(1);
W = params(2);
theta = params(3); % units are degrees
R = W; 

% Define r1 and r2 for the displaced rounded edges:
x1 = x - L;
x2 = x + L;
r1 = sqrt(x1.^2+y.^2);
r2 = sqrt(x2.^2+y.^2);

% Capped Rectangle prior to rotation (theta = 0):
temp = double( (abs(x) <= L) & (abs(y) <= W) | (r1 <= R) | (r2 <= R) );
cappedRectangleRotated = im2double(imrotate(mat2gray(temp), theta, 'bilinear', 'crop'));

result = cappedRectangleRotated(:);

return

そして、fminunc によって呼び出されるエラー関数も必要になります。

function [error, df_dx] = errorFunc(params,data)
nY = size(data,1);
nX = size(data,2);

% Anonymous function for the model:
model = @(params)cappedRectangle(params,nX,nY);

% Least-squares error (analogous to chi^2 in the literature):
f = @(x)sum( (data(:) - model(x) ).^2  ) / sum(data(:).^2);

% Scalar error:
error = f(params);
[df_dx] = finiteDiffGrad(f,params);

return

有限差分勾配を計算する関数と同様に:

function [df_dx] = finiteDiffGrad(fun,x)
N = length(x);
x = reshape(x,N,1);

% Pick a small delta, dx should be experimented with:
dx = norm(x(:))/10;

% define an array of dx values;
h_array = dx*eye(N); 
df_dx = zeros(size(x));

f = @(x) feval(fun,x); 

% Finite Diff Approx (use "centered difference" error is O(h^2);)
for j = 1:N
    hj = h_array(j,:)';
    df_dx(j) = ( f(x+hj) - f(x-hj) )/(2*dx);
end  

return

2 番目のアプローチ: regionprops() を使用する

他の人が指摘したように、Matlab の regionprops() も使用できます。全体として、期待どおりに動作することを保証するために、いくつかの調整とチェックを行うことで、これが最適に機能すると思います。したがって、アプローチは次のように呼び出すことになります (確かに、最初のアプローチよりもはるかに簡単です!):

data = im2double(cdata); 
data = round(data / max(data(:)));

s = regionprops(data, 'Orientation', 'MajorAxisLength', ...
    'MinorAxisLength', 'Eccentricity', 'Centroid'); 

そして、構造体の結果は次のとおりです。

>> s
s = 
           Centroid: [345.5309 389.6189]
    MajorAxisLength: 365.1276
    MinorAxisLength: 174.0136
       Eccentricity: 0.8791
        Orientation: 30.9354

これにより、キャップされた長方形のモデルにフィードするのに十分な情報が得られます。一見、これは進むべき道のように見えますが、別のアプローチ (おそらく上記の最初のアプローチ) に心を向けているようです。

とにかく、以下は、データの上に重ねられた結果 (赤) の画像で、非常によく見えます。

ここに画像の説明を入力


編集: 私は自分自身を助けることができませんでした.画像の中心を最適化パラメータとして含めることで、はるかに良い結果が得られるのではないかと思ったので、先に進んで確認するだけでした. 案の定、前述の最小二乗推定で使用したものと同じ開始推定値を使用すると、結果は次のようになります。

Iteration        f(x)          step          optimality   CG-iterations
     0           0.911579                       0.00465                
     1           0.859323             10        0.00471           2
     2           0.742788             20        0.00502           2
     3           0.530433             40        0.00541           2
     ... and so on ...
    28          0.0858947      0.0195312       0.000279           0
    29          0.0858947      0.0390625       0.000279           1
    30          0.0858947     0.00976562       0.000279           0
    31          0.0858947     0.00244141       0.000279           0
    32          0.0858947    0.000610352       0.000279           0

以前の値と比較すると、画像の中心を含めると、新しい最小二乗誤差の値がかなり小さいことがわかり、以前に疑っていたことが確認されました (大きな驚きはありません)。

したがって、キャップされた長方形パラメーターの更新された推定値は次のようになります。

Convergence time (sec) = 96.0418
    L0 = 25;     L estimate = 89.0784
    W0 = 25;     W estimate = 80.4379
theta0 = 90; theta estimate = 31.614

そして、画像配列の中心に対して、次のようになります。

xc = -22.9107 
yc = 35.9257

最適化には時間がかかりますが、目視検査でわかるように、結果は改善されています。

ここに画像の説明を入力

パフォーマンスが問題になる場合は、独自のオプティマイザーを作成することを検討するか、最初に Matlab の最適化パラメーターを調整してみてください。おそらく、別のアルゴリズム オプションも使用します。上記の最適化オプションを参照してください。

更新されたモデルのコードは次のとおりです。

function result = cappedRectangle(params, nX, nY)
[X,Y] = meshgrid(-(nX-1)/2:(nX-1)/2,-(nY-1)/2:(nY-1)/2);

% Extract params to make code more readable:
L = params(1);
W = params(2);
theta = params(3); % units are degrees
xc = params(4); % new param: image center in x
yc = params(5); % new param: image center in y

% Shift coordinates to the image center:
x = X-xc;
y = Y-yc;

% Define R = W as a constraint:
R = W;

% Define r1 and r2 for the rounded edges:
x1 = x - L;
x2 = x + L;
r1 = sqrt(x1.^2+y.^2);
r2 = sqrt(x2.^2+y.^2);

temp = double( (abs(x) <= L) & (abs(y) <= W) | (r1 <= R) | (r2 <= R) );
cappedRectangleRotated = im2double(imrotate(mat2gray(temp), theta, 'bilinear', 'crop'));

result = cappedRectangleRotated(:);

fminunc() を呼び出す前に、パラメーター リストを調整しました。

L = 25;
W = L;
theta = 90;
% set image center to zero as intial guess:
xc = 0; 
yc = 0;
params0 = [L W theta xc yc]; 

楽しみ。

于 2013-11-27T01:23:55.657 に答える