经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
OpenCV实战之图像拼接的示例代码
来源:jb51  时间:2022/1/17 16:40:57  对本文有异议

背景

图像拼接可以应用到手机中的全景拍摄,也就是将多张图片根据关联信息拼成一张图片;

实现步骤

1、读文件并缩放图片大小;

2、根据特征点和计算描述子,得到单应性矩阵;

3、根据单应性矩阵对图像进行变换,然后平移;

4、图像拼接并输出拼接后结果图;

一、读取文件

第一步实现读取两张图片并缩放到相同尺寸;

代码如下:

  1. img1 = cv2.imread('map1.png')
  2. img2 = cv2.imread('map2.png')
  3.  
  4. img1 = cv2.resize(img1, (640, 480))
  5. img2 = cv2.resize(img2, (640, 480))
  6.  
  7. input = np.hstack((img1, img2))
  8. cv2.imshow('input', input)
  9. cv2.waitKey(0)

上图为我们需要拼接的两张图的展示,可以看出其还具有一定的旋转变换,之后的图像转换必定包含旋转的操作;

二、单应性矩阵计算

主要分为以下几个步骤:

1、创建特征转换对象;

2、通过特征转换对象获得特征点和描述子;

3、创建特征匹配器;

4、进行特征匹配;

5、过滤特征,找出有效的特征匹配点;

6、单应性矩阵计算

实现代码:

  1. def get_homo(img1, img2):
  2. ? ? # 1实现
  3. ? ? sift = cv2.xfeatures2d.SIFT_create()
  4. ? ? # 2实现
  5. ? ? k1, p1 = sift.detectAndCompute(img1, None)
  6. ? ? k2, p2 = sift.detectAndCompute(img2, None)
  7. ? ? # 3实现
  8. ? ? bf = cv2.BFMatcher()
  9. ? ? # 4实现
  10. ? ? matches = bf.knnMatch(p1, p2, k=2)
  11. ? ? # 5实现
  12. ? ? good = []
  13. ? ? for m1, m2 in matches:
  14. ? ? ? ? if m1.distance < 0.8 * m2.distance:
  15. ? ? ? ? ? ? good.append(m1)
  16. ? ? # 6实现
  17. ? ? if len(good) > 8:
  18. ? ? ? ? img1_pts = []
  19. ? ? ? ? img2_pts = []
  20. ? ? ? ? for m in good:
  21. ? ? ? ? ? ? img1_pts.append(k1[m.queryIdx].pt)
  22. ? ? ? ? ? ? img2_pts.append(k2[m.trainIdx].pt)
  23. ? ? ? ? img1_pts = np.float32(img1_pts).reshape(-1, 1, 2)
  24. ? ? ? ? img2_pts = np.float32(img2_pts).reshape(-1, 1, 2)
  25. ? ? ? ? H, mask = cv2.findHomography(img1_pts, img2_pts, cv2.RANSAC, 5.0)
  26. ? ? ? ? return H
  27. ? ? else:
  28. ? ? ? ? print('piints is not enough 8!')
  29. ? ? ? ? exit()

三、图像拼接

实现步骤:

1、获得图像的四个角点;

2、根据单应性矩阵变换图片;

3、创建一张大图,拼接图像;

4、输出结果

实现代码:

  1. def stitch_img(img1, img2, H):
  2. ? ? # 1实现
  3. ? ? h1, w1 = img1.shape[:2]
  4. ? ? h2, w2 = img2.shape[:2]
  5. ? ? img1_point = np.float32([[0,0], [0,h1], [w1,h1], [w1,0]]).reshape(-1, 1, 2)
  6. ? ? img2_point = np.float32([[0,0], [0,h2], [w2,h2], [w2,0]]).reshape(-1, 1, 2)
  7. ? ? # 2实现
  8. ? ? img1_trans = cv2.perspectiveTransform(img1_point, H)
  9. ? ? # 将img1变换后的角点与img2原来的角点做拼接
  10. ? ? result_point = np.concatenate((img2_point, img1_trans), axis=0)
  11. ? ? # 获得拼接后图像x,y的最小值
  12. ? ? [x_min, y_min] = np.int32(result_point.min(axis=0).ravel()-0.5)
  13. ? ? # 获得拼接后图像x,y的最大值
  14. ? ? [x_max, y_max] = np.int32(result_point.max(axis=0).ravel()+0.5)
  15. ? ? # 平移距离
  16. ? ? trans_dist = [-x_min, -y_min]
  17. ? ? # 构建一个齐次平移矩阵
  18. ? ? trans_array = np.array([[1, 0, trans_dist[0]],
  19. ? ? ? ? ? ? ? ? ? ? ? ? ? ? [0, 1, trans_dist[1]],
  20. ? ? ? ? ? ? ? ? ? ? ? ? ? ? [0, 0, 1]])
  21. ? ? # 平移和单应性变换
  22. ? ? res_img = cv2.warpPerspective(img1, trans_array.dot(H), (x_max-x_min, y_max-y_min))
  23. ? ? # 3实现
  24. ? ? res_img[trans_dist[1]:trans_dist[1]+h2,
  25. ? ? ? ? ? ? trans_dist[0]:trans_dist[0]+w2] = img2
  26. ? ? return res_img
  27.  
  28. H = get_homo(img1, img2)
  29. res_img = stitch_img(img1, img2, H)
  30. # 4实现
  31. cv2.imshow('result', res_img)
  32. cv2.waitKey(0)?

最终结果图如上图所示,还有待优化点如下:

  • 边缘部分有色差,可以根据取平均值消除;
  • 黑色区域可进行裁剪并用对应颜色填充;

优化部分难度不大,有兴趣的可以实现一下;

总结

图像拼接作为一个实用性技术经常出现在我们的生活中,特别是全景拍摄以及图像内容拼接;当然,基于传统算法的图像拼接还是会有一些缺陷(速度和效果上),感兴趣的可以了解下基于深度学习的图像拼接算法,期待和大家沟通!

到此这篇关于OpenCV实战之图像拼接的示例代码的文章就介绍到这了,更多相关OpenCV图像拼接内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号