opencv 仿射变换_一文搞懂仿射变换

本文详细介绍了OpenCV中的仿射变换,包括图像平移、翻转、缩放和旋转的原理与实现。通过仿射变换矩阵,可以轻松完成这些图像操作,文中还提供了使用OpenCV warpAffine 函数和flip函数的实例。
摘要由CSDN通过智能技术生成
导读

在图像处理中,我们经常需要对图像进行各种操作如平移缩放旋转翻转等,这些操作都属于图像的仿射变换,我们通过一个变换矩阵就能很容易的实现。本篇文章详细的介绍了各种操作的实现原理,以及代码的实现和使用

仿射变换

仿射变换也称仿射投影,是指几何中,对一个向量空间进行线性变换并接上一个平移,变换为另一个向量空间。所以,仿射变换其实也就是在讲如何来进行两个向量空间的变换

假设有一个向量空间k:

18a753b947ff793fbb157505774b644e.png

和另一个向量空间j:

996fe2d93726c583d36279104fd6d4a0.png

如果我们想要将向量空间由k变为j,可以通过下面的公式来实现:

4d57e88611cf419f0b5f80427f77e63a.png

将上式进行拆分可得

ceedd29ac408461df06ff6fb55349c6c.png

我们再将上式转换为矩阵的乘法

313ff5367a20446518afaeffa90f55c5.png

上式表明通过一个两行三列的矩阵M就可以实现两个向量空间之间的转换,在进行仿射变换的时候我们也只需要一个矩阵M就可以实现图像的平移缩放旋转翻转变换。

接下来,会先介绍原理然后利用OpenCV来实现相应的例子,这里主要利用OpenCV的warpAffine函数来实现仿射变换

warpAffine函数参数:

  • src:输入的图像数组

  • M:仿射变换矩阵

  • dsize:变换后图像的大小

  • flags:使用的插值算法

  • borderValue:边界的填充值

图像平移

在平面坐标系有点P(x,y)和点P′(x′,y′),如果我们想要将P点移动到P′通过下面的变换就可以实现

aa1c84a57de081a3495f9046b552a7fc.png

其中ΔxΔy就是x方向上和y方向上的偏移量,我们将其转换为矩阵的形式上面的矩阵MM就是仿射变换的平移参数,接下来我们利用OpenCV中的warpAffine函数来实现

8673ec1ec8828ae44e8fb7e7179e5ee2.png

上面的矩阵M就是仿射变换的平移参数,接下来我们利用OpenCV中的warpAffine函数来实现图像的平移

d63f9171d5d59a55dfffe9642c572c86.png

49225b43352bb66b123fc41a8b5ffa6a.png

图像翻转

有时候我们我们需要对图像进行水平翻转垂直翻转镜像翻转(同时进行水平和垂直翻转),想要实现这个功能并不难,我们可以通过opencv内置的flip方法很容易实现,还可以通过numpy的索引来实现,当然也可以通过仿射变换矩阵来实现这个功能

2f65e4964d04cbbb5a8c60765bb2693a.png

上图中的ABCD表示图像的四个顶点,如果我们需要对图像进行水平翻转,那么我们就需要将A点和B点进行交换,C点和D点进行交换,沿着x轴的中线进行对称交换位置,通过下面的式子可以实现水平翻转

8fb2331a3da16472987ddb70bba41e7d.png

上式中的w表示图像的宽,同理可得垂直翻转的实现公式

03d33fefb5619a3ef433ec0194230426.png

上式中的h表示的是图像的高

  • 利用变换矩阵翻转图像

水平翻转的变换矩阵M:

7bc5237e27ab6698a70101d53f4c8537.png

垂直翻转的变换矩阵M:

7998ac570a6b6a4ae3548b26cac52bbd.png

镜像翻转的变换矩阵M:

2a8221471a9d21b08a11fb4983ab424d.png

cdb303abb54d6a1923e29e953469bdba.png

b55f5a1d8e876517452fe653a005209b.png

  • OpenCV的flip函数翻转图像

flip函数参数:

  • src:输入的图像数组

  • flipCode:图像翻转参数,1表示水平翻转,0表示垂直翻转,-1表示镜像翻转

