概念
图像拼接是计算机视觉领域中的一项技术,它涉及将多个图像合并成一个连续的、无缝的全景图像。在OpenCV中,图像拼接通常包括以下几个关键步骤:
1. 编写代码
-
导入必要的库 :导入
sys
、cv2
和numpy
库。 -
定义显示图像的函数 :编写
cv_show
函数,用于在窗口中显示图像。pythonimport sys import cv2 import numpy as np # 显示图像的函数 def cv_show(name,img): cv2.imshow(name,img) cv2.waitKey(0)
-
定义检测关键点和计算描述符的函数 :编写
detectAndDescribe
函数,使用SIFT算法检测图像中的关键点并计算描述符。python# 检测关键点并计算描述符的函数 def detectAndDescribe(image): gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) desciiptor=cv2.SIFT_create()#创建SIFT描述 #检测关键点并计算描述符 (kps,des)=desciiptor.detectAndCompute(gray,None)#kps 是检测到的关键点的列表,des 是关键点的描述符矩阵。 kps_float=np.float32([kp.pt for kp in kps])#转换关键点坐标为浮点数: return (kps,kps_float,des)
2. 读取图像
-
使用
cv2.imread
函数读取left.jpg
和right.jpg
图像。pythonimageA=cv2.imread('left.jpg') imageB=cv2.imread('right.jpg')
3. 检测关键点和计算描述符
-
对两幅图像分别调用
detectAndDescribe
函数,获取关键点和描述符。python#检测关键点并计算描述符 (kpsA,kps_floatA,desA)=detectAndDescribe(imageA) (kpsB,kps_floatB,desB)=detectAndDescribe(imageB)
4. 特征匹配
-
创建匹配器 :使用
cv2.BFMatcher
创建暴力匹配器。 -
进行K近邻匹配:对两幅图像的描述符进行K近邻匹配,获取匹配点对。
-
筛选好的匹配点 :使用Lowe's ratio test筛选出好的匹配点。
python#创建匹配器 matcher=cv2.BFMatcher() #进行K近邻匹配 rawMatches=matcher.knnMatch(desB,desA,2) good=[] matches=[] for m in rawMatches: if len(m)==2 and m[0].distance<0.65*m[1].distance: good.append(m) matches.append((m[0].trainIdx,m[0].queryIdx))
5. 计算单应性矩阵
-
检查匹配点数量:如果匹配点数量大于4,则继续;否则,程序退出。
-
计算单应性矩阵 :使用
cv2.findHomography
函数和RANSAC算法计算匹配点之间的单应性矩python#左侧连接 # 如果匹配点足够多,则进行下一步 if len(matches)>4: ptsA=np.float32([kps_floatA[i] for (i,_) in matches]) ptsB=np.float32([kps_floatB[i] for (_,i) in matches]) # 使用RANSAC算法计算单应性矩阵 (H,mask)=cv2.findHomography(ptsB,ptsA,cv2.RANSAC,10) else: sys.exit()
阵。
6. 图像变换和拼接
-
应用单应性矩阵 :使用
cv2.warpPerspective
函数对右图进行透视变换。 -
显示变换后的图像 :调用
cv_show
函数显示变换后的图像。 -
拼接图像:将左图拼接到变换后的右图上。
-
显示最终结果 :调用
cv_show
函数显示最终的拼接结果。python# 应用单应性矩阵进行透视变换 result=cv2.warpPerspective(imageB,H,(imageB.shape[1]+imageA.shape[1],imageB.shape[0])) cv_show('resultB',result) # 将左图拼接到结果图像上 result[0:imageA.shape[0],0:imageA.shape[1]]=imageA cv_show('result',result)
7. 可视化匹配的关键点
python
# 使用drawMatchesKnn函数绘制匹配的关键点
vis=cv2.drawMatchesKnn(imageB,kpsB,imageA,kpsA,good,None,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv_show('keypoint',vis)
运行结果
完整代码
python
# 图像拼接
import sys
import cv2
import numpy as np
# 显示图像的函数
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
# 检测关键点并计算描述符的函数
def detectAndDescribe(image):
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
desciiptor=cv2.SIFT_create()#创建SIFT描述
#检测关键点并计算描述符
(kps,des)=desciiptor.detectAndCompute(gray,None)#kps 是检测到的关键点的列表,des 是关键点的描述符矩阵。
kps_float=np.float32([kp.pt for kp in kps])#转换关键点坐标为浮点数:
return (kps,kps_float,des)
imageA=cv2.imread('left.jpg')
imageB=cv2.imread('right.jpg')
#检测关键点并计算描述符
(kpsA,kps_floatA,desA)=detectAndDescribe(imageA)
(kpsB,kps_floatB,desB)=detectAndDescribe(imageB)
#创建匹配器
matcher=cv2.BFMatcher()
#进行K近邻匹配
rawMatches=matcher.knnMatch(desB,desA,2)
good=[]
matches=[]
for m in rawMatches:
if len(m)==2 and m[0].distance<0.65*m[1].distance:
good.append(m)
matches.append((m[0].trainIdx,m[0].queryIdx))
# print(len(good))
# print(matches)
# 使用drawMatchesKnn函数绘制匹配的关键点
vis=cv2.drawMatchesKnn(imageB,kpsB,imageA,kpsA,good,None,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv_show('keypoint',vis)
#左侧连接
# 如果匹配点足够多,则进行下一步
if len(matches)>4:
ptsA=np.float32([kps_floatA[i] for (i,_) in matches])
ptsB=np.float32([kps_floatB[i] for (_,i) in matches])
# 使用RANSAC算法计算单应性矩阵
(H,mask)=cv2.findHomography(ptsB,ptsA,cv2.RANSAC,10)
else:
sys.exit()
# 应用单应性矩阵进行透视变换
result=cv2.warpPerspective(imageB,H,(imageB.shape[1]+imageA.shape[1],imageB.shape[0]))
cv_show('resultB',result)
# 将左图拼接到结果图像上
result[0:imageA.shape[0],0:imageA.shape[1]]=imageA
cv_show('result',result)