对图像块应用仿射变换,我们将其称为图像扭曲(或者仿射扭曲)。指的是在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间。下面会简单介绍仿射变换的原理及应用。
仿射变换(Affine Transformation 或Affine Map)是一种二维坐标(x, y)到二维坐标(x’, y’)的线性变换,其数学表达式形式如下:
由上式可知该方程需要求解的自由度数(即未知参数)为6个。为了能求解所有的参数,理论上至少需要6个方程联立求解,即需要3组点集对(且这3组点不共线),n>=3,当n>3时用最小二乘法求解未知参数。上式方程经过一系列的数学变换得到一个矩阵表达式:
仿射变换保持了二维图形的“平直性”(直线经仿射变换后依然为直线)和“平行性”(直线之间的相对位置关系保持不变,平行线经仿射变换后依然为平行线,且直线上点的位置顺序不会发生变化)。非共线的三对对应点确定一个唯一的仿射变换。
仿射扭曲的一个简单例子是,将图像或者图像的一部分放置在另一幅图像中,使得它们能够和指定的区域或者标记物对齐。
实现该变换需要Scipy工具包中的ndimage包、PCV工具包下geometry中的warp和homography。
示例用下面两张图展示仿射变换,即将尚大楼(左边)放置到右边图像中的校训牌上(集大的)。
代码如下:
from PCV.geometry import warp,homography
from PIL import Image
from pylab import *
from scipy import ndimage
im1=array(Image.open('../images/9.jpg').convert('L'))
im2=array(Image.open('../images/01.jpg').convert('L'))
#选定目标点
tp=array([[543,547,695,695],[305,385,396,313],[1,1,1,1]]) #目标区域的是个角点坐标,前两个[][]分别为x坐标和y坐标(分开的)
im3=warp.image_in_image(im1,im2,tp) #im1替换im2的像素值
figure()
gray()
subplot(131)
imshow(im1)
axis('equal')
axis('off')
subplot(132)
imshow(im2)
axis('equal')
axis('off')
subplot(133)
imshow(im3)
axis('equal')
axis('off')
show()
该函数的输入参数为两幅图像和一个坐标。该坐标为将第一幅图像放置到第二幅图像中的角点坐标。
具体代码为:
def image_in_image(im1,im2,tp):
# 扭曲的点
m, n = im1.shape[:2]
fp = array([[0,m,m,0],[0,0,n,n],[1,1,1,1]]) # im1的角点坐标
# 计算仿射变换,并且将其应用于图像im1
H = homography.Haffine_from_points(tp,fp) # 单应性矩阵(3*3)
im1_t = ndimage.affine_transform(im1,H[:2,:2],(H[0,2],H[1,2]),im2.shape[:2])
# 提取由前面获取的矩阵H的前2行,将im1仿射成im2所需要的图像大小
alpha = (im1_t > 0) # 二值的alpha图像(下面具体说明)
return (1-alpha)*im2 + alpha*im1_t
在图形图像学中,透明通道也称Alpha通道,是一个8位的灰度通道,代表数字图像中像素点的透明信息。由于上面提到的alpha图像是二值的,所以只考虑黑白两个颜色表示的含义:白色的Alpha像素用以定义不透明的彩色像素(1)作为前景,而黑色的Alpha定以透明像素(0)作为背景。
alpha图像中只有im1_t非0的区域有图像显示(为0的像素全透明),即只显示了im2所需要的图像。最后返回了im2与im1_t叠加的图像,im1_t替换了im2原来位置上的像素值,使之能够放置在im2上。
To be continued…