计算机视觉python--全景图像拼接

1 全景图像拼接

1.1 基本介绍

图像拼接技术就是将数张有重叠部分的图像(可能是不同时间、不同视角或者不同传感器获得的)拼成一幅无缝的全景图或高分辨率图像的技术。图像拼接在医学成像、计算机视觉、卫星数据、军事目标自动识别等领域具有重要意义。图像拼接的输出是两个输入图像的并集。
图像配准(image alignment)和图像融合是图像拼接的两个关键技术。图像配准是图像融合的基础,而且图像配准算法的计算量一般非常大,因此图像拼接技术的发展很大程度上取决于图像配准技术的创新。早期的图像配准技术主要采用点匹配法,这类方法速度慢、精度低,而且常常需要人工选取初始匹配点,无法适应大数据量图像的融合。图像拼接的方法很多,不同的算法步骤会有一定差异,但大致的过程是相同的。

1.2 基本原理

全景融合的3D 几何解释:

– 图像被投影到共同的拼接平面上(同一坐标系)
– 在拼接平面上实现全景融合

在图像拼接中首先利用SIFT算法提取图像特征进而进行特征匹配,继而使用RANSAC算法对特征匹配的结果进行优化,接着利用图像变换结构进行图像映射,最终进行图像融合。
在图像拼接过程中,运用SIFT局部描述算子检测图像中的关键点和特征,SIFT特征是基于物体上的一些局部外观的兴趣点而与影像的大小和旋转无关。对于光线、噪声、些微视角改变的容忍度也相当高,所以用来检测要拼接图像的特征及关键点就很有优势。而接下来是找到重叠的图片部分,连接所有图片之后就可以形成一个基本的全景图了。匹配图片最常用的方式是采用RANSAC(RANdom SAmple Consensus, 随机抽样一致),用此排除掉不符合大部分几何变换的匹配。之后利用这些匹配的点来估算单应矩阵”(Homography Estimation),也就是将其中一张图像通过关联性和另一张匹配。

以上关于SIFT算法、RANSAC算法以及图像变换结构可见上一篇博客详解(计算机视觉——SIFT特征提取与检索)。

1.2.1 APAP算法

在图像拼接融合的过程中,受客观因素的影响,拼接融合后的图像可能会存在“鬼影现象”以及图像间过度不连续等问题。下图就是图像拼接的一种“鬼影现象”。解决鬼影现象可以采用APAP算法。
算法流程:

1 提取两张图片的sift特征点
2 对两张图片的特征点进行匹配
3 匹配后,使用RANSAC算法进行特征点对的筛选,排除错误点。筛选后的特征点基本能够一一对应
4 使用DLT算法,将剩下的特征点对进行透视变换矩阵的估计
5 由于得到的透视变换矩阵是基于全局特征点对进行的,即一个刚性的单应性矩阵完成配 准。为提高配准的精度,Apap将图像切割成无数多个小方块,对每个小方块进行单应性矩阵变换,非常依赖于特征点对。若图像高频信息较少,特征点对过少,配准将完全失效,并且对大尺度的图像进行配准,其效果也不是很好,一切都决定于特征点对的数量。

1.2.2 寻找最佳拼接缝(Seam Finding)

在进行图像拼接中针对于鬼影现象可以很好地解决的的算法即为Seam Finding(寻找最佳拼接缝)。该算法的效果如下图:计算机视觉python--全景图像拼接_第1张图片

可以看到Seam Finding算法可以很好地解决鬼影现象,算法主要原理运用了最大流最小割的思想。图是一个具有权值的有向结构,通常采用一些节点,一些有向连接线表示,这些节点是像素值,或其他特征点。寻找代价最小的分割,典型算法是最小割最大流算法。最大流几句诗将图内带权值看作带有流量值的管道,将最大量水从源点送到汇点。

如何寻找一条最佳拼接缝:将匹配点最为接近的点作为拼接缝上的点,最终构造出拼接缝。

1.2.3 图像融合(multi-band bleing)

融合目的在于拼缝消除, Multi-Band能够达到比较好的融合效果,但是效率低,采用Laplacian(拉普拉斯)金字塔,通过对相邻两层的高斯金字塔进行差分,将原图分解成不同尺度的子图,对每一个之图进行加权平均,得到每一层的融合结果,最后进行金字塔的反向重建,得到最终融合效果过程。
由下图可知multi-band bleing的效果对于拼接之后的图像进行融合的效果是很好的。
计算机视觉python--全景图像拼接_第2张图片

思想:采用的方法是直接对带拼接的两个图片进行拉普拉斯金字塔分解,后一半对前一半进行融合。
步骤:
(1)首先计算当前待拼接图像和已合成图像的重叠部分。
计算机视觉python--全景图像拼接_第3张图片

