来自 cv2.getPerspectiveTransform 的矩阵没有适当地转换点

Matrix from cv2.getPerspectiveTransform does not transform points appropriately

function cv2.getPerspectiveTransform 从四对对应点计算透视变换的 3x3 矩阵。

我有一个 image 的池子 table 有透视变形,在手动选择四个角时(按左上、右上、左下、右下的顺序), cv2.getPerspectiveTransform 计算将池 table 的角变换为显示 window 的角所需的 3x3 矩阵。然后我应用 cv2.warpPerspective 用计算出的矩阵去扭曲池 table 图像。

我想使用此矩阵将单个点从失真池 table 图像转换为未失真池 table 图像。当我尝试通过将 3x3 变换矩阵乘以角坐标(根据链接文档写为 (x, y, 1)),用变换矩阵变换扭曲池 table 的相同手动选择角时,转换后的角点与预期的 window 显示的角点不匹配(如下所示)。也就是说,红点应该在图像的角落,但不是。

谁能解释一下为什么转换后的角点与显示的 window 的角点不匹配?

下面附上我的代码:

import cv2
import numpy as np


def mouse_position(event, mouse_x, mouse_y, flags, param):
    global corners
    if event == cv2.EVENT_LBUTTONDOWN:
        print(f"Corner #{len(corners) + 1}: {(mouse_x, mouse_y)}")
        corners.append((mouse_x, mouse_y))


corners = []
img = cv2.imread("Assets/Setup.jpg")
cv2.namedWindow("Select Corners of Pool Table")
cv2.setMouseCallback("Select Corners of Pool Table", mouse_position)
while len(corners) < 4:
    cv2.imshow("Select Corners of Pool Table", img)
    if cv2.waitKey(1) != -1:
        print("Exiting program.")
        cv2.destroyAllWindows()
        exit(0)
cv2.destroyAllWindows()
corners = np.array(corners, dtype="float32")
height, width = img.shape[:2]
transform_matrix = cv2.getPerspectiveTransform(corners, np.array([(0, 0), (width, 0), (0, height), (width, height)],
                                                                 dtype="float32"))
undistorted_image = cv2.warpPerspective(img, transform_matrix, (width, height))
transformed_corners = (transform_matrix @ np.hstack((corners, np.ones((corners.shape[0], 1)))).T).T.astype(int)
for corner in transformed_corners:
    cv2.circle(undistorted_image, (corner[0], corner[1]), 30, (0, 0, 255), -1)
cv2.imshow("Frame", undistorted_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

您可以使用cv2.perspectiveTransform转换点。

如果您想通过将 (x,y,1) 与 3x3 变换矩阵相乘来手动执行此操作,请确保将结果除以其 z 值,因此它将是 (x',y' ,1) 并且是齐次点表示。