有人说,我们不应该再造轮子;也有人说,学习怎么造轮子可以带来更深的理解。我说,用轮子有用轮子的乐趣,造轮子有造轮子的乐趣。总之,开心就好。
仿射变换,可能是图像处理中最为基本的变换之一了吧。OpenCV中就有现成的函数,大可以一调了之。然而,如果不能使用OpenCV呢?比如,在DSP上实现。有人会说,TI的DSP直接有一个医学图像库可以调用仿射变换啊。好吧,我被打败了,但TI的医学图像库的仿射变换有一篇文档。那篇文档写得实在是太感人肺腑了,难道我们不该顺便学习一下吗?所以有了这篇文章(其实大多数就是翻译一下啦,不用那么认真。直接看
原文吧:))
简介
图像中要使用仿射变换的目的其实就是为了把一个本来已经偏了的东西放正。比如,我之前做的身份证扫描的项目。身份证通过CIS的扫描,变成了一个背景是黑 {MOD},前景当然就是身份证的东西了。(透露这么多已经很危险了,就不放图了)可以想象一下,身份证不一定就很正吧,会有些许的倾斜。那问题来了,客户想要的是标标准准的正置着的裁好边的身份证图像。我该怎么做呢?很简单,就是分成两个步骤:
- 找到身份证的四个顶点的坐标。
- 利用仿射变换对这四个顶点坐标进行仿射变换。(其实只要三个顶点坐标就OK了。)
举这么个例子,想象力比较丰富的可能就知道仿射变换是要干什么了。仿射变换其实就是图像变换的一列组合,包括:旋转(rotating)、移位(shifting)、缩放(scaling)、切变(shearing)。
图像的变换究竟是怎么变换的呢?事实上,图像的变换其实就是坐标点位置的变换。正变换是这样:知道了原图,知道了变换方式,我们就可以推测出目标图像是哪样。但其实我们使用的往往是逆变换。也就是:我们首先对目标图像有一个大小的期望(分辨率为$W imes H$),那么每一个像素该填什么值呢?就可以通过逆变换,找到其在原图像上的对应位置。此时,看看原图上的周围像素点是多少,就可以用双线性插值等算法计算出目标图像上该点的像素值了。
基本操作
我们可以写出下面的式子来表示仿射坐标变换的通式:
![][matrix]
[matrix]:
http://latex.codecogs.com/svg.latex?p_T=Acdot{p_S}
其中,
![][00]
[00]:
http://latex.codecogs.com/svg.latex?p_S=left[egin{array}{c}x_Sy_S1\end{array}
ight]
![][01]
[01]:
http://latex.codecogs.com/svg.latex?p_T=left[egin{array}{c}x_Ty_T1\end{array}
ight]
分别是原点位置和目标点位置。
![][02]
[02]:
http://latex.codecogs.com/svg.latex?A=left[egin{array}{ccc}a_{11}&a_{12}&a_{13}a_{21}&a_{22}&a_{23}