私はこの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];
楽しみ。