matlab 使用滚转-俯仰-偏航角变换图像(图像校正)

k2arahey  于 2023-05-29  发布在  Matlab
关注(0)|答案(5)|浏览(423)

我正在开发一个应用程序,我需要纠正从移动的相机平台拍摄的图像。这个平台可以测量滚动、俯仰和偏航角,我想让它看起来像是从正上方拍摄的,通过对这些信息进行某种转换。
换句话说,我想要一个完美的正方形平放在地上,从远处用某种相机方向拍摄,经过改造,使正方形完全对称。
我一直试图通过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);

这给出了结果:

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

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

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

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

有人能帮我理解为什么绕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

初始图像:

BODY坐标系中的摄像机平台测量值:

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

据我所知,偏航角与转换没有直接关系。然而,我可能在这一点上错了。

附加信息:

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

cnh2zyt3

cnh2zyt31#

所以,这就是我最终所做的:我想,除非你实际上是在处理3D图像,否则纠正照片的视角是一个2D操作。考虑到这一点,我用0和1替换了变换矩阵的z轴值,并对图像应用了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轴旋转的初始图像看起来如下所示:

执行此转换的完整代码如下所示:

% 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

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

7cwmlq89

7cwmlq892#

我想你可以这样推导转换:
1)假设你有四个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点坐标(第1步中没有第3个坐标的坐标组和第3步中的坐标组),你就可以用标准的方法计算单应矩阵。
5)对图像应用逆同相变换。

jaql4c8m

jaql4c8m3#

你需要估计一个单应性。有关现成的Matlab解决方案,请参见http://www.robots.ox.ac.uk/~vgg/hzbook/code/中的函数vgg_H_from_x_lin.m
对于理论深入研究计算机视觉教科书,例如在http://szeliski.org/Book/http://programmingcomputervision.com/downloads/ProgrammingComputerVision_CCdraft.pdf的第3章中免费提供的教科书

falq053o

falq053o4#

也许我的答案是不正确的,由于我的误解的相机参数,但我想知道是否偏航/俯仰/滚动是相对于您的对象的位置。我使用了一般旋转的公式,我的代码如下(旋转函数R_xR_yR_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)

结果:

这表明您仍然需要一些旋转操作来获得您心目中的“正确”对齐(但可能不需要相机心目中的正确位置)。所以我把R_rot = inv(R_rot);改为R_rot = inv(R_rot)*R_x(-5)*R_y(25)*R_z(180);,现在它给了我:

看起来更像你想要的。谢谢。

u0sqgete

u0sqgete5#

你将需要你的相机的焦距(->视角)来正确地解决非倾斜失真。
我知道这已经晚了几年,但如果有人来了,我根据经验分析了图像,这是我的发现:相机的焦距为90 mm(基于36 mm宽度),其等于22°对角视角。倾斜大约为-28.5°。滚动-10°是正确的,但需要确保旋转顺序是先俯仰,然后滚动。
这是你的结果应该看起来像:https://i.stack.imgur.com/vDIHv.jpg
正方形实际上是完全正方形:https://i.stack.imgur.com/1po3k.png

相关问题