计算机视觉 图像映射和全景拼接

目录

一.图像映射:

1.图像映射基础:

1.1. 基础流程 :

1.2. 计算变换结构流程:

2. 2D 图像变换原理:

2.1. 图像滤波: 改变图像的像素点取值范围:

2.2. 图像变换: 改变图像的坐标取值范围:

2.3. 2D 图像变换类型:

二.全景拼接:

1.拼接原理:

2.RANSAC算法:

3.实验结果:

3.1.实验数据:

 3.2.实验代码:

3.3.实验结果:


一.图像映射:

1.图像映射基础:

        如何将两幅或多幅具有重叠区域的图像,合并成一张大图?
我们需要以下步骤:

1.1. 基础流程 :

① 针对某个场景拍摄多张 / 序列图像
② 计算第二张图像与第一张图像之间的变换关系
③ 将第二张图像叠加到第一张图像的坐标系中
④ 变换后的融合 / 合成
⑤ 在多图场景中,重复上述过程

 

在拼接的应用中,其实可以简化理解为 2D 图像的变换,叠加过程;

1.2. 计算变换结构流程:

提取特征点,生成描述符
特征匹配
计算变换结构

2. 2D 图像变换原理:

2.1. 图像滤波: 改变图像的像素点取值范围:

2.2. 图像变换: 改变图像的坐标取值范围:

 

2.3. 2D 图像变换类型:

 

 

 

二.全景拼接:

1.拼接原理:

相关流程:

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

        特征匹配过程是运用SIFT局部描述算子检测图像中的关键点和特征,SIFT特征是基于物体上的一些局部外观的兴趣点而与影像的大小和旋转无关。对于光线、噪声、些微视角改变的容忍度也相当高;然后通过一系列图片变化后找到重叠的图片部分,连接所有图片之后就可以形成一个基本的全景图;最常用的方法是采用RANSAC,用此排除掉不符合大部分几何变换的匹配。

2.RANSAC算法:

        RANSAC 算法假设数据中包含正确数据和异常数据(或称为噪声)。正确数据记为内点(inliers),异常数据记为外点(outliers)。同时 RANSAC 也假设,给定一组正确的数据,存在可以计算出符合这些数据的模型参数的方法。该算法核心思想就是随机性和假设性,随机性是根据正确数据出现概率去随机选取抽样数据,根据大数定律,随机性模拟可以近似得到正确结果。假设性是假设选取出的抽样数据都是正确数据,然后用这些正确数据通过问题满足的模型,去计算其他点,然后对这次结果进行一个评分。

RANSAC 求解单应矩阵:
RANSAC loop:
1. 随机选择四对匹配特征
2. 根据 直接线性变换解法 DLT 计算单应矩阵 H (唯一解 )
3. 对所有匹配点,计算映射误差 ε= || p i ’, H p i ||
4. 根据误差阈值,确定 inliers (例如 3-5 像素)
5. 针对最大 inliers 集合,重新计算单应矩阵 H

3.实验结果:

3.1.实验数据:

 

 

 3.2.实验代码:

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
np.seterr(invalid='ignore')


# 设置数据文件夹的路径
featname = ['D:\\image inform\\picture\\' + str(i + 1) + '.sift' for i in range(5)]
imname = ['D:\\image inform\\picture\\' + str(i + 1) + '.jpg' for i in range(5)]

# 提取特征并匹配使用sift算法
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])

# 可视化匹配
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

# 扭曲图像
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)

figure()
imshow(array(im_42, "uint8"))
axis('off')
show()

3.3.实验结果:

 

 最终效果图:

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值