基本介绍
图像的全景拼接,即“缝合”两张具有重叠区域的图来创建一张全景图。其中用到了计算机视觉和图像处理技术有:关键点特征检测、局部不变特征、关键特征点匹配、RANSAC(Random Sample Consensus,随机采样一致性)和透视变形。
具体步骤
(1)检测左右两张图像的SIFT关键特征点,并提取局部不变特征 ; (2)使用knnMatch检测来自右图(左图)的SIFT特征,与左图(右图)进行匹配 ; (3)计算视角变换矩阵H,用变换矩阵H对右图进行扭曲变换; (4)将左图(右图)加入到变换后的图像的左侧(右侧)获得最终图像;
import cv2 as cv
import numpy as np
def sift_keypoints_detect(image):
gray_image = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
sift = cv.xfeatures2d.SIFT_create()
keypoints, features = sift.detectAndCompute(image, None)
keypoints_image = cv.drawKeypoints(
gray_image, keypoints, None, flags=cv.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS)
return keypoints_image, keypoints, features
def get_feature_point_ensemble(features_right, features_left):
bf = cv.BFMatcher()
matches = bf.knnMatch(features_right, features_left, k=2)
matches = sorted(matches, key=lambda x: x[0].distance / x[1].distance)
good = []
for m, n in matches:
ratio = 0.6
if m.distance < ratio * n.distance:
good.append(m)
return good
def Panorama_stitching(image_right, image_left):
_, keypoints_right, features_right = sift_keypoints_detect(image_right)
_, keypoints_left, features_left = sift_keypoints_detect(image_left)
goodMatch = get_feature_point_ensemble(features_right, features_left)
if len(goodMatch) > 4:
Point_coordinates_right = np.float32(
[keypoints_right[m.queryIdx].pt for m in goodMatch]).reshape(-1, 1, 2)
Point_coordinates_left = np.float32(
[keypoints_left[m.trainIdx].pt for m in goodMatch]).reshape(-1, 1, 2)
ransacReprojThreshold = 4
Homography, status = cv.findHomography(
Point_coordinates_right, Point_coordinates_left, cv.RANSAC, ransacReprojThreshold)
Panorama = cv.warpPerspective(
image_right, Homography, (image_right.shape[1] + image_left.shape[1], image_right.shape[0]))
cv.imshow("扭曲变换后的右图", Panorama)
cv.waitKey(0)
cv.destroyAllWindows()
Panorama[0:image_left.shape[0], 0:image_left.shape[1]] = image_left
return Panorama
if __name__ == '__main__':
image_left = cv.imread("./Left.jpg")
image_right = cv.imread("./Right.jpg")
image_right = cv.resize(image_right, None, fx=0.4, fy=0.24)
image_left = cv.resize(image_left, (image_right.shape[1], image_right.shape[0]))
keypoints_image_right, keypoints_right, features_right = sift_keypoints_detect(image_right)
keypoints_image_left, keypoints_left, features_left = sift_keypoints_detect(image_left)
cv.imshow("左图关键特征点检测", np.hstack((image_left, keypoints_image_left)))
cv.waitKey(0)
cv.destroyAllWindows()
cv.imshow("右图关键特征点检测", np.hstack((image_right, keypoints_image_right)))
cv.waitKey(0)
cv.destroyAllWindows()
goodMatch = get_feature_point_ensemble(features_right, features_left)
all_goodmatch_image = cv.drawMatches(
image_right, keypoints_right, image_left, keypoints_left, goodMatch, None, None, None, None, flags=2)
cv.imshow("所有匹配的SIFT关键特征点连线", all_goodmatch_image)
cv.waitKey(0)
cv.destroyAllWindows()
Panorama = Panorama_stitching(image_right, image_left)
cv.namedWindow("全景图", cv.WINDOW_AUTOSIZE)
cv.imshow("全景图", Panorama)
cv.imwrite("./全景图.jpg", Panorama)
cv.waitKey(0)
cv.destroyAllWindows()
左图关键特征点检测
右图关键特征点检测
所有匹配的SIFT关键特征点连线
扭曲变换后的右图
全景图
由于输入的左右图像之间有大量重叠,导致全景图的主要添加部分是在拼接图像的右侧,因此会造成拼接后全景图右侧有大量的黑色空白区域。
|