我有一张从某个角度拍摄的棋盘图像。现在我想扭曲透视,让棋盘图像看起来就像是直接从上方拍摄的一样。
我知道我可以尝试在匹配点之间使用“findHomography”,但我想避免它并使用例如来自移动传感器的旋转数据自行构建单应矩阵。我校准了我的相机以获得内在参数。然后假设下图是围绕 x 轴以约 60 度角拍摄的。我认为我所要做的就是将相机矩阵与旋转矩阵相乘以获得单应性矩阵。我尝试使用以下代码,但看起来我没有正确理解某些内容,因为它没有按预期工作(结果图像完全是黑色或白色。
import cv2
import numpy as np
import math
camera_matrix = np.array([[ 5.7415988502105745e+02, 0., 2.3986181527877352e+02],
[0., 5.7473682183375217e+02, 3.1723734404756237e+02],
[0., 0., 1.]])
distortion_coefficients = np.array([ 1.8662919398453856e-01, -7.9649812697463640e-01,
1.8178068172317731e-03, -2.4296638847737923e-03,
7.0519002388825025e-01 ])
theta = math.radians(60)
rotx = np.array([[1, 0, 0],
[0, math.cos(theta), -math.sin(theta)],
[0, math.sin(theta), math.cos(theta)]])
homography = np.dot(camera_matrix, rotx)
im = cv2.imread('data/chess1.jpg')
gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
im_warped = cv2.warpPerspective(gray, homography, (480, 640), flags=cv2.WARP_INVERSE_MAP)
cv2.imshow('image', im_warped)
cv2.waitKey()
pass
校准后我还有失真系数。如何将这些合并到代码中以改进结果?
最佳答案
这个答案晚了好几年,但在这里......
(免责声明:我在此答案中使用的术语可能不准确或不正确。请务必从其他更可靠的来源查找此主题。)
记住:
- 因为您只有一个图像( View ),所以您只能计算 2D 单应性(一个 2D View 和另一个 2D View 之间的透视对应),而不是完整的 3D 单应性。
- 因此,您无法对 3D 单应性(旋转矩阵、平移矩阵、焦距等)有很好的直观理解。<
- 我们所说的是,对于 2D 单应性,您无法将 3x3 矩阵分解为 像 3D 单应性那样的直观组件。
- 你有一个矩阵——(它是你不知道的几个矩阵的乘积)——就是这样。
但是,
OpenCV 提供了一个getPerspectiveTransform
函数,它解决了两个平面四边形之间的 2D 单应性的 3x3 透视矩阵(使用齐次坐标系)。
要使用这个功能,
- 在图像上找到棋盘的四个角。这些将是您的源坐标。
- 提供您选择的四个矩形角。这些将是您的目的地坐标。
- 将源坐标和目标坐标传递到
getPerspectiveTransform
以生成一个 3x3 矩阵,该矩阵能够将您的棋盘变形为直立矩形。
要记住的注意事项:
注意四个角的顺序。
- 如果源坐标按顺时针顺序拾取,则目标坐标也需要按顺时针顺序拾取。
- 同样,如果使用逆时针顺序,请始终如一。
- 同样,如果使用 z 顺序(左上、右上、左下、右下),请始终如一。
- 未能一致地对角排序将生成一个矩阵,该矩阵精确地执行点对点对应(从数学上讲),但不会生成可用的输出图像。
目标矩形的纵横比可以任意选择。事实上,不可能推导出物体在世界坐标中的“原始纵横比”,因为“这是 2D 单应性,而不是 3D”。
关于image-processing - Warping Perspective 使用任意旋转角度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13040288/