Python OpenCV基于SURF特征匹配的图像拼接实现详解
本文详细介绍利用Python和OpenCV实现图像拼接的方法。通过SURF算法检测关键特征点,使用FLANN匹配器进行快速特征匹配,并筛选优质匹配点计算仿射变换矩阵。最终通过透视变换将左图映射到右图位置,完成全景图像的合成,并提供了完整的代码示例及抗干扰测试分析。
图像拼接原理概述
初级图像拼接仅涉及将两幅图像在几何空间上进行简单的粘贴与合成,不涉及图像内容的深层处理。而高级图像拼接,即基于特征匹配的拼接方式,旨在消除两幅图像中的重叠部分,从而实现无缝的全景图合成。
假设存在尺寸相同的图A和图B,它们包含相同区域与不同区域,具体结构如图所示:

应用基于特征的图像拼接算法处理后,结果如下所示:

设图像高度为h,两幅图像相同部分的宽度为wx。
拼接后图像的总宽度w等于图A宽度wA加上图B宽度wB,再减去重叠部分宽度wx,即w=wA+wB-wx。
基于上述原理,可构建一个高度为h、宽度为W*2的空白图像。将左图像向右平移wx距离,并将右图像粘贴至右侧区域,此时右图像恰好覆盖左图像中的相同部分。最终生成的图像左侧会保留宽度为wx的空白区域,该区域对应检测出的两幅图像相同部分,可根据实际需求选择是否裁剪去除。示例图如下。
基于特征匹配的拼接步骤
实现上述效果的具体步骤如下:
1. 采用SURF特征检测算法,识别两幅图像中的关键特征点;
2. 构建FLANN匹配器,利用目前最快的特征匹配算法(最近邻搜索)即FlannBasedMatcher对关键点进行匹配;
3. 从所有匹配的关键点中,基于距离标准筛选出优质的特征点;
4. 根据查询图像和模板图像的特征描述子索引,计算得出仿射变换矩阵;
5. 获取从左边图像到右边图像的投影映射关系;
6. 执行透视变换,将左图像放置到相应的位置;
7. 将右图像拷贝到指定位置,完成拼接操作。
Python OpenCV代码实现与测试
以下为在Python环境下利用OpenCV进行图像拼接的代码示例,运行环境为Python 2.7配合OpenCV 2:
#coding: utf-8
import numpy as np
import cv2
leftgray = cv2.imread('1.jpg')
rightgray = cv2.imread('2.jpg')
hessian=400
surf=cv2.SURF(hessian) #将Hessian Threshold设置为400,阈值越大能检测的特征就越少
kp1,des1=surf.detectAndCompute(leftgray,None) #查找关键点和描述符
kp2,des2=surf.detectAndCompute(rightgray,None)
FLANN_INDEX_KDTREE=0 #建立FLANN匹配器的参数
indexParams=dict(algorithm=FLANN_INDEX_KDTREE,trees=5) #配置索引,密度树的数量为5
searchParams=dict(checks=50) #指定递归次数
#FlannBasedMatcher:是目前最快的特征匹配算法(最近邻搜索)
flann=cv2.FlannBasedMatcher(indexParams,searchParams) #建立匹配器
matches=flann.knnMatch(des1,des2,k=2) #得出匹配的关键点
good=[]
#提取优秀的特征点
for m,n in matches:
if m.distance < 0.7*n.distance: #如果第一个邻近距离比第二个邻近距离的0.7倍小,则保留
good.append(m)
src_pts = np.array([ kp1[m.queryIdx].pt for m in good]) #查询图像的特征描述子索引
dst_pts = np.array([ kp2[m.trainIdx].pt for m in good]) #训练(模板)图像的特征描述子索引
H=cv2.findHomography(src_pts,dst_pts) #生成变换矩阵
h,w=leftgray.shape[:2]
h1,w1=rightgray.shape[:2]
shft=np.array([[1.0,0,w],[0,1.0,0],[0,0,1.0]])
M=np.dot(shft,H[0]) #获取左边图像到右边图像的投影映射关系
dst_corners=cv2.warpPerspective(leftgray,M,(w*2,h))#透视变换,新图像可容纳完整的两幅图
cv2.imshow('tiledImg1',dst_corners) #显示,第一幅图已在标准位置
dst_corners[0:h,w:w*2]=rightgray #将第二幅图放在右侧
#cv2.imwrite('tiled.jpg',dst_corners)
cv2.imshow('tiledImg',dst_corners)
cv2.imshow('leftgray',leftgray)
cv2.imshow('rightgray',rightgray)
cv2.waitKey()
cv2.destroyAllWindows()
所使用的测试图像为:

拼接完成后的最终图像效果为:

为了验证算法的抗干扰能力,使用以下图像进行测试:

测试结果如下:

可见,该方法的抗干扰能力表现良好。若在测试中出现拼接失败的情况,请重点检查以下两点:
1. 确认所使用的两幅图像尺寸是否一致,且是否存在相同的部分。
2. 适当调整Hessian阈值(hessian)的值。
总结
以上介绍了基于Python和OpenCV的图像拼接实现方法,希望能为读者提供帮助。如有任何疑问,欢迎留言,小编会及时回复!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









