OpenCV的战争

Hie*_*ien 16 c++ opencv image image-processing

出于某种原因,每当我使用OpenCV的warpPerspective()函数时,最终的扭曲图像都不包含原始图像中的所有内容.图像的左侧部分似乎被切断了.我认为发生这种情况的原因是因为warpPerspective()在画布最左边的位置创建了扭曲图像.有办法解决这个问题吗?谢谢

小智 32

之所以出现此问题是因为单应性将图像的一部分映射到图像区域外的负x,y值,因此无法绘制.我们希望做的是将扭曲的输出偏移一定数量的像素,以将整个变形图像"分流"成正坐标(因此在图像区域内).

可以使用矩阵乘法来组合Homographies(这就是为什么它们如此强大).如果A和B是单应性,那么AB代表首先应用B的单应性,然后是A.

因此,我们需要做的就是偏移输出是通过一些偏移为平移创建单应矩阵,然后通过我们原始的单应矩阵预乘

2D单应矩阵看起来像这样:

[R11,R12,T1]
[R21,R22,T2]
[ P , P , 1]
Run Code Online (Sandbox Code Playgroud)

其中R表示旋转矩阵,T表示平移,P表示透视扭曲.所以纯粹的翻译单应法看起来像这样:

[ 1 , 0 , x_offset]
[ 0 , 1 , y_offset]
[ 0 , 0 ,    1    ]
Run Code Online (Sandbox Code Playgroud)

因此,只需通过类似于上面的矩阵预乘你的单应性,输出图像就会偏移.

(确保使用矩阵乘法,而不是元素乘法!)

  • 看来x_offset和y_offset应该乘以-1。我不知道为什么。我尝试了正片,它使图像向相反方向移动。 (2认同)

joh*_*jik 6

马特的回答是一个好的开始,他说你需要将单应性乘以

[ 1 , 0 , x_offset]
[ 0 , 1 , y_offset]
[ 0 , 0 ,    1    ]
Run Code Online (Sandbox Code Playgroud)

但他没有具体说明 x_offset 和 y_offset 是什么。其他答案说只需进行透视变换,但这是不正确的。您想要进行逆透视变换。

仅仅因为点 0,0 变换为 -10,-10,并不意味着将图像移动 10,10 将产生未裁剪的图像。这是因为点 10,10 不一定映射到 0,0。
您想要做的是找出哪个点将映射到 0,0,并将图像移动相应的量。为此,您需要单应性的逆(cv2.invert)并应用透视变换。

在此输入图像描述 并不意味着: 在此输入图像描述

您需要应用逆变换来找到正确的点。

在此输入图像描述

这将获得正确的 x_offset 和 y_offset 来对齐左上角点。从那里找到正确的边界框并完美地适应整个图像,您需要计算出倾斜(在正常、非逆、变换后图像向左或向上倾斜多少)并将该量添加到您的 x_offset 和 y_offset以及。

编辑:这都是理论。在我的测试中图像有几个像素的偏差,我不知道为什么。

  • 我想,用一段代码,你想表达的意思会变得更加清楚 (4认同)

Dan*_*HsH 1

warpPerspective() 工作正常。无需重写。您可能错误地使用了它。

请记住以下提示:

  1. (0,0) 像素不在中心,而是在左上角。因此,如果将图像放大 2 倍,您将丢失下半部分和右半部分,而不是边框​​(就像在 matlab 中一样)。
  2. 如果将图像扭曲两次,最好乘以变换并激活该函数一次。
  3. 我认为它仅适用于 char/int 矩阵,不适用于 float/double。
  4. 当您进行变换时,首先应用缩放/倾斜/旋转/透视,最后应用平移。因此,如果图像的一部分丢失,只需更改矩阵中的转换(最后一列的上面两行)即可。