我有两个形状或坐标系统,我希望能够将点从一个系统转换到另一个系统。
我发现,如果这些形状是四边形,并且我有4对对应的点,那么我可以计算一个变换矩阵,然后用该矩阵将Shape B中的任意一点计算到它在Shape A中的相应坐标上。

下面是进行此计算的工作python代码:
import numpy as np
import cv2
shape_a_points = np.array([
[0.6, 0],
[1, 0.75],
[0.8, 1],
[0.5, 0.6]
], dtype="float32")
shape_b_points = np.array([
[0, 0],
[1, 0],
[1, 1],
[0, 1],
], dtype="float32")
test_points = [0.5, 0.5]
matrix = cv2.getPerspectiveTransform(shape_b_points, shape_a_points)
print(matrix)
result = cv2.perspectiveTransform(np.array([[test_points]], dtype="float32"), matrix)
print(result)如果运行此代码,您将看到Shape B上(中间)的测试点(0.5,0.5)在Shape A上显示为(0.73,0.67),这在视觉上是正确的。
,但是,如果形状更复杂,我能做什么。比如4+N顶点,和4+N对对应的点?或者更复杂的是,如果存在形状上的曲线呢?
例如:

发布于 2022-01-21 13:30:41
谢谢您为我指明了正确的方向。
在使用OpenCV ThinPlateSplineShapeTransformer进行转换时,我发现了非常好的结果。
下面是我的示例脚本。请注意,我有7对点。“匹配”只是一个7的列表(从Shape A匹配告诉脚本点#1,从Shape B...etc告诉#1 )。
import numpy as np
import cv2
number_of_points = 7
shape_a_points = np.array([
[0.6, 0],
[1, 0.75],
[0.8, 1],
[0.5, 0.6],
[0.75, 0],
[1, 0],
[1, 0.25]
], dtype="float32").reshape((-1, number_of_points, 2))
shape_b_points = np.array([
[0, 0],
[1, 0],
[1, 1],
[0, 1],
[0.25, 0],
[0.5, 0],
[0.75, 0]
], dtype="float32").reshape((-1, number_of_points, 2))
test_points = [0.5, 0.5]
matches = [cv2.DMatch(i, i, 0) for i in range(number_of_points)]
tps = cv2.createThinPlateSplineShapeTransformer()
tps.estimateTransformation(shape_b_points, shape_a_points, matches)
M = tps.applyTransformation(np.array([[test_points]], dtype="float32"))
print(M[1])我不知道为什么你需要重塑数组;“你只是做”,否则它将无法工作。
如果有人想要使用它,我也把它放在一个简单的类中:
import cv2
import numpy as np
class transform:
def __init__(self, points_a, points_b):
assert len(points_a) == len(points_b), "Number of points in set A and set B should be same count"
matches = [cv2.DMatch(i, i, 0) for i in range(len(points_a))]
self.tps = cv2.createThinPlateSplineShapeTransformer()
self.tps.estimateTransformation(np.array(points_b, dtype="float32").reshape((-1, len(points_a), 2)),
np.array(points_a, dtype="float32").reshape((-1, len(points_a), 2)), matches)
def transformPoint(self, point):
result = self.tps.applyTransformation(np.array([[point]], dtype="float32"))
return result[1][0][0]发布于 2022-01-21 13:04:58
如果这两种形状是通过透视变换联系起来的,那么任何四个点都会导致相同的变换,至少只要它们不是共线的。从理论上讲,您可以选择任何四个这样的点,而其余的应该只起作用。
在实践中,数字考虑可能会起作用。如果你选择彼此非常接近的点,那么它们的位置上的小错误将导致更大的误差远离这些点。您可能会做一些涉及错误间隔的复杂分析,但根据经验,我会尝试在转换的输入和输出端的任意两个点之间设定很长的距离。
An answer from me on Math Exchange解释了对点的透视图转换的定义中的计算类型。这可能有助于理解数字4的来源。
如果您有4对以上的点,并且使用其中任何四个点定义转换都不能正确地转换其余的点,那么您很可能处于另外两个用例中的一个。
或者您确实在寻找透视图转换,但输入数据却很差。您可能有特征检测的位置,而且可能不精确。有些特性甚至可能间接匹配。因此,在这种情况下,您将寻找最好的转换来描述您的数据与小错误。你的问题听起来不像是你的用例,所以我不会详细说明。
我们的“你”有一个不是透视变换的转变。尤其是,任何将直线变成弯曲曲线或相反的东西,都不再是透视变换。您可能在寻找其他类的转换,或者类似于分段投影转换。如果不了解更多关于用例的信息,就很难提出一个很好的转换类。
https://stackoverflow.com/questions/70800310
复制相似问题