Python计算机视觉之全景图像拼接

目录

一、概述

二、基本介绍及步骤

三、原理

3.1 RANSAC算法

3.1.1 概述

3.1.2 基本思想

 3.2 APAP算法

3.2.1 概述

3.2.2 基本思想

 四、代码实现


一、概述

        全景图像(全景图)是指利用摄像机的平移或旋转得到的部分重叠的图像样本,生成一个较大的甚至360°的全方位图像的场景绘制方法。换句话说,就是给定某个真实场景的一组局部图像,然后对这一组图像进行拼接,生成包含这组局部图像的新视图。目前全景图像基本可分为柱面、球面、立方体等形式,以柱面和球面全景图最易实现而普遍采用。

二、基本介绍及步骤

        图像配准(image alignment)和图像融合是图像拼接的两个关键技术。图像配准是图像融合的基础,而且图像配准算法的计算量一般非常大,因此图像拼接技术的发展很大程度上取决于图像配准技术的创新。早期的图像配准技术主要采用点匹配法,这类方法速度慢、精度低,而且常常需要人工选取初始匹配点,无法适应大数据量图像的融合。图像拼接的方法很多,不同的算法步骤会有一定差异,但大致的过程是相同的。一般来说,图像拼接主要包括以下五步: 

图像预处理

        包括数字图像处理的基本操作(如去噪、边缘提取、直方图处理等)、建立图像的匹配模板以及对图像进行某种变换(如傅里叶变换、小波变换等)等操作。

图像配准

        就是采用一定的匹配策略,找出待拼接图像中的模板或特征点在参考图像中对应的位置,进而确定两幅图像之间的变换关系。

建立变换模型

        根据模板或者图像特征之间的对应关系,计算出数学模型中的各参数值,从而建立两幅图像的数学变换模型。

统一坐标变换

        根据建立的数学转换模型,将待拼接图像转换到参考图像的坐标系中,完成统一坐标变换。

融合重构

        将待拼接图像的重合区域进行融合得到拼接重构的平滑无缝全景图像。

三、原理

     之前的博客已经对Harris角点检测算法和SIFT特征检测算法有了较为详细的讲解,这里就不再继续赘述,接下来以RANSAC算法和APAP算法为例让大家更进一步感受图像拼接这一门技术。

3.1 RANSAC算法

3.1.1 概述

        RANSAC为Random Sample Consensus的缩写,它是根据一组包含异常数据的样本数据集,计算出数据的数学模型参数,得到有效样本数据的算法。它于1981年由Fischler和Bolles最先提出。RANSAC算法的基本假设是样本中包含正确数据(inliers,可以被模型描述的数据),也包含异常数据(outliers,偏离正常范围很远、无法适应数学模型的数据),即数据集中含有噪声。这些异常数据可能是由于错误的测量、错误的假设、错误的计算等产生的。同时RANSAC也假设,给定一组正确的数据,存在可以计算出符合这些数据的模型参数的方法。

3.1.2 基本思想

        RANSAC通过反复选择数据中的一组随机子集来达成目标。被选取的子集被假设为局内点,并用下述方法进行验证:

  1. 有一个模型适用于假设的局内点,即所有的未知参数都能从假设的局内点计算得出。

  2. 用1中得到的模型去测试所有的其它数据,如果某个点适用于估计的模型,认为它也是局内点。

  3. 如果有足够多的点被归类为假设的局内点,那么估计的模型就足够合理。

  4. 然后,用所有假设的局内点去重新估计模型,因为它仅仅被初始的假设局内点估计过。

  5. 最后,通过估计局内点与模型的错误率来评估模型。

这个过程被重复执行固定的次数,每次产生的模型要么因为局内点太少而被舍弃,要么因为它比现有的模型更好而被选用。

        对上述步骤可简单总结为:

N:样本点个数,K:求解模型需要的最少的点的个数

  1. 随机采样K个点
  2. 针对该K个点拟合模型
  3. 计算其它点到该拟合模型的距离,小于一定阈值当做内点,统计内点个数
  4. 重复M次,选择内点数最多的模型
  5. 利用所有的内点重新估计模型(可选)

举例:利用RANSAC算法拟合一条直线 

 

 

 

 

