仿射变换实现组合操作 抠图+缩放+旋转

原创
2018/04/30 17:28
阅读数 6.4K

前言

         之前在工作中需要用仿射变换的方式来实现,用给定的bounding box(标注框)从一张图片

中扣出特定的区域,然后做旋转和缩放等特定操作。然后在网上搜索了一下与仿射变换相关的资料,

看了仿射变换的思想和一些例子,然后结合手头上的代码,做了一些实验,最后终于搞懂了如何实现。

实验代码(提供C++、Scala和Python三种语言的实现):

码云地址

Github地址

正文

         根据给定的标注框从原图中裁剪出物体并且对裁剪出的图片做各种随机旋转和缩放变换,

如果这几个步骤能合成一个仿射变换来做,则代码看起来会更加的简洁和通用。不过之前只了解

如何生成简单的仿射变换矩阵,而且上网上查阅了不少相关的资料,基本都是介绍一些常用的简单变换,

没看到这种有点复杂的组合变换怎么做。后来觉得还是得先了解清楚仿射变换的原理,才知道怎么实现。

 

首先贴上原图:

 

        现在需要实现把图中的熊猫宝宝裁剪出来,标注框信息:[175,30,250,270], 这四个数字

从左到右的意思是, 标注框左上角x坐标, 标注框左上角y坐标,  框的宽, 框的高。

          其实仿射变换的就是把原图上的一个点映射到目标图上的对应点,映射规则由变换矩阵

确定。然后复杂的仿射变换可以通过将简单的仿射变换对应的变换矩阵做矩阵乘法就得到

对应的复杂变换的矩阵。那么把图中的熊猫宝宝裁剪出来的,加上缩放和旋转等的组合变换,

其实可以分解为以下四个变换(这个是我实验的结果,可能还有其他更好的方式):

第一个变换矩阵(crop_mat)

            是根据标注框以及裁剪出的大小生成裁剪与缩放组合矩阵,假设标注框信息是

 [x, y, bboxW, bboxW],裁剪出的框大小 [outW, outH],这个大小表达的意思是相当于根据

标注框裁剪出物体后,再把该物体缩放的大小。首先我们先计算出物体在原图的中心点以及

物体在变换后的中心点,物体在原图的中心点就是 [x + bboxW / 2,  y + bboxH / 2],变换后的

中心点就是 [outW / 2,  outH / 2],则变换矩阵定义如下:

这个变换矩阵代表的意思简单来说就是把物体在原图上的中心点映射为裁剪缩放后图的中心点,

做个简单的验证即可,我们知道原图中心点是 [x + bboxW / 2,  y + bboxH / 2],做个矩阵向量乘法

就到了[outW / 2,  outH / 2]。

第二个变换矩阵(shift_mat1)

         是平移矩阵,是做旋转之前的准备工作,把经过第一个变换后的中心点

(就是[outW / 2,  outH / 2])平移到原点,矩阵定义:

第三个变换矩阵(rotate_map)

        是旋转矩阵,给定旋转的角度 a,变换矩阵定义如下:

需要注意的是,用于计算公式中的cos和sin是弧度,所以要先把角度转为弧度,就是

先除以180再乘以pi。

第四个变换矩阵(shift_mat2)

         是平移矩阵,把经过中心点平移回原来的位置,矩阵定义:

        然后四个矩阵连续做矩阵乘法(注意不是矩阵点乘)就得到组合矩阵,哪个变换先做,

则优先排在右边,所以最后的矩阵是 shift_mat2 * rotate_mat * shift_mat1 * crop_mat:

有兴趣的读者可以自己推导下。

实验结果

标注框信息:[175,30,250,270]。

实验一、裁剪后图片大小设为[250,270],旋转0度

实验二、裁剪后图片大小设为[250,270],旋转20度

实验三、裁剪后图片大小设为[500,540],旋转-20度

实验四、裁剪后图片大小设为[125,135],旋转0度

    

相关资料

[1] 仿射变换

[2] 图像几何变换之仿射变换

[3] 何为仿射变换(Affine Transformation)

 

我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=27qgkalathesc

展开阅读全文
打赏
0
3 收藏
分享
加载中
Ldpe2G博主

引用来自“红薯”的评论

用码云的 git 呗:)

试用了一下,感觉不错:)
2018/05/01 13:51
回复
举报
用码云的 git 呗:)
2018/05/01 12:07
回复
举报
更多评论
打赏
2 评论
3 收藏
0
分享
返回顶部
顶部