Python 基于已知摄像机方向的OpenCV透视扭曲

Python 基于已知摄像机方向的OpenCV透视扭曲,python,opencv,computer-vision,Python,Opencv,Computer Vision,我正在进行一个项目,该项目试图根据已知的摄像机方向消除图像中的透视失真。我的想法是,我可以根据相机的已知X、Y和Z方向创建旋转矩阵。然后,我可以通过透视法将这些矩阵应用于图像 在我的脚本(用Python编写)中,我创建了三个旋转矩阵,每个矩阵基于一个方向角。我已经在两个问题上陷入困境。首先,当我将每个矩阵加载到WarpPerspective方法中时,它似乎无法正常工作。每当我在一个轴上扭曲一个图像时,它就会明显地使图像过度扭曲。只有当我将方向角限制在1度或更小时,图像的内容才可识别 其次,如何将

我正在进行一个项目,该项目试图根据已知的摄像机方向消除图像中的透视失真。我的想法是,我可以根据相机的已知X、Y和Z方向创建旋转矩阵。然后,我可以通过透视法将这些矩阵应用于图像

在我的脚本(用Python编写)中,我创建了三个旋转矩阵,每个矩阵基于一个方向角。我已经在两个问题上陷入困境。首先,当我将每个矩阵加载到WarpPerspective方法中时,它似乎无法正常工作。每当我在一个轴上扭曲一个图像时,它就会明显地使图像过度扭曲。只有当我将方向角限制在1度或更小时,图像的内容才可识别

其次,如何将三个旋转矩阵组合成一个矩阵,以加载到透视方法中。我可以将一个3x3旋转矩阵导入到该方法中,还是必须创建一个4x4投影矩阵。下面是我正在编写的代码

谢谢你的帮助


显示了如何将三个基本旋转矩阵组合为一个。

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

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


但是,如果你能在图像中识别出一个四边形,它是真实世界中的正方形(或具有已知宽高比的矩形)的图像,那么你可以更简单地获得相同的结果。如果你能做到这一点,你就可以简单地计算将正方形(矩形)映射到四边形的单应矩阵,然后使用它的逆矩阵进行扭曲。

你做错了几件事。首先,如果没有摄影机模型,则无法在x轴或y轴上旋转。想象一个拥有难以置信的广阔视野的相机。你可以把它举得离一个物体很近,然后看到整个物体,但是如果这个物体旋转,它的边缘看起来会很快向你飞来,并伴随着强烈的透视失真。另一方面,小视场(比如望远镜)的透视失真很小。一个很好的起点是设置图像平面,使其至少与相机的宽度一样远,并将对象放在图像平面上。这就是我在本例中所做的(c++openCV)

步骤是

  • 构造一个旋转矩阵
  • 将图像居中于原点
  • 旋转图像
  • 沿z轴向下移动图像
  • 乘以相机矩阵
  • 扭曲透视图

  • 这个代码给了我这个输出


    直到我贴出这个,我才看到佛朗哥的答案。他完全正确,使用FindHomography可以节省所有这些步骤。不过我还是希望这是有用的。

    也许我可以更清楚地说明我想做什么,因为我还没有找到实现它的方法。我要做的是从视频序列中获取各种物体的航向测量值。真实标题会根据相机的透视图进行更改。有没有可能我不知道什么是“航向测量”。你能用一段你想做什么的视频来更新你的问题吗?
    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")
    
    //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());