python计算机视觉编程——全景拼接

全景拼接

  • 一、图像拼接
    • 1.1什么是图像拼接
    • 1.2图像拼接的用到的技术支持
      • 1.2.1 APAP算法
      • 1.2.2 用最大流最小割找拼接裂缝
      • 1.2.3 multi-band blending实现图像融合
    • 1.3用python完成简单的图像拼接
      • 1.3.1实验代码
      • 1.3.2实验内容与分析
      • 1.3.3实验小结与问题解决

一、图像拼接

1.1什么是图像拼接

图像拼接(Image Stitching)是一种利用实景图像组成全景空间的技术,它将多幅图像拼接成一幅大尺度图像或360度全景图,图像拼接技术涉及到计算机视觉、计算机图形学、数字图像处理以及一些数学工具等技术。图像拼接其基本步骤主要包括以下几个方面:摄相机的标定、传感器图像畸变校正、图像的投影变换、匹配点选取、全景图像拼接(融合),以及亮度与颜色的均衡处理等方面。这篇博文主要从后期处理,即匹配点选取和具体的全景拼接技术的实现来论述。

1.2图像拼接的用到的技术支持

在以前的博文中有有关sift特征匹配算法,这里不再过多赘述。这次将其应用到图像的全景拼接上,根据特征点匹配的方式,则利用这些匹配的点来估算单应矩阵(使用以前博文中提到的RANSAC算法(该算法用于优化sift算法减少错误的特征匹配),也就是把其中一张通过个关联性和另一张匹配的方法。通过单应矩阵H,可以将原图像中任意像素点坐标转换为新坐标点,转换后的图像即为适合拼接的结果图像。
可以简单分为以下几步:
1.根据给定图像/集,实现特征匹配。
2.通过匹配特征计算图像之间的变换结构。
3.利用图像变换结构,实现图像映射。
4.针对叠加后的图像,采用APAP之类的算法,对齐特征点。(图像配准)
5.通过图割方法,自动选取拼接缝。
6.根据multi-band blending策略实现融合。

根据以上的全景拼接用到的方法赘述,除了我以前博文中有介绍过的有关特征匹配图像变换的知识点以外,这次的重点技术介绍是有关图像配准的,即如何将两张特征匹配后相似度很高的图像对齐特征点进行叠加拼接,通过某种方法找到两张图片的拼接裂缝,使其很好的融合,再通过multi-band blending的方法对图像拍摄时产生的不同曝光度对拼接后的图像进行处理,使拼接后的图像在人眼视觉效果上更加柔和。

1.2.1 APAP算法

图像配准是对图像进行变换,使变换后的图像能够在常见的坐标系中对齐。为了能够进行图像对比和更精细的图像分析,图像配准是一步非常重要的操作。这里主要用到的算法为APAP算法。
这边引用了csdn中有关博主对于APAP算法的解读,我觉得有助于理解该算法的基本流程和实现。

https://blog.csdn.net/warrenwg/article/details/49759779

基本步骤:
1.提取两张图片的sift特征点
2.对两张图片的特征点进行匹配,匹配的过程引用了论文(Distinctive Image Features from Scale-Invariant Keypoints)
3.匹配后,仍有很多错误点,此时使用论文(Accelerated Hypothesis Generation for Multi-Structure Robust Fitting)提到的RANSAC的改进算法进行特征点对的筛选。筛选后的特征点基本能够一一对应。
4.使用DLT算法(Multiple View Geometry p92提到),将剩下的特征点对进行透视变换矩阵的估计。
5.因为得到的透视变换矩阵是基于全局特征点对进行的,即一个刚性的单应性矩阵完成配准。为提高配准的精度,Apap将图像切割成无数多个小方块,对每个小方块的变换矩阵逐一估计
Apap虽然能够较好地完成配准,但非常依赖于特征点对,存在局限性。若图像高频信息较少,特征点对过少,配准将完全失效,并且对大尺度的图像进行配准,其效果也不是很好,一切都决定于特征点对的数量

1.2.2 用最大流最小割找拼接裂缝

作为解决图论问题的经典方法,我完全没想到这个方法可以用在图像处理的拼接问题上,即图割。以下这篇博文在我看来整理的非常通俗易懂,推荐参考。
最大流最小割

1.2.3 multi-band blending实现图像融合

在图像拼接过程中,根据所采集的样本在拍照角度和曝光度上的不同,会导致拼接后的图像灰度情况层次不齐,虽然在视觉效果上拼接后的图片很好的重合,但是人眼感受到的拼接带来的光效痕迹还是过于明显,所以需要特定的处理解决这种不自然。那么这时候可以采用blending方法。multi-band blending(多波段融合又称为拉普拉斯金字塔融合)是目前图像融和方面比较好的方法,人们可以通过这种方法较好的融合样本图像,即通俗而言的毫无PS痕迹。
python计算机视觉编程——全景拼接_第1张图片
多波段融合的思想是对待融合的图像分别构建拉普拉斯金字塔,(拉普拉斯算子可以提取出图像的高频信息,在拉普拉斯金字塔中,越往上层的图像越高频)然后对同一层图像按照某种规则融合,一般是Alpha blending/Feathering;对于不同层图像(不同频率段的图像)进行不同规则的融合,高频部分blend slowly,低频部分blend quickly;
基本步骤:

1.根据图像A和B建立拉普拉斯金字塔LA和LB;

2.从选择蒙版M中建立高斯金字塔GM;

3.使用GM的节点作为权重,从LA和LB组成金字塔金字塔LS:

LS = GM * LA +(1-GM)* LB

4.折叠LS金字塔以获得最终的融合图像

这里我参考了一篇详细论述拉普拉斯金字塔融合的博文,推荐参考阅读。
https://blog.csdn.net/u014485485/article/details/89516028

下面开始测试拼接吧。

1.3用python完成简单的图像拼接

1.3.1实验代码


# -*- coding: utf-8
from pylab import *
from numpy import *
from PIL import Image
from scipy.spatial import Delaunay
# If you have PCV installed, these imports should work
from PCV.geometry import homography, warp
from PCV.localdescriptors import sift


featname = [ 'E:/thirddown/computervision/data/ransac/AP/1/'+ str(i + 1) + '.sift' for i in range(5)]
imname = ['E:/thirddown/computervision/data/ransac/AP/1/' + str(i + 1) + '.jpg' for i in range(5)]

# extract features and match
l = {}
d = {}
for i in range(5):
    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([tp[1], tp[0], tp[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  # im1 到 im2 的单应性矩阵


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 = 2000  # 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)
imsave('example.jpg', array(im_42, "uint8"))
figure()
imshow(array(im_42, "uint8"))
axis('off')
show()

1.3.2实验内容与分析

①针对固定点位拍摄多张图片,以中间图片为中心,实现图像的拼接融合

数据集①
python计算机视觉编程——全景拼接_第2张图片
python计算机视觉编程——全景拼接_第3张图片

从实验结果来看,最开始的时候没有看清理解代码,导致拼接出来的图片有很多黑屏和错配,后来发现是代码逻辑要求我们的数据集合,必须要从右往左依次编号才行。修改过后即可以正确拼接。为了拼接处理速度变快,我将图片的像素从原来的2448x3264改为1000x1333。大体上看这张全景图像的拼接算是比较成功,出来中央有一条拼接缝的光线曝光度相差明显之外没有很大的不足,但是放大来看,为了使特征匹配符合,也有一定的错位。
python计算机视觉编程——全景拼接_第4张图片
在这里插入图片描述
数据集②
python计算机视觉编程——全景拼接_第5张图片

由于曝光度问题,导致拼接后的图像色彩有差异,但是总体来说,拼接效果答题良好,除了特征点匹配较为密集的建筑物上有少许偏倚,答题拼接良好。因为图像的伸缩变换,导致一些像素信息丢失,放大看有写地方失真。
python计算机视觉编程——全景拼接_第6张图片
②2. 针对同一场景(需选取视差变化大的场景,也就是有近景目标),更换拍摄位置,分析拼接结果
python计算机视觉编程——全景拼接_第7张图片
python计算机视觉编程——全景拼接_第8张图片
python计算机视觉编程——全景拼接_第9张图片
从实验结果来看,对于有主图物的拼接,效果很好,图上拼接部分除了明显的肉眼差异,中间的红圈部分的拼接几乎不可视,是很优秀的一次实验测试,五张图片的最右张样本图因为有伸缩尺度的关系,导致拼接没有很拟合,但是主要建筑物这个是算法的局限性。相对于数据集②,在同一场景拍摄,有主图物的特征匹配明显的拼接效果更好。

1.3.3实验小结与问题解决

关于我所使用的全景拼接算法局限性很大,对于处于统一地点的拍摄,旋转镜头越稳定,没有上下或者尺度上的偏倚和光线上的曝光度不一致的情况下,拼接效果才会比较好,即在统一水平线上旋转角度拍摄不晃动镜头。从上面的测试中我也发现了许多问题,比如拼接时发生错拼现象,这些都是特征处理时发生的错配较多引起的,所以一个好的特征提取匹配算法是全景拼接效果好的基础。同时代码中有个参数delta。这个参数是针对你拍摄图像时,你相对平移的距离的变量,当你拍摄近景时候,这个参数尽量该小,远景相反。dpi是图像精细度的变量,可以通过修改来改变图像的分辨率,数值越大表示图像越精细,即分辨率越高。该拼接技术对有主体的平移影响的拼接较好,对无主体的拼接较差。

这个问题出现说明采集的图片无法达到匹配要求,因为算法局限性,该图像拼接只能对等水平等尺度的图片进行较好的拼接,所以应该重新采集过样本数据集。
在这里插入图片描述
图片太大导致内存运行不足溢出,同比修改样本集的像素大小,但是同样的像素修改过后会影响拼接的成功程度。

在这里插入图片描述
由于所写代码局限性数据集图片的名字要改为1.jpg,2.jpg依次类推,这段代码可以进行适当修改,便于遍历数据集。

在这里插入图片描述
数据集大小尺寸必须统一。

你可能感兴趣的:(python计算机视觉编程——全景拼接)