4

我有一个关于投影变换矩阵中元素的含义的问题,例如在OpenCv warpPerspective.

我知道仿射变换的基本知识,但在这里我对射影变换更感兴趣,这意味着在下面显示的矩阵中,元素A31A32

A11 A12 A13
A21 A22 A23
A31 A32  1

我稍微玩了一下这些值,这意味着所有其他元素都有一个固定的数字。意义:

 1   0   0 
 0   1   0
A31 A32  1

只有投影元素。

但是究竟是什么导致了元素 A31 和 A32 ?像 A13 和 A23 负责水平和垂直平移。

这两个元素有简单的解释吗?就像具有正值意味着 ....,具有负值意味着 .... 某某 像那样。

希望任何人都可以帮助我。

4

2 回答 2

8

牛顿的描述是正确的,但实际查看转换以了解正在发生的事情以及它们如何与转换矩阵中的其他值一起工作以更有意义可能会有所帮助。我将给出一些带有动画的 python/OpenCV 示例来展示这些值的作用

import numpy as np
import cv2
img = cv2.imread('img1.png')
h, w = img.shape[:2]

# initializations
max_m20 = 2e-3
nsteps = 50
M = np.eye(3)

所以在这里我将转换矩阵设置为恒等式(无转换)。我们希望看到在变换矩阵 (2, 0) 处更改元素的效果M,因此我们将通过在 to 之间线性间隔循环来制作nsteps动画。0max_m20

for m20 in np.linspace(0, max_m20, nsteps):
    M[2, 0] = m20
    warped = cv2.warpPerspective(img, M, (w, h))
    cv2.imshow('warped', warped)
    k = cv2.waitKey(1)
    if k == ord('q') & 0xFF:
        break

我将其应用于从牛津视觉几何组拍摄的图像上。

m20

所以实际上,我们可以看到这类似于围绕与图像左边缘对齐的点旋转相机,或者围绕轴旋转图像本身。但是,它此略有不同。请注意,顶部边缘始终保持在顶部,这有点奇怪。我们不会像上面那样绕轴旋转,而是想象顶部边缘也会开始下降到右侧边缘。像这样:

m20m10

好吧,如果您正在考虑转换,获得此转换的一种简单方法是采用上面的转换,并添加一些倾斜失真,以便在右下角被向上推时,右上侧被向下推。实际上,这正是创建此视图的方式:

M = np.eye(3)
max_m20 = 2e-3
max_m10 = 0.6
for m20, m10 in zip(np.linspace(0, max_m20, nsteps), np.linspace(0, max_m10, nsteps)):
    M[2, 0] = m20
    M[1, 0] = m10
    warped = cv2.warpPerspective(img, M, (w, h))
    cv2.imshow('warped', warped)
    k = cv2.waitKey(1)
    if k == ord('q') & 0xFF:
        break

因此,在这些矩阵中考虑视角的正确方法是,IMO,将倾斜条目和最后一行放在一起。这些是单应矩阵中实际修改角度的两个位置*;否则,它只是旋转、缩放和平移——所有这些都是角度保持的。

*注意:实际上,可以通过我没有提到的另一种方式更改角度。仿射变换允许非均匀缩放,这意味着您可以拉伸形状的宽度而不是高度,反之亦然,这也会改变角度。想象一下,如果你有一个三角形并且只拉伸它的宽度;角度会改变。所以事实证明,非均匀缩放(即当变换矩阵的第一个和中间元素是不同的值时)除了透视变化和剪切失真之外,还可以修改角度。

请注意,在这些示例中,这同样适用于最后一行中具有另一个偏移位置的第二个条目;唯一的区别是它发生在顶部而不是左侧。这两种情况下的负值类似于沿该轴将平面旋转到而不是远离相机。

于 2017-08-21T03:07:24.273 回答
4

单应矩阵的 3x1 ,3x2 元素改变了图像的平面。这就是仿射矩阵和单应矩阵之间的区别。例如考虑一下 - A31 沿左边缘改变图像的平面。就像将您的图像粘贴到像旗帜一样的棍子上并旋转。正极是顺时针,负极是反向。另一个元素从顶部边缘执行相同的操作。但他们一起为你的形象设定了一个平面。这是我能说的最简单的方式。

于 2017-08-18T18:18:33.300 回答