openCV:如何使用getPerspectiveTransform

Dot*_*tan 3 python opencv

我有一个由尺寸矩阵表示的图像 n * n

我创建了一个转换矩阵

M = cv2.getPerspectiveTransform(...)
Run Code Online (Sandbox Code Playgroud)

我可以M使用定义的形状来变换图像

cv2.warpPerspective(image, M, image_shape)
Run Code Online (Sandbox Code Playgroud)

根据这个,我应该能够用一个点乘以矩阵并得到该点的新位置,改造后。我尝试过:

point = [100, 100, 0]
x, y, z = M.dot(point)
Run Code Online (Sandbox Code Playgroud)

但是我得到了错误的结果。(在这种情况下[112.5 12.5 0])

我究竟做错了什么?


为了更加清楚,这是我在做什么:

我有这张图片,线条和正方形在不同的图层上

翘曲之前

我使线条变形并得到以下信息:

弯曲的线

现在,我想获取放置正方形的坐标,如下所示:

预期

我所拥有的是我用于线条的扭曲矩阵以及第一张图片中正方形的坐标


注意:一种选择是创建一个带有单个点的图像,只需使用第一种方法将其变形并在新图像中查找非零单元格。我正在寻找比这更惯用的东西

alk*_*asm 6

齐次坐标的最后一个点永远不应为0,除非它专门引用了infinity处的点。为了您的目的,应该为1。您还应该缩放变换后的像素x并按y最后一个值缩放z。请在此处查看我的答案以获取详细说明。

对于一点:

point = np.array([100, 100])
homg_point = [point[0], point[1], 1] # homogeneous coords
transf_homg_point = M.dot(homg_point) # transform
transf_homg_point /= transf_homg_point[2] # scale
transf_point = transf_homg_point[:2] # remove Cartesian coords
Run Code Online (Sandbox Code Playgroud)

对于多个点(使用OpenCV编写点的标准方式):

points = np.array([[[100, 100]], [[150,100]], [[150,150]], [[150,100]]])
homg_points = np.array([[x, y, 1] for [[x, y]] in points]).T
transf_homg_points = M.dot(homg_points)
transf_homg_points /= transf_homg_points[2]
transf_points = np.array([[[x,y]] for [x, y] in transf_homg_points[:2].T])
Run Code Online (Sandbox Code Playgroud)

一个使用从OpenCV函数获取的点的最小示例:

import numpy as np 
import cv2

# generate random noise image, draw a white box
img = np.random.rand(512,512,3)
img[128:384, 64:196] = [1,1,1]

# create a Euclidean transformation which rotates by 30 deg + translates by (100,100)
theta = 30*np.pi/180
H = np.array([
    [ np.cos(theta),np.sin(theta),100.],
    [-np.sin(theta),np.cos(theta),100.],
    [0.,0.,1.]])

# find the white box
bin_img = cv2.inRange(img, np.ones(3), np.ones(3))
contour_points = cv2.findContours(bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1][0]

# transform the location of the box
homg_points = np.array([[x, y, 1] for [[x, y]] in contour_points]).T
transf_homg_points = H.dot(homg_points)
transf_homg_points /= transf_homg_points[2]
transf_rect = np.array([[[x,y]] for [x, y] in transf_homg_points[:2].T], dtype=np.int32)

# draw the transformed box as a green outline
cv2.polylines(img, [transf_rect], isClosed=True, color=[0,1,0], thickness=2)
Run Code Online (Sandbox Code Playgroud)

产生具有随机噪声,白色框和绿色轮廓的图像,该轮廓显示应用于框轮廓的变换。

变形轮廓