我有一个以一定 Angular 拍摄的棋盘图像。现在,我想扭曲透 View ,使棋盘图像再次看起来像是直接从上方拍摄的。

我知道我可以尝试在匹配点之间使用'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单应性,您无法像3D单应性那样将3x3矩阵分解为那些漂亮的直观组件。
  • 您只有一个矩阵-(这是几个未知矩阵的乘积)-就是这样。

  • 然而,

    OpenCV提供了getPerspectiveTransform函数,用于解决两个平面四边形之间的2D单应性的3x3透视矩阵(使用同构坐标系)。

    Link to documentation

    要使用此功能,
  • 在图像上找到棋盘的四个角。这些将成为您的源坐标。
  • 提供您选择的四个矩形角。这些将是您的目的地坐标。
  • 将源坐标和目标坐标传递到getPerspectiveTransform中,以生成3x3矩阵,该矩阵能够将您的棋盘变形为直立的矩形。

  • 注意事项:
  • 注意四个角的顺序。
  • 如果按顺时针顺序选择源坐标,则也需要按顺时针顺序选择目的地。
  • 同样,如果使用了逆时针顺序,请始终保持一致。
  • 同样,如果使用z顺序(左上,右上,左下,右下),请始终保持一致。
  • 如果不能始终如一地排序角点,将生成一个矩阵,该矩阵精确地(从数学上来说)执行点对点的对应关系,但不会生成可用的输出图像。
  • 可以任意选择目标矩形的纵横比。实际上,由于“这是2D单应性,而不是3D”,因此无法推断对象在世界坐标中的“原始纵横比”。
  • 09-10 06:48
    查看更多