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

时间:2012-09-05 19:31:48

标签: python opencv computer-vision

我正在开发一个项目,该项目试图根据相机的已知方向从图像中消除透视失真。我的想法是我可以根据摄像机的已知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 个答案:

答案 0 :(得分:3)

只要知道旋转是不够的,除非使用远心镜头拍摄图像,或使用长焦距的远摄镜头(在这种情况下图像几乎是正交的,并且没有透视失真)。

此外,没有必要。确实,您可以通过校准相机来撤消图像中一个平面的透视缩短(即估计内部和外部参数以形成完整的相机投影矩阵)。

但是,如果您可以在图像中识别出四边形,即实际正方形(或具有已知宽度/高度比的矩形)的图像,则可以更简单地获得相同的结果。如果你能做到这一点,你可以简单地计算将方形(矩形)映射到四边形的单应矩阵,然后使用它的逆变形。

答案 1 :(得分:3)

你做错了几件事。首先,如果没有相机型号,则无法在x或y轴上旋转。想象一下具有令人难以置信的宽视野的相机。你可以把它保持在一个物体附近并看到整个物体,但是如果那个物体旋转它的边缘似乎会很快地向你飞向强烈的透视扭曲。另一方面,一个小视场(想想望远镜)的透视失真非常小。一个好的起点是将图像平面设置为至少与相机一样远,因为它很宽并且将对象放在图像平面上。这就是我在这个例子中所做的(c ++ openCV)

步骤

  1. 构建旋转矩阵
  2. 将图像置于原点
  3. 旋转图像
  4. 沿z轴向下移动图像
  5. 乘以相机矩阵
  6. 扭曲观点

  7. //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());
    

    这段代码给了我这个输出

    enter image description here

    在我发布之前,我没有看到Franco的回答。他完全正确,使用FindHomography可以为您节省所有这些步骤。我仍然希望这很有用。

答案 2 :(得分:0)

Wikipedia page on rotation matrices显示了如何将三个基本旋转矩阵合并为一个。