f50a141c7427cee21c3bdd86456d8ae4.pngflip函数实现图像翻转

  • numpy的索引翻转图像

8a1a5623e33f1e66b38c5e4fb08c0951.png

图像缩放

如果我们想要对坐标系的P点进行缩放操作,通过下面的公式就可以实现

f0af74a47f73fb24d53f73c4cd6d4e4f.png

通过在x和y前面添加一个缩放系数即可,同样我们将其转换为矩阵形式

356ff94cd36dfb67d28b141678648cab.png

通过上面的矩阵M我们就可以实现对图片的缩放

e3ae84ea958c3a27991b5eb209b38dc9.png

705448d0e8c8703cda49def85b49c65e.png

这里使用仿射变换实现的图片缩放其实和resize函数的效果是一样的,缩放时选择的插值函数不同最终效果会有所偏差

图像旋转

  • 围绕原点旋转

我们先来看看一个二维平面上的点在围绕原点是如何旋转的

d68b7fc3dbf62909a2de9dfce736a2ae.png

上图中点v围绕原点旋转θ度之后得到了点v′,我们将坐标点用极坐标的形式来表示可以得到v(rcosϕ,rsinϕ),所以v′(rcos(θ+ϕ),rsin(θ+ϕ))利用正弦和余弦展开式将其展开可得,对于v点来说:

8fd0400657c4692a106570741c42169c.png

对于v′来说:

1b74a6257e75b8b487cc2d6fac830d50.png

然后我们再将x和y代入上式可得

2fd6ea70a4fb1bf6954b346f414382a8.png

然后再将上式用矩阵M表示,可得

284ec2dce7219da9815c4dc7f0642ab1.png

特别注意:我们在建立直角坐标系的时候是以左下角为原点建立的,然而对于图像而言是以左上角为原点建立的,所以我们需要对角度θ进行取反,结合三角函数的特性,M矩阵的表达式如下

e611eea178f512a9111d784a450c7dd4.png

还需要注意的是这里的角度都是弧度制,所以我们在使用的时候还需要对其进行转换,转换代码如下

#将角度转换为弧度制radian_theta = theta/180 * np.pi#np.pi指的是π

将图片围绕原点进行逆时针旋转θ度的代码如下

a6ce95113c0361d9ee0d06bddf2c599c.png

  • 围绕任意点旋转

如果我们想围绕任意坐标点旋转呢?其实也并不难,下图的v点在围绕c点(a,b)旋转90度得到v′。其实我们可以将其等价于,先将V点平移到V1点,然后再将V1点围绕原点旋转90度得到V2点,最后再将V2点沿着V点平移的反方向平移相同长度,最终得到V'。这样我们就将围绕任意坐标点旋转的问题转换成了围绕原点旋转的问题

7772475681b11eba2c5298c925d6ce07.png

我们来回顾一下,围绕原点旋转坐标的变换公式

29399c9558ad3d6669f08620c73308fe.png

在围绕原点旋转变换公式的基础上,我们将其改进为围绕任意点c(a,b)旋转,我们现在原来的坐标进行平移,得到变换后的坐标,最后再沿着之前平移的反方向进行平移,就得到围绕任意点旋转的变换公式

eb397d9781064b99eb0beabea97ab233.png

将其展开可得

d67ea94169fd4e94dde568d43d8705fb.png

将上式用矩阵M表示:

b8cc7fc2a5db27c2b90dc50b870065d3.png

上式中的c(a,b)表示旋转中心,因为坐标系问题需要对θ进行取反,最终M矩阵的表达式如下

47617f730f342ceecef3b3cbb42b54c4.png

98eecd673e3ed439d3c490a66dc719be.png

d4d15d168b9ae3317777343f046ef7ab.png

细心的同学也许已经发现了,上图中围绕图像中心旋转后的图片部分被裁剪掉了,如果我们想让旋转之后的图片仍然是完整,应该如何修改呢?

8671a25ee57177884b5dd822745b5c69.png

6a44306c6c95703ee4c808b319975148.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值