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

标签 python opencv computer-vision

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

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

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

感谢您的帮助。

回复

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")

最佳答案

你做错了几件事。首先,没有相机模型就不能在 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());

这段代码给了我这个输出

enter image description here

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

关于python - 基于已知相机方向的 OpenCV 中的透视变形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12288473/

相关文章:

python - 在 Python 中初始化二维数组

opencv - Opencv videoCapture() 中的 Gstreamer 管道

机器学习中的 Python 问题

python - 当我输入用户名时,未显示 "good job"

c++ - 这是向容器添加元素的正确方法吗?

python - 为什么我们将图像归一化为mean=0.5, std=0.5?

python - 从直方图曲线中选择最佳值范围

python - 如何在 python 中将黑白图像转换为 3 维数组?

python - 从 Python 调用 FSCTL_CREATE_OR_GET_OBJECT_ID

c++ - 单个多对象卡尔曼滤波器与多个单对象卡尔曼滤波器(复数)