仿射扭曲之图像中的图像
实现仿射扭曲中一个简单的例子,将图像或者图像中的一部分放置在另一幅图像指定的位置中
运行代码及结果
具体代码如下:
from PCV.geometry import warp,homography
from PIL import Image
from pylab import *
from scipy import ndimage
im1=array(Image.open('D:/输入图片/aa_12.jpg').convert('L'))
im2=array(Image.open('D:/输入图片/aa_16.jpg').convert('L'))
tp=array([[7,7,402,402],[4,157,157,4],[1,1,1,1]])
im3=warp.image_in_image(im1,im2,tp)
figure()
gray()
imshow(im3)
axis('equal')
axis('off')
show()
imshow(im2)
axis('equal')
axis('off')
show()
输入的两张图片如下:
图一:
图二:
运行结果如下:
此代码中fp是图一四个边角的坐标,这里我获取的是图一整张图片,tp是图二中目标位置四个边角的坐标,在我的代码中y位置在前面,x位置在后面,即[左上角的y坐标,右上角的y坐标,右下角的y坐标,左下角的y坐标],[左上角的x坐标,右上角的x坐标,右下角的x坐标,左下角的x坐标]。目标位置的选定输入一定要正确,否则在目标位置贴上的图片既怪异又丑陋…
函数image_in_image()部分方法的原理
具体代码:
def image_in_image(im1,im2,tp):
""" Put im1 in im2 with an affine transformation
such that corners are as close to tp as possible.
tp are homogeneous and counter-clockwise from top left. """
m,n = im1.shape[:2]
fp = array([[0,0,n,n],[0,m,m,0],[1,1,1,1]])
H = homography.Haffine_from_points(tp,fp)
im1_t = ndimage.affine_transform(im1,H[:2,:2],
(H[0,2],H[1,2]),im2.shape[:2])
alpha = (im1_t > 0)
return (1-alpha)*im2 + alpha*im1_t
homograph.Haffine_from_points(tp,fp)负责算出这四个点对的变换关系。homograph的意思是单应性矩阵,它的适用场景为:当场景中的特征点都落在同一平面上,比如墙、地面等,此时可用单应性估计运动。其描述方程为
H乘以一个不为0的数
H是一个3*3的矩阵。假设已经获得了两幅图像之间的单应矩阵,可得
其中左边为图像1中的点,右边为图像2中的点。
affine_transform的意思是仿射变换,是一种二维坐标到二维坐标之间的线性变换,保持二维图形的“平直性”和“平行性”,其实是指保二维图形间的相对位置关系不变,平行线还是平行线,相交直线的交角不变,但是仿射变换不能保持原来的线段的长度不变,也不能保持原来的夹角角度不变。下图是变换过程的运算:
c,f是平移量,a,b,d,e反映了图像旋转、缩放等变化,将这些参数计算出来,就可以得到两幅图像的坐标变换关系。
这样图一所要截取的区域经过仿射变换映射到图二的目标位置上,且大小和图二的目标区域一样。
alpha通道方法则是设置图二的目标区域部分值为1,其他区域值为0,(0是背景为黑色,1是前景为白色),先映射出一张和图二一样的图像a(相当于先建立一个蒙板),然后在蒙板里把不需要的地方填充成黑色,需要的地方即目标区域留成白色,这个时候实际上是做了一次乘法。用黑色所代表的数值0去乘以图二 ,那么这个地方就变透明了,用白色所代表的数值乘以目标区域,再将两者相加,这样图一就能贴在图二的目标区域上。
调试代码中遇到的问题
No module named ‘matplotlib.delaunay’
如果你们也遇到了这种问题,说明matplotlib库中已经不再支持delaunay模块了,需要去warp.py文件中修改两部分,如下这样就ok啦!