首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于多点对的复杂形状getPerspectiveTransform矩阵变换

基于多点对的复杂形状getPerspectiveTransform矩阵变换
EN

Stack Overflow用户
提问于 2022-01-21 11:08:23
回答 2查看 413关注 0票数 0

我有两个形状或坐标系统,我希望能够将点从一个系统转换到另一个系统。

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

下面是进行此计算的工作python代码:

代码语言:javascript
复制
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对对应的点?或者更复杂的是,如果存在形状上的曲线呢?

例如:

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-01-21 13:30:41

谢谢您为我指明了正确的方向。

在使用OpenCV ThinPlateSplineShapeTransformer进行转换时,我发现了非常好的结果。

下面是我的示例脚本。请注意,我有7对点。“匹配”只是一个7的列表(从Shape A匹配告诉脚本点#1,从Shape B...etc告诉#1 )。

代码语言:javascript
复制
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])

我不知道为什么你需要重塑数组;“你只是做”,否则它将无法工作。

如果有人想要使用它,我也把它放在一个简单的类中:

代码语言:javascript
复制
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]
票数 1
EN

Stack Overflow用户

发布于 2022-01-21 13:04:58

如果这两种形状是通过透视变换联系起来的,那么任何四个点都会导致相同的变换,至少只要它们不是共线的。从理论上讲,您可以选择任何四个这样的点,而其余的应该只起作用。

在实践中,数字考虑可能会起作用。如果你选择彼此非常接近的点,那么它们的位置上的小错误将导致更大的误差远离这些点。您可能会做一些涉及错误间隔的复杂分析,但根据经验,我会尝试在转换的输入和输出端的任意两个点之间设定很长的距离。

An answer from me on Math Exchange解释了对点的透视图转换的定义中的计算类型。这可能有助于理解数字4的来源。

如果您有4对以上的点,并且使用其中任何四个点定义转换都不能正确地转换其余的点,那么您很可能处于另外两个用例中的一个。

或者您确实在寻找透视图转换,但输入数据却很差。您可能有特征检测的位置,而且可能不精确。有些特性甚至可能间接匹配。因此,在这种情况下,您将寻找最好的转换来描述您的数据与小错误。你的问题听起来不像是你的用例,所以我不会详细说明。

我们的“你”有一个不是透视变换的转变。尤其是,任何将直线变成弯曲曲线或相反的东西,都不再是透视变换。您可能在寻找其他类的转换,或者类似于分段投影转换。如果不了解更多关于用例的信息,就很难提出一个很好的转换类。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70800310

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档