计算机视觉——图像拼接

实验环境

系统:Ubuntu16.04
语言:python3.7

图像映射的基本原理

基于SIFT的特征点的提取与匹配

利用Sift提取图像的局部特征,在尺度空间寻找极值点,并提取出其位置、尺度、方向信息。

具体步骤:

1). 生成高斯差分金字塔(DOG金字塔),尺度空间构建

2). 空间极值点检测(关键点的初步查探)

3). 稳定关键点的精确定位

4). 稳定关键点方向信息分配

5). 关键点描述

6). 特征点匹配

图像配准

图像配准是一种确定待拼接图像间的重叠区域以及重叠位置的技术,它是整个图像拼接的核心。本节采用的是基于特征点的图像配准方法,即通过匹配点对构建图像序列之间的变换矩阵,从而完成全景图像的拼接。

变换矩阵H求解是图像配准的核心,其求解的算法流程如下。

1)检测每幅图像中特征点。

2)计算特征点之间的匹配。

3)计算图像间变换矩阵的初始值。

4)迭代精炼H变换矩阵。

5)引导匹配。用估计的H去定义对极线附近的搜索区域,进一步确定特征点的对应。

6)重复迭代4)和5)直到对应点的数目稳定为止。

设图像序列之间的变换为投影变换

可用4组最佳匹配计算出H矩阵的8 个自由度参数hi=( i=0,1,…,7),并以此作为初始值。

为了提高图像配准的精度,本节采用RANSAC算法对图像变换矩阵进行求解与精炼,达到了较好的图像拼接效果。RANSAC算法的思想简单而巧妙:首先随机地选择两个点,这两个点确定了一条直线,并且称在这条直线的一定范围内的点为这条直线的支撑。这样的随机选择重复数次,然后,具有最大支撑集的直线被确认为是样本点集的拟合。在拟合的误差距离范围内的点被认为是内点,它们构成一致集,反之则为外点。根据算法描述,可以很快判断,如果只有少量外点,那么随机选取的包含外点的初始点集确定的直线不会获得很大的支撑,值得注意的是,过大比例的外点将导致RANSAC算法失败。在直线拟合的例子中,由点集确定直线至少需要两个点;而对于透视变换,这样的最小集合需要有4个点。

图像融合

因为相机和光照强度的差异,会造成一幅图像内部,以及图像之间亮度的不均匀,拼接后的图像会出现明暗交替,这样给观察造成极大的不便。 亮度与颜色均衡处理,通常的处理方式是通过相机的光照模型,校正一幅图像内部的光照不均匀性,然后通过相邻两幅图像重叠区域之间的关系,建立相邻两幅图像之间直方图映射表,通过映射表对两幅图像做整体的映射变换,最终达到整体的亮度和颜色的一致性。

实验流程

实验数据来源

本次实验所进行拼接的图片为笔者在校园里随意拍摄所得。

代码展示

from numpy import *
from matplotlib.pyplot import *
from PIL import Image
import warp
import homography
from PCV.localdescriptors import sift


featname = ['图片路径' + str(i + 1) + '.sift' for i in range(5)] #这里的5可自行根据图片数量改变
imname = ['图片路径' + str(i + 1) + '.jpg' for i in range(5)] #这里的5可自行根据图片数量改变
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)

# 将匹配转换成齐次坐标点的函数
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


# 估计单应性矩阵
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

# 扭曲图像
# img delta
# delta = 100  # 用于填充和平移 for padding and translation
# libraryimg delta
delta = 1000

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')
show()

实验结果展示

其中分别展示使用sift进行特征点匹配的结果和原图的对比
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到在上一篇的特征匹配上还是完成的很好的,有了上面的实验基础,一步我们尝试进行图像拼接

拼接结果

在这里插入图片描述

实验结果总结

从此次实验来看图片都是在景深比较丰富的地方,由于景深较为丰富,所以特征匹配点较多,在进行拼接时参考点较多,所以拼接结果的成功率就较高。可以看到成功的例子整体拼接起来完成度还是很高的。但是要是当有近景和远景时,由于图片中的景物处于不同平面,景深变化大,会出现鬼影现象。在利用RANSAC算法进行拼接的时候都不可避免地出现了重叠鬼影现象,这也是病态问题。

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值