web-dev-qa-db-ja.com

ロール-ピッチ-ヨー角を使用して画像を変換する(画像補正)

私は、モバイルカメラプラットフォームから撮影した画像を修正する必要があるアプリケーションに取り組んでいます。プラットフォームはロール、ピッチ、ヨーの角度を測定します。この情報から何らかの変換を行って、画像が真上から撮影されたように見せたいと思います。

つまり、カメラの向きを変えて遠くから撮影した、地面に平らに横たわっている完全な正方形を変換して、後で正方形が完全に対称になるようにします。

私はOpenCV(C++)とMatlabを介してこれを実行しようとしていますが、これがどのように実行されるかについて基本的な何かが欠けているようです。

Matlabで、私は次のことを試しました。

%% Transform perspective
img = imread('my_favourite_image.jpg');
R = R_z(yaw_angle)*R_y(pitch_angle)*R_x(roll_angle);
tform = projective2d(R);   
outputImage = imwarp(img,tform);
figure(1), imshow(outputImage);

ここで、R_z/y/xは標準の回転行列(度で実装)です。

一部のヨー回転では、すべて正常に機能します。

R = R_z(10)*R_y(0)*R_x(0);

結果が得られます:

Image rotated 10 degrees about the Z-image axis

X軸またはY軸を中心に同じ量だけ画像を回転させようとすると、次のような結果が得られます。

R = R_z(10)*R_y(0)*R_x(10);

Image rotated 10 degrees about the X-image axis

しかし、10度回転させて、いくつかの巨大な数で割ると、問題なく見え始めます。しかし、繰り返しになりますが、これはこれまで研究価値がまったくない結果です。

R = R_z(10)*R_y(0)*R_x(10/1000);

Image rotated 10/1000 degrees about the X-image axis

X軸またはY軸を中心に回転すると、変換がワイルドになる理由を誰かが理解するのを手伝ってくれませんか?乱数やその他の手品で割らずにこれを解決する方法はありますか?これは、ある種のオイラーパラメーターを使用して解決できるものでしょうか?どんな助けでも大歓迎です!

更新:完全なセットアップと測定

完全を期すために、完全なテストコードと初期イメージ、およびプラットフォームのオイラー角が追加されました。

コード:

%% Transform perspective
function [] = main()
    img = imread('some_image.jpg');
    R = R_z(0)*R_y(0)*R_x(10);
    tform = projective2d(R);   
    outputImage = imwarp(img,tform);
    figure(1), imshow(outputImage);
end

%% Matrix for Yaw-rotation about the Z-axis
function [R] = R_z(psi)
    R = [cosd(psi) -sind(psi) 0;
         sind(psi)  cosd(psi) 0;
         0          0         1];
end

%% Matrix for Pitch-rotation about the Y-axis
function [R] = R_y(theta)
    R = [cosd(theta)    0   sind(theta);
         0              1   0          ;
         -sind(theta)   0   cosd(theta)     ];
end

%% Matrix for Roll-rotation about the X-axis
function [R] = R_x(phi)
    R = [1  0           0;
         0  cosd(phi)   -sind(phi);
         0  sind(phi)   cosd(phi)];
end

初期画像:

enter image description here

BODY座標フレームでのカメラプラットフォームの測定:

Roll:     -10
Pitch:    -30
Yaw:      166 (angular deviation from north)

私が理解していることから、ヨー角は変換に直接関係していません。しかし、私はこれについて間違っているかもしれません。

追加情報:

セットアップが使用される環境には、参照として確実に使用できる線(海の写真)が含まれていないことを指定したいと思います(通常、地平線は写真に表​​示されません)。また、初期画像の正方形は、変換が正しいかどうかを確認するための尺度としてのみ使用され、実際のシナリオでは存在しません。

16
Tormod Haugene

つまり、これが私がやったことです。実際に3D画像を扱っていない限り、写真の遠近法を修正することは2D操作であると考えました。これを念頭に置いて、変換行列のz軸の値を0と1に置き換え、2Dアフィン変換を画像に適用しました。

測定されたロール= -10およびピッチ= -30での初期画像(最初の投稿を参照)の回転は、次の方法で行われました。

R_rotation = R_y(-60)*R_x(10); 
R_2d       = [   R_rot(1,1)  R_rot(1,2) 0; 
                 R_rot(2,1)  R_rot(2,2) 0;
                 0           0          1    ] 

これは、カメラがシーンの上に配置され、真下を向く仮想カメラの向きにカメラプラットフォームが回転することを意味します。上記のマトリックスのロールとピッチに使用されている値に注意してください。

