2つの画像の青い点の間で1対1のマッチングがすでに確立されています。image2は、image1の歪んだバージョンです。歪みモデルは、アイフィッシュレンズの歪みのようです。問題は、この遷移を記述する変換行列を計算する方法はありますか。実際、最初の画像の青い点を2番目の画像の対応する青い点に変換する行列はありますか?ここでの問題は、焦点距離がわからないことです(つまり、画像がキャリブレーションされていないことを意味します)が、2つの画像の約200ポイントが完全に一致しています。 歪んだ画像:
1 に答える
あなたがやろうとしていることは、他の古典的なカメラのキャリブレーションを必要とせずに、歪み補正の問題として扱うことができると思います。
行列変換は線形変換であり、線形変換は常に直線を直線にマッピングします(http://en.wikipedia.org/wiki/Linear_map)。写真から明らかなように、変換は非線形であるため、行列演算で説明することはできません。
そうは言っても、OpenCV( http://docs.opencv.org/doc/tutorials/calib3d/camera_calibration/camera_calibration.html )で使用されているようなレンズ歪みモデルを使用でき、係数の取得はそれほど難しくありません。Matlabでできることは次のとおりです。
(x、y)元の点の座標(上の画像)と(xp、yp)歪んだ点の座標(下の画像)を呼び出します。どちらも画像の中心にシフトされ、スケーリング係数で除算されます(同じxとy)なので、それらは多かれ少なかれ[-1、1]間隔にあります。歪みモデルは次のとおりです。
x = ( xp*(1 + k1*r^2 + k2*r^4 + k3*r^6) + 2*p1*xp*yp + p2*(r^2 + 2*xp^2));
y = ( yp*(1 + k1*r^2 + k2*r^4 + k3*r^6) + 2*p2*xp*yp + p1*(r^2 + 2*yp^2));
どこ
r = sqrt(x^2 + y^2);
5つのパラメーターがあります。半径方向および接線方向の歪み用のk1、k2、k3、p1、p2、および200ペアの点であるため、非線形システムを解くことができます。
x、y、xp、およびyp配列がワークスペースに存在することを確認し、それらをグローバルとして宣言します。
global x y xp yp
任意の歪み係数のセットが与えられた場合の平均二乗誤差を評価する関数を記述します。たとえば、「dist」と呼ばれます。
function val = dist(var)
global x y xp yp
val = zeros(size(xp));
k1 = var(1);
k2 = var(2);
k3 = var(3);
p1 = var(4);
p2 = var(5);
r = sqrt(xp.*xp + yp.*yp);
temp1 = x - ( xp.*(1 + k1*r.^2 + k2*r.^4 + k3*r.^6) + 2*p1*xp.*yp + p2*(r.^2 + 2*xp.^2));
temp2 = y - ( yp.*(1 + k1*r.^2 + k2*r.^4 + k3*r.^6) + 2*p2*xp.*yp + p1*(r.^2 + 2*yp.^2));
val = sqrt(temp1.*temp1 + temp2.*temp2);
'fsolve"でシステムを解きます。
[coef, fval] = fsolve(@dist, zeros(5,1));
'coef'の値は、探している歪み係数です。元のセットに存在しない新しいポイント(xp、yp)の歪みを修正するには、次の式を使用します。
r = sqrt(xp.*xp + yp.*yp);
x_corr = xp.*(1 + k1*r.^2 + k2*r.^4 + k3*r.^6) + 2*p1*xp.*yp + p2*(r.^2 + 2*xp.^2);
y_corr = yp.*(1 + k1*r.^2 + k2*r.^4 + k3*r.^6) + 2*p2*xp.*yp + p1*(r.^2 + 2*yp.^2);
結果は画像の中央にシフトされ、上記で使用した係数でスケーリングされます。
ノート:
- 歪みは画像に対して対称であるため、座標は画像の中心にシフトする必要があります。
- 間隔[-1、1]に正規化する必要はありませんが、取得される歪み係数がほぼ同じ桁になるように正規化することは一般的です(ピクセルの2、4、6乗で動作)座標には非常に小さな係数が必要です)。
- この方法では、画像内の点が均一なグリッド内にある必要はありません。