N:样本点个数,K:求解模型需要的最少的点的个数,P:该点为内点的概率

P^{K}:K个点都是内点的概率

1-P^{K}:K个点至少有一个外点的概率(采样失败)

\left ( 1-P^{K} \right )^{M}:M次采样全部失败的概率

Z=1-\left ( 1-P^{K} \right )^{M}:M次采样至少有一次成功的概率

计算P=0.9,K=8,想要采样成功率达到Z>=0.99时,所需要的采样次数M

                                                                   M=\frac{log\left ( 1-Z \right )}{log\left ( 1-P^{K} \right )} 

 3.2 APAP算法

3.2.1 概述

        在图像拼接融合的过程中,受客观因素的影响,拼接融合后的图像可能会存在“鬼影现象”以及图像间过度不连续等问题。下图就是图像拼接的一种“鬼影现象”。通过上面RANSAC方法可以消除异常匹配的特征点的问题,但是匹配后得到的图像会出现“鬼影”问题,所谓鬼影问题就是图像叠加后出现重影。解决办法就是局部单应性变换。解决鬼影现象可以采用APAP算法。

3.2.2 基本思想

1.SIFT得到两幅图像的匹配点对
2.通过RANSAC剔除外点,得到N对内点
3.利用DLT和SVD计算全局单应性
4.将源图划分网格,取网格中心点,计算每个中心点和源图上内点之间的欧式距离和权重
5.将权重放到DLT算法的A矩阵中,构建成新的W*A矩阵,重新SVD分解,自然就得到了当前网格的局部单应性矩阵
6.遍历每个网格,利用局部单应性矩阵映射到全景画布上,就得到了APAP变换后的源图
7.最后就是进行拼接线的加权融合

        APAP算法虽然能够较好地完成配准,但非常依赖于特征点对。若图像高频信息较少,特征点对过少,配准将完全失效,并且对大尺度的图像进行配准,其效果也不是很好,一切都决定于特征点对的数量。

 四、代码实现

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 = [str(i + 1) + '.sift' for i in range(3)]
imname = [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("result.png",dpi=300)
show()

 

 

 

 

 

  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
全景图像拼接是将多张拍摄自同一地点、视角不同的照片拼接成一张大的全景图像。OpenCV是一个非常强大的计算机视觉库,可以用来实现全景图像拼接。 下面是实现全景图像拼接的基本步骤: 1. 加载图片。使用OpenCV的cv2.imread()函数加载图片。 2. 特征点检测。使用OpenCV的SIFT、SURF、ORB等算法检测每张图片的特征点。 3. 特征点匹配。使用OpenCV的FLANN或者Brute-Force算法对特征点进行匹配。 4. 计算单应性矩阵。使用OpenCV的findHomography函数计算单应性矩阵,将当前图片与上一张图片进行拼接。 5. 图像拼接。使用OpenCV的warpPerspective函数将当前图片进行透视变换,然后将图片拼接到上一张图片上。 6. 重复步骤2-5,直到所有图片拼接完成。 下面是一个基于OpenCV实现全景图像拼接的示例代码: ```python import cv2 import numpy as np # 加载图片 img1 = cv2.imread('img1.jpg') img2 = cv2.imread('img2.jpg') # 特征点检测 sift = cv2.xfeatures2d.SIFT_create() kp1, des1 = sift.detectAndCompute(img1, None) kp2, des2 = sift.detectAndCompute(img2, None) # 特征点匹配 bf = cv2.BFMatcher() matches = bf.knnMatch(des1, des2, k=2) good_matches = [] for m, n in matches: if m.distance < 0.75 * n.distance: good_matches.append(m) src_pts = np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2) dst_pts = np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2) # 计算单应性矩阵 M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) # 图像拼接 result = cv2.warpPerspective(img1, M, (img1.shape[1] + img2.shape[1], img1.shape[0])) result[0:img2.shape[0], 0:img2.shape[1]] = img2 cv2.imshow('result', result) cv2.waitKey(0) cv2.destroyAllWindows() ``` 这段代码实现了两张图片的拼接。你可以使用这个基本的框架,将多张图片进行拼接,从而实现全景图像拼接

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值