OpenCV实战之图像拼接的示例代码
图像拼接可以应用到手机中的全景拍摄,也就是将多张图片根据关联信息拼成一张图片。本文将介绍利用Python OpenCV实现图像拼接的方法,感兴趣的可以试一试
目录
背景
实现步骤
一、读取文件
二、单应性矩阵计算
三、图像拼接
总结
背景
图像拼接可以应用到手机中的全景拍摄,也就是将多张图片根据关联信息拼成一张图片;
实现步骤
1、读文件并缩放图片大小;
2、根据特征点和计算描述子,得到单应性矩阵;
3、根据单应性矩阵对图像进行变换,然后平移;
4、图像拼接并输出拼接后结果图;
一、读取文件
第一步实现读取两张图片并缩放到相同尺寸;
代码如下:
1 2 3 4 5 6 7 8 9 | img1 = cv2.imread( 'map1.png' ) img2 = cv2.imread( 'map2.png' ) img1 = cv2.resize(img1, ( 640 , 480 )) img2 = cv2.resize(img2, ( 640 , 480 )) input = np.hstack((img1, img2)) cv2.imshow( 'input' , input ) cv2.waitKey( 0 ) |
上图为我们需要拼接的两张图的展示,可以看出其还具有一定的旋转变换,之后的图像转换必定包含旋转的操作;
二、单应性矩阵计算
主要分为以下几个步骤:
1、创建特征转换对象;
2、通过特征转换对象获得特征点和描述子;
3、创建特征匹配器;
4、进行特征匹配;
5、过滤特征,找出有效的特征匹配点;
6、单应性矩阵计算
实现代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | def get_homo(img1, img2): # 1实现 sift = cv2.xfeatures2d.SIFT_create() # 2实现 k1, p1 = sift.detectAndCompute(img1, None ) k2, p2 = sift.detectAndCompute(img2, None ) # 3实现 bf = cv2.BFMatcher() # 4实现 matches = bf.knnMatch(p1, p2, k = 2 ) # 5实现 good = [] for m1, m2 in matches: if m1.distance < 0.8 * m2.distance: good.append(m1) # 6实现 if len (good) > 8 : img1_pts = [] img2_pts = [] for m in good: img1_pts.append(k1[m.queryIdx].pt) img2_pts.append(k2[m.trainIdx].pt) img1_pts = np.float32(img1_pts).reshape( - 1 , 1 , 2 ) img2_pts = np.float32(img2_pts).reshape( - 1 , 1 , 2 ) H, mask = cv2.findHomography(img1_pts, img2_pts, cv2.RANSAC, 5.0 ) return H else : print ( 'piints is not enough 8!' ) exit() |
三、图像拼接
实现步骤:
1、获得图像的四个角点;
2、根据单应性矩阵变换图片;
3、创建一张大图,拼接图像;
4、输出结果
实现代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | def stitch_img(img1, img2, H): # 1实现 h1, w1 = img1.shape[: 2 ] h2, w2 = img2.shape[: 2 ] img1_point = np.float32([[ 0 , 0 ], [ 0 ,h1], [w1,h1], [w1, 0 ]]).reshape( - 1 , 1 , 2 ) img2_point = np.float32([[ 0 , 0 ], [ 0 ,h2], [w2,h2], [w2, 0 ]]).reshape( - 1 , 1 , 2 ) # 2实现 img1_trans = cv2.perspectiveTransform(img1_point, H) # 将img1变换后的角点与img2原来的角点做拼接 result_point = np.concatenate((img2_point, img1_trans), axis = 0 ) # 获得拼接后图像x,y的最小值 [x_min, y_min] = np.int32(result_point. min (axis = 0 ).ravel() - 0.5 ) # 获得拼接后图像x,y的最大值 [x_max, y_max] = np.int32(result_point. max (axis = 0 ).ravel() + 0.5 ) # 平移距离 trans_dist = [ - x_min, - y_min] # 构建一个齐次平移矩阵 trans_array = np.array([[ 1 , 0 , trans_dist[ 0 ]], [ 0 , 1 , trans_dist[ 1 ]], [ 0 , 0 , 1 ]]) # 平移和单应性变换 res_img = cv2.warpPerspective(img1, trans_array.dot(H), (x_max - x_min, y_max - y_min)) # 3实现 res_img[trans_dist[ 1 ]:trans_dist[ 1 ] + h2, trans_dist[ 0 ]:trans_dist[ 0 ] + w2] = img2 return res_img H = get_homo(img1, img2) res_img = stitch_img(img1, img2, H) # 4实现 cv2.imshow( 'result' , res_img) cv2.waitKey( 0 ) |
最终结果图如上图所示,还有待优化点如下:
边缘部分有色差,可以根据取平均值消除;
黑色区域可进行裁剪并用对应颜色填充;
优化部分难度不大,有兴趣的可以实现一下;
总结
图像拼接作为一个实用性技术经常出现在我们的生活中,特别是全景拍摄以及图像内容拼接;当然,基于传统算法的图像拼接还是会有一些缺陷(速度和效果上),感兴趣的可以了解下基于深度学习的图像拼接算法,期待和大家沟通!
到此这篇关于OpenCV实战之图像拼接的示例代码的文章就介绍到这了
原文链接:https://blog.csdn.net/weixin_40620310/article/details/122517310