さらに、プラットフォームの見出しに合わせて画像を回転させると、z軸を中心とした回転が追加され、次のようになります。

R_rotation = R_y(-60)*R_x(10)*R_z(some_heading); 
R_2d       = [   R_rot(1,1)  R_rot(1,2) 0; 
                 R_rot(2,1)  R_rot(2,2) 0;
                 0           0          1    ] 

これは実際の画像を変更するのではなく、回転するだけであることに注意してください。

その結果、Y軸とX軸を中心に回転した最初の画像は次のようになります。

enter image description here

上に表示されているように、この変換を行うための完全なコードは次のとおりです。

% Load image
img = imread('initial_image.jpg'); 

% Full rotation matrix. Z-axis included, but not used.
R_rot = R_y(-60)*R_x(10)*R_z(0); 

% Strip the values related to the Z-axis from R_rot
R_2d  = [   R_rot(1,1)  R_rot(1,2) 0; 
            R_rot(2,1)  R_rot(2,2) 0;
            0           0          1    ]; 

% Generate transformation matrix, and warp (matlab syntax)
tform = affine2d(R_2d);
outputImage = imwarp(img,tform);

% Display image
figure(1), imshow(outputImage);



%*** Rotation Matrix Functions ***%

%% Matrix for Yaw-rotation about the Z-axis
function [R] = R_z(psi)
    R = [cosd(psi) -sind(psi) 0;
         sind(psi)  cosd(psi) 0;
         0          0         1];
end

%% Matrix for Pitch-rotation about the Y-axis
function [R] = R_y(theta)
    R = [cosd(theta)    0   sind(theta);
         0              1   0          ;
         -sind(theta)   0   cosd(theta)     ];
end

%% Matrix for Roll-rotation about the X-axis
function [R] = R_x(phi)
    R = [1  0           0;
         0  cosd(phi)   -sind(phi);
         0  sind(phi)   cosd(phi)];
end

サポートありがとうございます、これが誰かに役立つことを願っています!

7
Tormod Haugene

この方法で変換を導き出すことができると思います。

1)4つの3DポイントA(-1、-1,0)、B(1、-1,0)、C(1,1,0)、およびD(-1,1,0)があるとします。あなたは4つの非同一直線上の点を取ることができます。それらは画像とは関係ありません。

2)変換行列があるので、ポイント座標に変換行列を掛けてカメラを設定できます。また、カメラの位置/方向を基準にした3D座標を取得します。

3)ポイントをスクリーン平面に投影する必要があります。最も簡単な方法は、正投影を使用することです(単に深度座標を無視します)。この段階では、変換されたポイントの2D投影があります。

4)2セットの2Dポイント座標(3番目の座標を含まないステップ1のセットとステップ3のセット)ができたら、標準的な方法でホモグラフィ行列を計算できます。

5)画像に逆ホモグラフィ変換を適用します。

3
Andrey Smorodov

ホモグラフィを推定する必要があります。既成のMatlabソリューションについては、関数vgg_H_from_x_lin.m from http://www.robots.ox.ac.uk/~vgg/hzbook/code/ を参照してください。

理論については、 http://szeliski.org/Book/ または http://programmingcomputervision.com)の第3章で無料で入手できるようなコンピュータビジョンの教科書を掘り下げてください。 /downloads/ProgrammingComputerVision_CCdraft.pdf

2
YXD

カメラのパラメータを誤解しているために私の答えは正しくないかもしれませんが、ヨー/ピッチ/ロールがオブジェクトの位置に関連しているかどうか疑問に思っていました。 一般的な回転 の式を使用しましたが、コードは次のとおりです(回転関数_R_x_、_R_y_、および_R_z_はあなたからコピーされました。ここに貼り付けます)

_close all
file='http://i.stack.imgur.com/m5e01.jpg'; % original image
I=imread(file);

R_rot = R_x(-10)*R_y(-30)*R_z(166);
R_rot = inv(R_rot);

R_2d  = [   R_rot(1,1)  R_rot(1,2) 0; 
            R_rot(2,1)  R_rot(2,2) 0;
            0           0          1    ]; 


T = maketform('affine',R_2d);

transformedI = imtransform(I,T);
        figure, imshow(I), figure, imshow(transformedI)
_

結果:

enter image description here

これは、頭の中で「正しい」位置合わせを行うために、まだ回転操作が必要であることを示しています(ただし、カメラの頭の中で正しい位置である必要はおそらくありません)。そこで、R_rot = inv(R_rot);R_rot = inv(R_rot)*R_x(-5)*R_y(25)*R_z(180);に変更すると、次のようになります。

enter image description here

あなたが望むもののようによく見えます。ありがとう。

2
lennon310