问题描述
我需要在OpenCV中计算一个扭曲矩阵,代表围绕给定轴的旋转.
I need to calculate a warp matrix in OpenCV, representing the rotation around a given axis.
绕Z轴->简单明了:我使用标准旋转矩阵
Around Z axis -> straightforward: I use the standard rotation matrix
[cos(a) -sin(a) 0]
[sin(a) cos(a) 0]
[ 0 0 1]
对于其他旋转方式来说,这不是很明显,因此我尝试构建单应性,如Wikipedia所述:
This is not so obvious for other rotations, so I tried building a homography, as explained on Wikipedia:
H = R - t n^T / d
我尝试绕X轴简单旋转,并假设相机和图像之间的距离是图像高度的两倍.
I tried with a simple rotation around the X axis, and assuming the distance between the camera and the image is twice the image height.
R是标准旋转矩阵
[1 0 0]
[0 cos(a) -sin(a)]
[0 sin(a) cos(a)]
n是[0 0 1]
,因为相机正直接从(0,0,z_cam)中查看图像
n is [0 0 1]
because the camera is looking directly at the image from (0, 0, z_cam)
t是翻译,应为[0 -2h*(sin(a)) -2h*(1-cos(a))]
d是距离,每个定义为2h.
d is the distance, and it's 2h per definition.
因此,最终矩阵为:
[1 0 0]
[0 cos(a) 0]
[0 sin(a) 1]
看起来很不错,当a = 0时是一个标识,当a = pi时,它围绕x轴镜像.
which looks quite good, when a = 0 it's an identity, and when a = pi it's mirrored around the x axis.
但是,使用此矩阵进行透视变形并不会产生预期的结果,图像对于a的较小值只是太扭曲",并且很快消失.
And yet, using this matrix for a perspective warp doesn't yield the expected result, the image is just "too warped" for small values of a, and disappears very quickly.
那么,我在做什么错了?
So, what am I doing wrong?
(注意:我已经阅读了许多与此主题相关的问题和答案,但都朝着相反的方向:我不想分解单应性矩阵,而是 >构建,并进行3D转换,然后使用固定"相机或固定图像和移动相机.
(note: I've read many questions and answers about this subject, but all are going in the opposite direction: I don't want to decompose a homography matrix, but rather to build one, given a 3d transformation, and a "fixed" camera or a fixed image and a moving camera).
谢谢.
推荐答案
感谢这篇文章,终于找到了一种方法: https://plus.google.com/103190342755104432973/posts/NoXQtYQThgQ
Finally found a way, thanks to this post: https://plus.google.com/103190342755104432973/posts/NoXQtYQThgQ
我让OpenCV为我计算矩阵,但是我正在自己进行透视变换(发现实现起来比将所有内容放入cv :: Mat都容易实现)
I let OpenCV calculate the matrix for me, but I'm doing the perspective transform myself (found it easier to implement than putting everything into a 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());
这篇关于在OpenCV中绕x,y,z轴旋转图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!