使用Roll-Pitch-Yaw角度变换图像(图像校正)

Tor*_*ene 16 matlab opencv image-processing euler-angles image-rotation

我正在开发一个应用程序,我需要纠正从移动相机平台拍摄的图像.平台测量滚动角,俯仰角和偏航角,我希望通过这种信息的某种变换使图像看起来像是从正上方拍摄的.

换句话说,我想要一个平躺在地面上的完美广场,从远处拍摄一些相机方向,进行转换,以便广场在之后完全对称.

我一直试图通过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);
Run Code Online (Sandbox Code Playgroud)

其中R_z/y/x是标准旋转矩阵(用度数实现).

对于某些偏航旋转,一切正常:

R = R_z(10)*R_y(0)*R_x(0);
Run Code Online (Sandbox Code Playgroud)

结果如下:

图像围绕Z轴图像旋转10度

如果我尝试围绕X轴或Y轴旋转相同数量的图像,我会得到如下结果:

R = R_z(10)*R_y(0)*R_x(10);
Run Code Online (Sandbox Code Playgroud)

图像围绕X轴图像旋转10度

但是,如果我旋转10度,除以一些巨大的数字,它开始看起来不错.但话说回来,这是一个没有研究价值的结果:

R = R_z(10)*R_y(0)*R_x(10/1000);
Run Code Online (Sandbox Code Playgroud)

图像围绕X轴图像旋转10/1000度

有人可以帮助我理解为什么围绕X轴或Y轴旋转会使转换变得疯狂吗?有没有办法解决这个问题而不用一些随机数和其他魔术技巧?这可能是某些可以使用某种Euler参数解决的东西吗?任何帮助将非常感谢!

更新:完整设置和测量

为了完整性,添加了完整的测试代码和初始图像,以及平台Euler角度:

码:

%% 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
Run Code Online (Sandbox Code Playgroud)

初始图片:

在此输入图像描述

BODY坐标系中的相机平台测量:

Roll:     -10
Pitch:    -30
Yaw:      166 (angular deviation from north)
Run Code Online (Sandbox Code Playgroud)

据我所知,偏航角与变换没有直接关系.但是,我可能错了.

附加信息:

我想指定使用设置的环境不包含可以可靠地用作参考的线(海洋照片)(地平线通常不在图片中).此外,初始图像中的正方形仅用作衡量转换是否正确的度量,并且不会出现在真实场景中.

Tor*_*ene 7

所以,这就是我最终要做的事情:我认为除非您实际处理3D图像,否则纠正照片的视角是2D操作.考虑到这一点,我用零和1替换了变换矩阵的z轴值,并对图像应用了2D仿射变换.

使用测量的Roll = -10和Pitch = -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    ] 
Run Code Online (Sandbox Code Playgroud)

这意味着将相机平台旋转到虚拟相机方向,其中相机被放置在场景上方,指向正下方.请注意上面矩阵中用于滚动和俯仰的值.

此外,如果旋转图像使其与平台标题对齐,则可能会添加围绕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    ] 
Run Code Online (Sandbox Code Playgroud)

请注意,这不会更改实际图像 - 它只会旋转它.

结果,围绕Y轴和X轴旋转的初始图像看起来像:

在此输入图像描述

如上所示,执行此转换的完整代码是:

% 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
Run Code Online (Sandbox Code Playgroud)

谢谢你的支持,希望对大家有所帮助!