(2)两幅图像的融合:分别构建图像A、B的高斯金字塔和拉普拉斯金字塔,然后进行加权融合。
计算机视觉python--全景图像拼接_第4张图片

(3)对加权后的拉普拉斯金字塔进行重构。
计算机视觉python--全景图像拼接_第5张图片

1.3 基本流程

图像拼接的基本流程如下:

1 根据给定图像/集,实现特征匹配
2 通过匹配特征计算图像之间的变换结构
3 利用图像变换结构,实现图像映射
4 针对叠加后的图像,采用APAP之类的算法,对齐特征点
5 通过图割方法,自动选取拼接缝
6 根据multi-band bleing策略实现融合

1.4 代码实现

# ch3_panorama_test.py
from pylab import *
from numpy import *
from PIL import Image
# If you have PCV installed, these imports should work
from PCV.geometry import homography, warp
from PCV.localdescriptors import sift
"""
This is the panorama example from section 3.3.
""" 
# set paths to data folder
featname = ['F:test4\\group1\\1\\' + str(i + 1) + '.sift' for i in range(3)]
imname = ['F:test4\\group1\\1\\' + str(i + 1) + '.jpg' for i in range(3)]
# extract features and match
l = {}
d = {}
for i in range(3): 
    sift.process_image(imname[i],featname[i])
    l[i],d[i] = sift.read_features_from_file(featname[i])
matches = {}
for i in range(2):
    matches[i] = sift.match(d[i+1],d[i])
    print(matches) 
# visualize the matches (Figure 3-11 in the book)
for i in range(2):
    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([tp[1],tp[0],tp[2]])
    return fp,tp
# estimate the homographies
model = homography.RansacModel()  
fp,tp = convert_points(0)
H_01 = homography.H_from_ransac(fp,tp,model)[0] #im 0 to 1 
tp,fp = convert_points(1) #NB: reverse order
H_21 = homography.H_from_ransac(fp,tp,model)[0] #im 2 to 1  
# warp the images
delta = 2000 # for padding and translation
im1 = array(Image.open(imname[0]), "uint8")
im2 = array(Image.open(imname[1]), "uint8")
im_01 = warp.panorama(H_01,im1,im2,delta,delta)
im1 = array(Image.open(imname[2]), "f")
im_21 = warp.panorama(H_21,im1,im_01,delta,delta)
figure()
imshow(array(im_21, "uint8"))
axis('off')
savefig("example5.png",dpi=300)
show()

1.5 实验结果

1.5.1 固定点位拍摄实现图像拼接

计算机视觉python--全景图像拼接_第6张图片
计算机视觉python--全景图像拼接_第7张图片

1 拼接的效果不是很好 应该是图中物体的差异度也就是两个屏幕和两个音响的太类似导致特征的点的匹配出现错误 而ransac算法起到的效果也很一般导致拼接效果不好 说明景色简单的图片直接的拼接是比较困难的
2 在拼接运行时运行的时间属实多点久 因为图片的像素太大了 导致每一个像素点的映射需要很长的时间 可先将图片进行压缩然后再进行拼接可以很有效的改进运行时间

1.5.2 视差变化大的场景实现图像拼接

计算机视觉python--全景图像拼接_第8张图片
计算机视觉python--全景图像拼接_第9张图片

拼接完后 近处红色花和盆栽的部分出现了两次 这是因为拼接找特征点匹配的时候匹配点集中出现在远处的景色的 但是由于是在不同的位置进行拍摄的 所当进行像素点映射的时候 会只照顾远处景色的拼接而导致近处的盆栽效果不好 可以清晰的看出来第二张图片是斜着映射进去的 而因为位置不同导致第一张图片会有较大的与第一张图片相同的景色单独暴露出来

1.7 实验中遇到的问题

问题1

Traceback (most recent call last):
  File "F:PJ.py", line 7, in <module>
    from PCV.geometry import homography, warp
  File "F:warp.py", line 128
    print 'warp - left'                      ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(print 'warp - left')?
[Finished in 4.7s]

因为版本的问题 在print后面要加括号

问题2
计算机视觉python--全景图像拼接_第10张图片

因为PCV下面的warp.py里面的matplotlib.delaunay不再被使用了,所以把它换成一个相同功能的就可以:
①:把import matplotlib.delaunay as md 换成from scipy.spatial import Delaunay
②:warp.py里面的centers,edges,tri,neighbors = md.delaunay(x,y)换成tri= Delaunay(np.c_[x,y]).simplices就好啦

问题3
计算机视觉python--全景图像拼接_第11张图片

因为索引超了 我的图像集有五张图片 应该给range后面数字改成5

你可能感兴趣的:(计算机视觉python--全景图像拼接)