给定 4 个点的仿射变换

问题描述 投票:0回答:1

如何获得一个表示所有变换(缩放、旋转)的 3x3 矩阵,以应用于画布上绘制的图像,给定 4 个点 x1,y1...x4,y4 表示我想要的 ROI(子图像)缩放和旋转?

第一个坐标 x1,y1 应该转换为画布的左上角(0,0),x2,y2 应该转换为画布的右下角(canvas.width, canvas.height)。

非常感谢您的帮助!

math matrix html5-canvas affinetransform
1个回答
0
投票

这个功能其实还是蛮有用的。确实,您需要 3 个值。但是,4 在概念上更好,因为您将一个四边形映射到另一个四边形。

def perspective(p1, p2, p3, p4):
        x1, y1 = p1
        x2, y2 = p2
        x3, y3 = p3
        x4, y4 = p4

        j = x1 - x2 - x3 + x4
        k = -x1 - x2 + x3 + x4
        l = -x1 + x2 - x3 + x4
        m = y1 - y2 - y3 + y4
        n = -y1 - y2 + y3 + y4
        o = -y1 + y2 - y3 + y4
        i = 1.0

        try:
            h = (j * o - m * l) * i / (m * k - j * n)
        except ZeroDivisionError:
            h = 0

        try:
            g = (k * h + l * i) / j
        except ZeroDivisionError:
            g = 0

        f = (y1 * (g + h + i) + y3 * (-g - h + i)) / 2.0
        e = (y1 * (g + h + i) - y2 * (g - h + i)) / 2.0
        d = y1 * (g + h + i) - f - e
        c = (x1 * (g + h + i) + x3 * (-g - h + i)) / 2.0
        b = (x1 * (g + h + i) - x2 * (g - h + i)) / 2.0
        a = x1 * (g + h + i) - c - b
        return Matrix(a, d, b, e, c, f)

这是 [1, 1], [1, -1], [-1, -1], [-1, 1] 到 P1, P2, P3, P4 给出的空间的映射。

要使其真正有用,您需要的是更有用的映射矩阵函数:

def map(p1, p2, p3, p4,  p5, p6, p7, p8):
        m1 = perspective(p1, p2, p3, p4)
        m2 = perspective(p5, p6, p7, p8)
        return ~m1 * m2

这里的

~
表示矩阵求逆,乘法是矩阵串联。这为您提供了将 4 点映射到 4 点的非常有用的功能。并求解实现这一点的矩阵。

现在,有一些注意事项。首先,您实际上可以将其写为整个矩阵。我们在许多变换中看到的 3x3 矩阵实际上通常有一个第三行,即

0,0,1
许多系统现在会给你一个 3x2 矩阵,这里的代码正在处理仿射矩阵,这就是区别。

g, h, i
等于
0, 0, 1
时,矩阵是仿射的。如果我们有 g 和 h 的实际值,这些值有时在列出它们的某些矩阵公式中称为 PERSPECTIVE_X 和 PERSPECTIVE_Y。原因是,只有在矩阵不是仿射的情况下,它们才是实际给定的值,也就是说,应用矩阵之前的平行线在应用矩阵之后仍然是平行线。

您实际上还可以在完整的 3x3 矩阵中使用这组附加值,它可以让您进行视角更改。因此,如果移动一个角,它仍然会解出完整的 3x3 矩阵。

这实际上解决了点从一个空间到另一个空间的投影。如果变换是仿射的,您将得到

g
h
的零。如果没有,您将在那里获得价值。这仍然是一个常规变换矩阵,将您的点乘以矩阵将得到结果点,但该变换中的线可能不会保持平行。但是,如果将第一组点映射到第二组点,使得它们“仅”保持仿射,则这将仅求解变换矩阵。这也非常有用。 另请参阅:

https://math.stackexchange.com/questions/186286/get-transformation-matrix-from-points

如果您实际上

关心仿射矩阵,您实际上可以使用单位平方并简化事情。因此,如果您的角点在仿射空间中为:(0,0)、(1, 0)、(1, 1)、(0, 1),并且您将其映射到您的点,则方程为: a = x4 - x1 b = x2 - x1 c = x1 d = y4 - y1 e = y2 - y1 f = y1

记住 x3,y3 从未被使用过。如果我们说这是一个仿射矩阵,那么该点绝对必须位于给定位置并不重要,因为在仿射空间中线保持平行。请参阅:
数学证明

来证明这些方程。在上面给出的过程中,您可以将 8 个点映射在一起(或者实际上是 6 个点,因为仿射不需要最后一个点)。 如果添加的话,

rw (by ring: x4 - x1 + (x2 - x1) + x1 = x4 - x1 + x2) at h5, rw (by ring: y4 - y1 + (y2 - y1) + y1 = y4 - y1 + y2) at h6, rw eq_comm at h6 h5,

在位之后,它将最终方程重写为:

h5 : x3 = x4 - x1 + x2, h6 : y3 = y4 - y1 + y2

这本质上是对 x3 和 y3 位置的要求,以使目标保持正确。 h5 和 h6 是真实的当且仅当空间该空间是仿射的。

© www.soinside.com 2019 - 2024. All rights reserved.