赞
踩
昨天总结了基于特征的图像对齐,今天来尝试一下,基于特征对齐的二景图像拼接吧。如下图所示,这是同一地点不同角度拍摄的两幅图像,现在尝试将其进行拼接。
import numpy as np import cv2 as cv # 导入自己写的一个工具库 import opencv_utils MAX_FEATURES = 500 GOOD_MATCH_PERCENT = 0.15 def stitchImage(img1, img2): # Detect ORB features and compute descriptors. orb = cv.ORB_create(MAX_FEATURES) kp1, des1 = orb.detectAndCompute(img1, None) kp2, des2 = orb.detectAndCompute(img2, None) # Match features. matcher = cv.DescriptorMatcher_create(cv.DESCRIPTOR_MATCHER_BRUTEFORCE_HAMMING) matches = matcher.match(des1, des2, None) # Sort matches by score matches.sort(key=lambda x: x.distance, reverse=False) # Remove not so good matches numGoodMatches = int(len(matches) * GOOD_MATCH_PERCENT) matches = matches[:numGoodMatches] # Draw top matches imMatches = cv.drawMatches(img1, kp1, img2, kp2, matches, None) cv.imwrite("matches.png", imMatches) # Extract location of good matches points1 = np.zeros((len(matches), 2), dtype=np.float32) points2 = np.zeros((len(matches), 2), dtype=np.float32) for i, match in enumerate(matches): points1[i, :] = kp1[match.queryIdx].pt points2[i, :] = kp2[match.trainIdx].pt # 通过两个图像的特征点计算变换矩阵,获得变换矩阵和掩模 (M, mask) = cv.findHomography(points1, points2, cv.RANSAC) # 对 img1 透视变换,M 是变换矩阵, 变换后的大小是 (img1.w + img2.w, img1.h) result = cv.warpPerspective(img1, M, (img1.shape[1] + img2.shape[1], img1.shape[0])) # 将img2的值赋给结果图像 result[0:img2.shape[0], 0:img2.shape[1]] = img2 return result if __name__ == "__main__": img1 = cv.imread(r"F:\opencvTest\stitch_right.png") img2 = cv.imread(r"F:\opencvTest\stitch_left.png") # 顺时针旋转90度 img1_90 = opencv_utils.rotateClockWise90(img1) img2_90 = opencv_utils.rotateClockWise90(img2) # 进行拼接 stitched = stitchImage(img1_90, img2_90) # 结果图逆时针旋转90度 stitched = opencv_utils.rotateAntiClockWise90(stitched) cv.imwrite('stitched.png', stitched) # 原图与结果图一起展示,易于对比 result = opencv_utils.merge3Image(img1, img2, stitched) cv.imshow('result', result) cv.imwrite('result.png', result) cv.waitKey(0) cv.destroyAllWindows()
# opencv_utils.py import cv2 as cv import numpy as np # 合并两张图片为一张图片 def merge2Image(src1, src2): if not src1.shape == src2.shape: print("图片的尺寸不相等") return y = src1.shape[0] x = src1.shape[1] res = np.zeros((y, x * 2, 3), dtype=src1.dtype) res[:, :x, :] = src1 res[:, x:, :] = src2 return res # 合并三张图象为一张图像,第一张第二张上下合并,新图像再与第三张左右合并 def merge3Image(src1, src2, src3): if (not src1.shape == src2.shape) or (not src1.shape[0] + src2.shape[0] == src3.shape[0]): print("图片的尺寸不合适") return height = src1.shape[0] + src2.shape[0] width = src1.shape[1] + src3.shape[1] res = np.zeros((height, width, 3), dtype=src1.dtype) res[:src1.shape[0], :src1.shape[1], :] = src1 res[src1.shape[0]:, :src2.shape[1], :] = src2 res[:, src1.shape[1]:, :] = src3 return res # 顺时针旋转90度 def rotateClockWise90(img): trans_img = cv.transpose(img) new_img = cv.flip(trans_img, 1) return new_img # 逆时针旋转90度 def rotateAntiClockWise90(img): trans_img = cv.transpose(img) new_img = cv.flip(trans_img, 0) return new_img if __name__ == "__main__": src1 = cv.imread(r"F:\opencvTest\stitch_left.png") src2 = cv.imread(r"F:\opencvTest\stitch_right.png") res = merge2Image(src1, src2) cv.imshow("res", res) cv.imwrite("src_merge.png", res) cv.waitKey() cv.destroyAllWindows()
如果您觉得这篇文章对您有帮助,欢迎为我的 github项目 点一个⭐
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。