一张图片,我们怎样对其进行平移、旋转、放缩、倾斜、反射变换呢?

普通坐标系

我们知道,一副 RGB 图片可以看做是一个 R^2 -> R^3 的一个映射,即图中坐标 (x,y) 的点颜色为 (Red,Green,Blue)。

对于图像变换,我们可以认为是一个匹配问题,即:新图像中的坐标对应于原图像中的哪个坐标?

显然矩阵是我们进行线性变换的好帮手。我们接下来对上述不同变换分别讨论。

1.放缩(Scalling)

新图像坐标应该分别变为原来的某些倍,显然:

因为涉及到矩阵计算,所以这里为了方便直接使用 numpy 了,后面代码相同。感兴趣的同学可以用 C++ 调用 blas 库自己写一写。话说这种双层 nest for 太丑陋了,有比较好的 map 方法的话求告知。

我们对甜甜私房猫 width、height 分别做 0.5、0.7倍放缩得到图像如下所示,想变瘦的可以用这个矩阵

2.倾斜(Skewing)

这个有点像我们高中学的斜二测画法,倾斜示意图如下所示:

易观察到,倾斜有 x、y 两个方向的倾斜情形,对于两种情形,都只需要保证其中一个坐标不变,另一个沿相应方向平移一定距离即可。

上面是对 width 方向进行倾斜的 skewing 矩阵,对 height 方向倾斜的矩阵类似。代码只要将 scalling 矩阵换成 skewing 矩阵即可,这里不再赘述。一个绕左上角点沿 width 方向倾斜12°的实例如下所示:

3.旋转(Rotating)

旋转的本质是选择对应旋转的基向量,通常情形我们的基向量选择列向量 [1,0] 和 [0,1],平面上任何的点都可以表示成 x、y 份前述向量的线性组合。现在我们选择旋转好的新单位基向量 [cosθ,sinθ] 和 [-sinθ,cosθ],份数不变,则可以在旋转坐标系中相对位置不变,整体来看完成了旋转。

变换矩阵如下所示。注意要以列向量的形式理解变换矩阵。

由于 numpy 对于图像的计数方式是从左上角 (0,0) 开始向右、向下递增,所以直接旋转也是按照左上角旋转。旋转太多,我们的喵不见了。

我们可以通过对所有 x、y 坐标 offset 半个图像的宽、高来将图像中心平移到原点,此时旋转为绕图像中心旋转。操作完我们再移回来(反向 offset)即可。喵喵回来了!

4.反射(Reflecting)

反射是说我们希望将图像沿着某条直线做镜像对称变换。(也叫 Householder 变换)

这个的变换矩阵比较复杂,不过根绝镜像点、原点连线与“平面”法向量平行以及它们的中点在“平面”中细心推导还是可以蛮简单的。假设我们希望沿着 (lx,ly) 向量旋转,那么公式可以推导如下:

沿着 (1,0.8) 镜像翻转的示意图如下所示(有点像旋转,但请注意那只爪印即可区别于旋转):

齐次坐标系

1.平移

普通坐标系对大多数坐标变换都是那么地友好,但是最简单的平移它却不能做!这是因为无论怎样设置 2*2 的变换矩阵都不可能为原坐标加上常量。这时齐次坐标系应运而生,通过给原始的坐标表示加上一个维度,即可在保留普通坐标系变换方式的同时,增加对平移的支持!此时变换由 3*3 矩阵表示。

显然,增加了一维可以用于给坐标添加常量。

此时代码坐标添加一维即可(加一个1)。

平移结果如下所示:

2.综合变换(来自 Feifei Li)

T、R、S 分别为平移、旋转和放缩矩阵,那么一个融合了这三种操作的变换矩阵如下所示:

红框圈出来的部分即为一个 general 形式的变换矩阵。注意矩阵的乘法不具有交换性,所以这些操作交换后意义有所不同,例如先放缩再旋转和先旋转后放缩并不一样!

总结

本文主要介绍了坐标变换,并介绍了一种非常通用的坐标表示形式——齐次坐标系。这里主要讲了其在二维坐标中的应用,不过原理类似很容易推广到三维乃至 n 维。有兴趣的小伙伴可以自行推导!(三维旋转有些复杂,不过还是化为基向量旋转即可。)

本文部分图片来自 Feifei Li,向她表示感谢!

1.《如何确定图片种坐标系、如何给图片建立坐标系》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《如何确定图片种坐标系、如何给图片建立坐标系》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/keji/3302519.html