【问题标题】:Rotate image around x, y, z axis in OpenCV在 OpenCV 中围绕 x、y、z 轴旋转图像
【发布时间】:2013-09-30 12:00:49
【问题描述】:

我需要在 OpenCV 中计算一个扭曲矩阵,表示围绕给定轴的旋转。

围绕 Z 轴 -> 直截了当:我使用标准旋转矩阵

[cos(a) -sin(a) 0]
[sin(a)  cos(a) 0]
[    0       0  1]

这对于其他旋转不是很明显,所以我尝试构建一个单应性,如 Wikipedia 上所述:

H = R - t n^T / d

我尝试绕 X 轴简单旋转,并假设相机和图像之间的距离是图像高度的两倍。

R是标准旋转矩阵

[1      0       0]
[0 cos(a) -sin(a)]
[0 sin(a)  cos(a)]

n 是[0 0 1]因为相机直接从 (0, 0, z_cam) 看图像

t是翻译,应该是[0 -2h*(sin(a)) -2h*(1-cos(a))]

d 是距离,每个定义是 2h。

所以,最终的矩阵是:

[1      0 0]
[0 cos(a) 0]
[0 sin(a) 1]

看起来相当不错,当 a = 0 时它是一个标识,而当 a = pi 时它围绕 x 轴镜像。

然而,使用这个矩阵进行透视扭曲并不能产生预期的结果,对于较小的 a 值,图像只是“过于扭曲”,并且很快就会消失。

那么,我做错了什么?

(注意:我已经阅读了很多关于这个主题的问题和答案,但都朝着相反的方向发展:我不想分解单应矩阵,而是要构建一个,给定一个 3d 变换和一个“固定”相机或一个固定图像和一个移动相机)。

谢谢。

【问题讨论】:

  • 你的坐标系是怎么设置的?
  • (0,0) 是左上角,x=colum,y=row。基本上,图像是使用 cv::imread 加载的,并且没有应用任何转换。
  • 我认为你应该使用轴角表示,然后使用指数映射来获得你的旋转矩阵see this link for a brief explanation
  • Grazie Mille,卡罗。 :-) 但我试图保持简单,整个转换只使用 3x3 矩阵。也许我在这里找到了一些东西:jepsonsblog.blogspot.in/2012/11/…
  • di niente,但通过这种方式(使用偏航、俯仰和滚动)您可以停留在gimbal lock。使用指数映射来避免这个问题。您只需要旋转轴(如果您想绕 x 轴旋转,则需要一个单位向量,例如 (1,0,0))和一个角度。

标签: opencv matrix rotation


【解决方案1】:

终于找到方法了,感谢这个帖子:https://plus.google.com/103190342755104432973/posts/NoXQtYQThgQ

我让 OpenCV 为我计算矩阵,但我自己进行透视变换(发现比将所有内容都放入 cv::Mat 更容易实现)

float rotx, roty, rotz; // set these first
int f = 2; // this is also configurable, f=2 should be about 50mm focal length

int h = img.rows;
int w = img.cols;

float cx = cosf(rotx), sx = sinf(rotx);
float cy = cosf(roty), sy = sinf(roty);
float cz = cosf(rotz), sz = sinf(rotz);

float roto[3][2] = { // last column not needed, our vector has z=0
    { cz * cy, cz * sy * sx - sz * cx },
    { sz * cy, sz * sy * sx + cz * cx },
    { -sy, cy * sx }
};

float pt[4][2] = {{ -w / 2, -h / 2 }, { w / 2, -h / 2 }, { w / 2, h / 2 }, { -w / 2, h / 2 }};
float ptt[4][2];
for (int i = 0; i < 4; i++) {
    float pz = pt[i][0] * roto[2][0] + pt[i][1] * roto[2][1];
    ptt[i][0] = w / 2 + (pt[i][0] * roto[0][0] + pt[i][1] * roto[0][1]) * f * h / (f * h + pz);
    ptt[i][1] = h / 2 + (pt[i][0] * roto[1][0] + pt[i][1] * roto[1][1]) * f * h / (f * h + pz);
}

cv::Mat in_pt = (cv::Mat_<float>(4, 2) << 0, 0, w, 0, w, h, 0, h);
cv::Mat out_pt = (cv::Mat_<float>(4, 2) << ptt[0][0], ptt[0][1],
    ptt[1][0], ptt[1][1], ptt[2][0], ptt[2][1], ptt[3][0], ptt[3][1]);

cv::Mat transform = cv::getPerspectiveTransform(in_pt, out_pt);

cv::Mat img_in = img.clone();
cv::warpPerspective(img_in, img, transform, img_in.size());

【讨论】:

    猜你喜欢
    • 2021-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-30
    • 2012-05-09
    • 2017-07-11
    • 1970-01-01
    相关资源
    最近更新 更多