欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 资讯 > OpenCV--图像拼接

OpenCV--图像拼接

2024/12/22 0:05:56 来源:https://blog.csdn.net/GamBleout/article/details/144448176  浏览:    关键词:OpenCV--图像拼接

OpenCV--图像拼接

  • 代码和笔记

代码和笔记

import cv2
import numpy as np"""
图像拼接:
1. 读取图片,灰度化
2. 计算各自的特征点和描述子
3. 匹配特征
4. 计算单应性矩阵
5. 透视变换
6. 创建一个大图,放图两张图
"""img1 = cv2.imread('./img/ca2.jpeg')
img2 = cv2.imread('./img/cat.jpeg')# 把两张图的尺寸变为同样大小
img1 = cv2.resize(img1, (640, 480))
img2 = cv2.resize(img2, (640, 480))# 灰度化处理
gary1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gary2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)# 创建特征检测器
sift = cv2.SIFT_create()# 计算描述子
kp1, des1 = sift.detectAndCompute(gary1, None)
kp2, des2 = sift.detectAndCompute(gary2, None)# 创建特征匹配器 为了更准确,这里使用KNN算法匹配器进行相应的筛选,k是KNN的参数
bf = cv2.BFMatcher()
match = bf.knnMatch(des1, des2, k=2)# 筛选后的集合
goods = []
# 开始筛选
# match返回两个index
for m, n in match:# 这个阈值一般为0.7-0.8# distance为描述子之间的距离,越小越好if m.distance < 0.75 * n.distance:goods.append(m)# 计算单应性矩阵至少需要四个点
if len(goods) >= 4:# src_points:源平面中点的坐标矩阵。 dst_points:目标平面中点的坐标矩阵src_points = np.float32([kp1[m.queryIdx].pt for m in goods]).reshape(-1, 1, 2)dst_points = np.float32([kp2[m.trainIdx].pt for m in goods]).reshape(-1, 1, 2)# 根据匹配的点计算单应性矩阵H, _ = cv2.findHomography(src_points, dst_points, cv2.RANSAC, 5)
else:exit()# 获取原始图的高和宽
h1, w1 = img1.shape[:2]
h2, w2 = img2.shape[:2]
img1_pts = np.float32([[0, 0], [0, h1-1], [w1-1, h1-1], [w1-1, 0]]).reshape(-1, 1, 2)
img2_pts = np.float32([[0, 0], [0, h2-1], [w2-1, h2-1], [w2-1, 0]]).reshape(-1, 1, 2)# 计算img1的四个角变换之后的坐标
# 变换后img1_transform可能有负数,要平移回正,OpenCV中,x向左或者y向上为负
img1_transform = cv2.perspectiveTransform(img1_pts, H)# 要把两幅图放在一个大图上,先把坐标聚合,也就是数组上下放在一起,对齐
results_pts = np.concatenate((img2_pts, img1_transform))# 对齐后,找到每一列的最小值(应该为负数),平移这个最小值为正数,才能显示图像
# results_pts.min(axis=0)是二维的,用ravel直接取到一维的数据
# 因为原来有小数,可以-+1
[x_min, y_min] = np.int32(results_pts.min(axis=0).ravel() - 1)# 大图需要的大小为两张图最大的宽和高与最小的宽和高的绝对值的和,这里求出最大的值
[x_max, y_max] = np.int32(results_pts.max(axis=0).ravel() + 1)# 构造平移矩阵(格式固定),平移即仿射变换,原图点乘平移矩阵
move_matrix = np.array([[1, 0, -x_min], [0, 1, -y_min], [0, 0, 1]])# 将img1平移并透视变换到大图中,如果不平移,我们看不全图片
# 大图的大小:(x_max - x_min, y_max - y_min)
results_img = cv2.warpPerspective(img1, move_matrix.dot(H), (x_max - x_min, y_max - y_min))# 把第二张图放进来,直接用切片放进来 ndarray和OpenCV的wh是反的
results_img[-y_min: -y_min + h2, -x_min: -x_min + w2] = img2
# 如果中间有线,可以对img2进行透视变换,把图片拉正,大图片也可以拉正cv2.imshow('results_img', results_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com