c++ hough变换代码_一文搞懂仿射变换的原理和应用

导读

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

仿射变换

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

假设有一个向量空间k:

9f555a0227775b44326bd7f75adde823.png

向量空间k

和另一个向量空间j:

43f2c7c909f17662af8191a615b71c42.png

向量空间j

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

628b7a61d2066a4d258e59b65951d69c.png

向量空间变换

将上式进行拆分可得

e84e33f4bfa9ca6d972c7d74965d0288.png

向量空间坐标变换

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

1d6ef379b8c3cbc5272eb4c231fd5c92.png

向量空间变换的矩阵表示

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

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

warpAffine函数参数:

  • src:输入的图像数组
  • M:仿射变换矩阵
  • dsize:变换后图像的大小
  • flags:使用的插值算法
  • borderValue:边界的填充值

图像平移

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

80a039a631d909cbe58282acf145e3c1.png

坐标平移

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

6bf3ed94e6ee626c6bb2555ea657e5ee.png

坐标平移的矩阵形式

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

f496932abc233f2cd8c9045a8ff4995e.png

仿射变换实现图像平移

ee9d4ba3c7fa04c3b9fb3f2040cc1d48.png

图像平移

图像翻转

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

fdb1238d80daad02c1588b82b4a5d547.png

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

4b21c816c252d6c9f5407491a6db8390.png

水平翻转

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

29ffb6165270e02901c77be87680084a.png

垂直翻转

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

  • 利用变换矩阵翻转图像

水平翻转的变换矩阵M:

095fa5c29435b4e8a0659cd846228361.png

仿射变换水平翻转矩阵

垂直翻转的变换矩阵M:

0704d9c103181a0ec708caeea3ba2ec8.png

仿射变换垂直翻转矩阵

镜像翻转的变换矩阵M:

a2add0167fdb7a22e04cf3389f5e761a.png

仿射变换镜像翻转矩阵

241d2bcc28c0b57190e9ee69d00017f6.png

仿射变换实现图像的镜像翻转

724868e046d4019640be290d5f25159f.png

镜像翻转

  • OpenCV的flip函数翻转图像

flip函数参数:

  • src:输入的图像数组
  • flipCode:图像翻转参数,1表示水平翻转,0表示垂直翻转,-1表示镜像翻转
ad74ec17d72785bc73d6a139660039be.png

flip函数实现图像翻转

  • numpy的索引翻转图像
a48a16a67e42546201deb3ca76c5734f.png

numpy通过索引数组实现图像翻转

图像缩放

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

25cf6e0b96ef6704b30350ed9326a7e4.png

图像缩放

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

840510f4636cdaf4d19436a7feb1f0f7.png

图像缩放的矩阵形式

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

d4b1afb1b183b7a3827ca57a56c119d2.png

仿射变换实现图像缩放

ec68047b346305ec96eeca845cb27e13.png

仿射变换实现图像缩放

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

图像旋转

  • 围绕原点旋转

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

b0477fc964426394afb952b648711426.png

任意一点围绕原点旋转

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

1255df84ba2fcb2515ce29f992903c95.png

v点坐标展开式

对于v′来说:

15dbce48a5400088bc6ab282a283a6e5.png

v'点坐标展开式

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

a2e286f4543b0fcff738972a559dc367.png

变换后的x和y的坐标

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

8fe93fcab086195a6bda943dd99bbd97.png

旋转后坐标的矩阵表示形式

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

0aee78fdc6e54eb83d46c58d8fd670c0.png

围绕原点旋转的仿射变换矩阵

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

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

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

6710102fef02b8aad9fa4f90981f32ed.png

将图像围绕原点旋转

  • 围绕任意点旋转

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

13aeb06767415921b839b2f52372afd5.png

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

df0cc251b9b7684f4567b46ccf972a15.png

围绕原点旋转

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

d500e5542c010db5a275bafa0b2168e9.png

围绕任意点旋转

将其展开可得

36ca0444483c216f0eb797eae496608f.png

围绕任意点旋转的展开式

将上式用矩阵M表示:

40f23002c1ed98cd65a7f15c4ba30335.png

矩阵形式表示围绕点c进行旋转

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

4186ede23b1b9bb4295930b81d2fade6.png

旋转矩阵

f86a32a8653c01963830cda81e547e75.png

围绕图像中心旋转图像

cd996d2430f302481ed26c158c6d62b4.png

围绕图像中心旋转图像

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

9f4c62e3fa7f443c41f452881190a7c0.png

围绕图像中心旋转后仍保持完整

10552013b6113ca52bfb6aafdcc712df.png
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值