计算机视觉--图像拼接

一、基本原理

  要实现两张图片的简单拼接,其实只需找出两张图片中相似的点 (至少四个,因为 homography 矩阵的计算需要至少四个点), 计算一张图片可以变换到另一张图片的变换矩阵 (homography 单应性矩阵),用这个矩阵把那张图片变换后放到另一张图片相应的位置 ,就是相当于把两张图片中定好的四个相似的点重合在一起。如此,就可以实现简单的全景拼接。

二、注意事项

  1.在同一位置拍摄两张以上图片,这些图片是单应性相关的,即图片之间有相同的拍摄区域。

  2.手机拍的图片太大会报错的话可以用ps修改图片分辨率,将图片压缩。

三、实验步骤

  1.读入连续图片并使用SIFT特征查找匹配对应点对

    sift算子存在错误的匹配点,因此需要用Ransac算法剔除错误匹配点。

  2.利用RANSAC算法计算变换矩阵,实现代码:

class RansacModel(object):
    """ Class for testing homography fit with ransac.py from
        http://www.scipy.org/Cookbook/RANSAC"""    
    def __init__(self,debug=False):
        self.debug = debugdef fit(self, data):
        """ 计算选取四个对应的单应性矩阵 """
        
        # 将其转置,来调用H_from_points()计算单应性矩阵
        data = data.T
        #映射的起始点
        fp = data[:3,:4]
        # 映射的目标点
        tp = data[3:,:4]
        #计算单应性矩阵然后返回
        return H_from_points(fp,tp)
    
    def get_error( self, data, H):
        """ 对所有的对应计算单应性矩阵,然后对每个变换后的点,返回相应的误差 """
        data = data.T
        #映射的起始点
        fp = data[:3]
        # 映射的目标点
        tp = data[3:]
        #变换fp
        fp_transformed = dot(H,fp)
        #归一化齐次坐标
        for i in range(3):
          fp_transformed[i] /= fp_transformed[2]
        return sqrt( sum((tp-fp_transformed)**2,axis=0) )

  3.进行图像拼接,实现代码:

from pylab import *
from numpy import *
from PIL import Image
from PCV.geometry import homography, warp
from PCV.localdescriptors import sift

featname = ['jmu'+str(i+1)+'.sift' for i in range(5)] 
imname = ['jmu'+str(i+1)+'.jpg' for i in range(5)]

l = {}
d = {}
for i in range(5): 
    print(i)
    sift.process_image(imname[i],featname[i])
    l[i],d[i] = sift.read_features_from_file(featname[i])

matches = {}
for i in range(4):
    matches[i] = sift.match(d[i+1],d[i])
    
# visualize the matches (Figure 3-11 in the book)
for i in range(4):
    im1 = array(Image.open(imname[i]))
    im2 = array(Image.open(imname[i+1]))
    figure()
    sift.plot_matches(im2,im1,l[i+1],l[i],matches[i],show_below=True)


# function to convert the matches to hom. points
def convert_points(j):
    ndx = matches[j].nonzero()[0]
    fp = homography.make_homog(l[j+1][ndx,:2].T) 
    ndx2 = [int(matches[j][i]) for i in ndx]
    tp = homography.make_homog(l[j][ndx2,:2].T) 
    
    # switch x and y - TODO this should move elsewhere
    fp = vstack([fp[1],fp[0],fp[2]])
    tp = vstack([fp[1],fp[0],fp[2]])
    
    return fp,tp


# estimate the homographies
model = homography.RansacModel() 

fp,tp = convert_points(1)
H_12 = homography.H_from_ransac(fp,tp,model)[0] #im 1 to 2 

fp,tp = convert_points(0)
H_01 = homography.H_from_ransac(fp,tp,model)[0] #im 0 to 1 

tp,fp = convert_points(2) #NB: reverse order
H_32 = homography.H_from_ransac(fp,tp,model)[0] #im 3 to 2 

tp,fp = convert_points(3) #NB: reverse order
H_43 = homography.H_from_ransac(fp,tp,model)[0] #im 4 to 3    


# warp the images
delta = 420 # for padding and translation

im1 = array(Image.open(imname[1]), "uint8")
im2 = array(Image.open(imname[2]), "uint8")
im_12 = warp.panorama(H_12,im1,im2,delta,delta)
  
im1 = array(Image.open(imname[0]), "f")
im_02 = warp.panorama(dot(H_12,H_01),im1,im_12,delta,delta)
  
im1 = array(Image.open(imname[3]), "f")
im_32 = warp.panorama(H_32,im1,im_02,delta,delta)
  
im1 = array(Image.open(imname[4]), "f")
im_42 = warp.panorama(dot(H_32,H_43),im1,im_32,delta,2*delta)



figure()
imshow(array(im_42, "uint8"))
axis('off')
savefig("example.png",dpi=300)
show()

    (注:关于使用PCV包报错 'No module named 'matplotlib.delaunay' 的解决方法可以参考博客:

        https://blog.csdn.net/weixin_42648848/article/details/88667243)

四、运行结果

  第一组原图:

              计算机视觉--图像拼接                计算机视觉--图像拼接               计算机视觉--图像拼接

                                         计算机视觉--图像拼接                 计算机视觉--图像拼接

 

 

 

  运行结果:

                            计算机视觉--图像拼接   

 

                          计算机视觉--图像拼接

 

  结果分析:

    缺陷:

      1.首先,从拼接结果看,感觉像是单纯的图片平移叠加,并没有实现很好的变换拼接效果

      2.右侧还有一块黑色区域的空缺

    分析:

      1.图片是边走边拍的,从原图中也可以看出角度在拍摄中发生了倾斜,估计是当时手抖导致的

      2.走的时候距离建筑的远近也会发生变化

      3.走动会导致图片移动距离不固定

      4.查找到一个参数delta,这个参数是针对你拍摄图像时,你相对平移的距离的变量,当你拍摄近景时候,这个参数尽量该小,远景相反。

  所以,多次修改了delta参数,确实是会发生一些变化,运行结果:

                                                         计算机视觉--图像拼接

 

    这结果跟我美好的想象一点都不一样,我很难过,于是,我决定重新拍组图片,站在一个位置不动,持手机转动上半身,拍5张图片。

  第二组原图:

 计算机视觉--图像拼接     计算机视觉--图像拼接     计算机视觉--图像拼接

 

                                  计算机视觉--图像拼接          计算机视觉--图像拼接

   运行结果:

                        计算机视觉--图像拼接

 

      (深深的无力感。。。。。。)

五、实验小结

  1.拍摄照片的好坏会影响拼接结果

  2.图片的大小会影响程序运行的时间,所以为了速度和CPU着想,图片不要搞太大

  3.修改delta参数会影响结果

  4.我觉得周围环境如果都太相似可能也会造成误差

  5.我觉得我这个代码的运行结果像是单纯的平移叠加,很是奇怪,还有待继续研究修改

(后续再继续修改更新。。。。。。。。)

 

    

 

上一篇:[入门到入土] 简单一元导数


下一篇:SiamMOT解读