计算机视觉学习(三):仿射变换将一幅图像放置到另一幅图像中

本例子为通过仿射扭曲变换将图像放置到另一幅图像中,使得它们能够和指定的区域或者标记物对齐。

  运行的代码如下:

 # test.py
from PCV.geometry import warp, homography
from PIL import  Image
from pylab import *
from scipy import ndimage

#放射扭曲im1到im2
#打开两张图片
im1 = array(Image.open('D:\pythonxy\image/wen.jpg').convert('L'))
im2 = array(Image.open('D:\pythonxy\image/yu.jpg').convert('L'))

#设置映射的目标点  
tp = array([[240,375,375,240],[143,145,275,275],[1,1,1,1]])

#使用仿射变换将im1放置在im2上,使im1图像的角和tp尽可能的靠近
im3 = warp.image_in_image(im1,im2,tp)

#将图像灰度显示
figure()
gray()
subplot(131)
axis('off')
imshow(im1)
subplot(132)
axis('off')
imshow(im2)
subplot(133)
axis('off')
imshow(im3)

#选定im1角上的一些点
m,n = im1.shape[:2]
fp = array([[0,m,m,0],[0,0,n,n],[1,1,1,1]])

# 第一个三角形
tp2 = tp[:,:3]
fp2 = fp[:,:3]

# 计算仿射变换H,并且将其应用于图像im1
H = homography.Haffine_from_points(tp2,fp2)

#affine仿射变换的方式把第一幅图像变到第二幅图像里面
im1_t = ndimage.affine_transform(im1,H[:2,:2],
(H[0,2],H[1,2]),im2.shape[:2])
# 对图像进行alpha通道处理,三角形的alphy
alpha = warp.alpha_for_triangle(tp2,im2.shape[0],im2.shape[1])
#创建alpha图像
im3 = (1-alpha)*im2 + alpha*im1_t
axis('off')
show()

  运行的结果图如下:

图二建筑物来源于集美大学

其中主要用到了两个函数:warp 和 homography(单应)

  warp函数中又用到了两个方法:image_in_image() 和 alpha_for_triangle()

    image_in_image() 方法的代码如下:

#tp是齐次表示的,并且是按照从左上角逆时针计算的
#使用仿射变换将im1放置在im2上,使im1图像的角和tp尽可能的靠近
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]])
    
    #算出两个图像间的变换关系,返回给定对应点的最优仿射变换,并用H表示
    H = homography.Haffine_from_points(tp,fp)

    #affine通过仿射变换的方式把第一幅图像变到第二幅图像里面
    im1_t = ndimage.affine_transform(im1,H[:2,:2],
                    (H[0,2],H[1,2]),im2.shape[:2])

    #alpha通道对图像进行处理
    alpha = (im1_t > 0)
    
    return (1-alpha)*im2 + alpha*im1_t

    该方法的输入参数为两幅图像和一个tp坐标,该坐标为将第一幅图像放置到第二幅图像中的角点坐标,是齐次表示的。然后将扭曲的im1图像和im2图像融合,创建alpha图像。该alpha图像定义了每个像素从各个图像中获取的像素值成分的多少。扭曲的 图像是在扭曲区域边界以外用0来填充的图像,以此来创建一个二值的alpha图像。所以从严格意义上来说,我们需要在第一幅图像中的潜在0像素上加上一个小的数值。

    alpha_for_triangle() 方法的代码如下:

def alpha_for_triangle(points,m,n):

 #对于由角点定义的三角形创建大小为(m,n)的alpha映射(在归一化齐次坐标中给出)   
    alpha = zeros((m,n))
    for i in range(min(points[0]),max(points[0])):
        for j in range(min(points[1]),max(points[1])):
            x = linalg.solve(points,[i,j,1])

            #如果所有系数为正
            if min(x) > 0:
                alpha[i,j] = 1

    #返回alpha的值
    return alpha

    alpha通道是一个8位的灰度通道,该通道用256级灰度来记录图像中的透明度信息,定义透明、不透明和半透明区域,其中白表示不透明,黑表示透明,灰表示半透明。使用alpha通道来给图像增加透明度。这里我们简单地为每个三角形创建了alpha图像,然后将所有的图像合并起来。该三角形的alpha图像可以简单地通过检查像素的坐标能否写成三角形顶点坐标的凸组合来计算得出。如果坐标可以表示成这种形式,那么该像素就位于三角形的内部。

  homography函数中用到了Haffine_from_points()方法

    Haffine_from_points()方法的代码如下:

def Haffine_from_points(fp,tp):
#对H进行仿射变换,tp是fp的仿射输注
    
    if fp.shape != tp.shape:
        raise RuntimeError('number of points do not match')
        
    #条件点
    m = mean(fp[:2], axis=1)
    maxstd = max(std(fp[:2], axis=1)) + 1e-9
    C1 = diag([1/maxstd, 1/maxstd, 1]) 
    C1[0][2] = -m[0]/maxstd
    C1[1][2] = -m[1]/maxstd
    fp_cond = dot(C1,fp)
    
    # 条件点指向
    m = mean(tp[:2], axis=1)
    C2 = C1.copy() #must use same scaling for both point sets
    C2[0][2] = -m[0]/maxstd
    C2[1][2] = -m[1]/maxstd
    tp_cond = dot(C2,tp)
    
    # 条件点的平均值为零,所以平移为零
    A = concatenate((fp_cond[:2],tp_cond[:2]), axis=0)
    U,S,V = linalg.svd(A.T)
    
    # 创建B、C矩阵
    tmp = V[:2].T
    B = tmp[:2]
    C = tmp[2:4]
    
    tmp2 = concatenate((dot(C,linalg.pinv(B)),zeros((2,1))), axis=1) 
    H = vstack((tmp2,[0,0,1]))
    
    # 仿射
    H = dot(linalg.inv(C2),dot(H,C1))
    
    return H / H[2,2]

    该方法会返回给定对应点的最优仿射变换。以本例子来说,对应点为图像和黑方块的角点,如果透视效应比较弱,那么这种方法会返回很好的结果。

    透视变换的本质是将图像投影到一个新的视平面。仿射变换可以理解为透视变换的特殊形式。

    一幅图像就是一个像素坐标系下的各个带有像素值的坐标点,而透视变换可以理解为就是将一幅图像中的这些坐标点完成了一个坐标转换,将它们的坐标变换到了其他位置,从而实现了变换了图像视角的效果。因此,透视变换和相机标定等概念其实并没有什么内在关系。在车道线检测中的“相机标定”过程,其实就是做了一个透视变换,即相机画面图像和一幅假想的地面图像这两幅图像之间的变换关系,所谓假想的地面图像,即将实际地面上各点距离(离车辆后轴中心点)按一个设定的尺度放到一张图像上(鸟瞰图),此时只要是在这个地平面上的点,通过透视变换都可以得到其在相机图像上的点的坐标。因为假想的是在地平面上的点做的透视变换,所以此时只有位于地平面上的物体,才具有真正的鸟瞰图像素值,投影到图像上才是正常的。

发布了28 篇原创文章 · 获赞 21 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_43955429/article/details/88665823