基于已知相机方向的OpenCV透视变换

8
我正在开发一个项目,旨在基于已知的相机方位角移除图片的透视畸变。我的想法是可以创建一个基于相机已知的X、Y和Z方向的旋转矩阵。然后通过WarpPerspective方法将这些矩阵应用于图像上。
在我的Python脚本中,我创建了三个旋转矩阵,每个基于一个方向角度。我遇到了两个问题。首先,在将每个单独的矩阵加载到WarpPerspective方法中时,它似乎不能正确地工作。每当我在一个轴上扭曲图像时,图像会显着超出扭曲。只有当我将方位角限制在大约1度或更低时,图像内容才能被识别出来。
其次,如何将这三个旋转矩阵合并成一个要加载到WarpPerspective方法中的矩阵。我可以将一个3x3旋转矩阵导入该方法中吗?还是必须创建一个4x4投影矩阵?下面是我正在处理的代码。
感谢您的帮助。
CR
from numpy import *
import cv

#Sets angle of camera and converts to radians
x =  -14 * (pi/180)
y = 20 * (pi/180)
z =  15 * (pi/180)

#Creates the Rotational Matrices
rX = array([[1, 0, 0], [0, cos(x), -sin(x)], [0, sin(x), cos(x)]])
rY = array([[cos(y), 0, -sin(y)], [0, 1, 0], [sin(y), 0, cos(y)]])
rZ = array([[cos(z), sin(z), 0], [-sin(z), cos(z), 0], [0, 0, 1]])

#Converts to CVMat format
X = cv.fromarray(rX)
Y = cv.fromarray(rY)
Z = cv.fromarray(rZ)

#Imports image file and creates destination filespace
im = cv.LoadImage("reference_image.jpg")
dst = cv.CreateImage(cv.GetSize(im), cv.IPL_DEPTH_8U, 3)

#Warps Image
cv.WarpPerspective(im, dst, X)

#Display
cv.NamedWindow("distorted")
cv.ShowImage("distorted", im)
cv.NamedWindow("corrected")
cv.ShowImage("corrected", dst)
cv.WaitKey(0)
cv.DestroyWindow("distorted")
cv.DestroyWindow("corrected")
3个回答

5
您正在做几件事情不正确。 首先,没有摄像机模型,您无法在x或y轴上旋转。 想象一下视野非常宽的相机。 如果将其靠近一个物体并看到整个物体,但如果该物体旋转,则其边缘会以非常快的透视畸变向您飞来。 另一方面,视野小(想想望远镜)的透视畸变很小。 一个不错的起点是将图像平面设置为至少与相机距离相同,并将对象放在图像平面上。 这就是我在这个例子中所做的(c ++ openCV)
步骤如下:
1.构建旋转矩阵 2.将图像居中于原点 3.旋转图像 4.将图像沿z轴下移 5.乘以摄像机矩阵 6.扭曲视角
//1
float x =  -14 * (M_PI/180);
float y =  20 * (M_PI/180);
float z =  15 * (M_PI/180);

cv::Matx31f rot_vec(x,y,z);
cv::Matx33f rot_mat;
cv::Rodrigues(rot_vec, rot_mat); //converts to a rotation matrix

cv::Matx33f translation1(1,0,-image.cols/2,
                        0,1,-image.rows/2,
                        0,0,1);
rot_mat(0,2) = 0;
rot_mat(1,2) = 0;
rot_mat(2,2) = 1;

//2 and 3
cv::Matx33f trans = rot_mat*translation1;
//4
trans(2,2) += image.rows;
cv::Matx33f camera_mat(image.rows,0,image.rows/2,
                       0,image.rows,image.rows/2,
                       0,0,1);
//5
cv::Matx33f transform = camera_mat*trans;
//6
cv::Mat final;
cv::warpPerspective(image, final, cv::Mat(transform),image.size());

这段代码给我输出了这个结果。我发布这篇文章之前没有看到Franco的回答。他是完全正确的,使用FindHomography可以节省所有这些步骤。尽管如此,我仍希望这很有用。

camera_mat 中,我假设第一行或第二行中的 image.cols 是指图像的列数?可能只适用于正方形图像。 - oarfish

3
只知道图像旋转是不够的,除非您使用远心镜头拍摄图像,或者使用焦距非常长的长焦镜头拍摄(在这种情况下,图像几乎是正交的,没有透视畸变)。
此外,这并不是必要的。确实,您可以通过校准相机(即估计内部和外部参数以形成完整的相机投影矩阵)来撤消图像中一个平面的透视缩短。
但如果您能在图像中识别出一个四边形,它是现实世界中一个正方形(或已知宽高比的矩形)的图像,那么您可以轻松计算将正方形(矩形)映射到四边形的单应性矩阵,然后使用其逆矩阵进行变形,从而达到同样的效果。

也许我可以更清楚地阐述我正在尝试做的事情,因为我还没有确定实现它的方法。我正在尝试从视频序列中获取各种对象的标题测量值。由于摄像机的视角不同,真实的标题会发生改变。这是否可能? - eminentCodfish
我不知道什么是“标题测量”。你能否更新你的问题,提供一个样本视频,让我们更好地了解你想要做什么? - Francesco Callari

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接