作者:Pisces2lemon | 来源:互联网 | 2024-11-03 12:48
图像拼接技术在全景摄影中具有广泛应用,如手机全景拍摄功能,通过将多张照片根据其关联信息合成为一张完整图像。本文详细探讨了使用Python和OpenCV库实现图像拼接的具体方法,并提供了示例代码解析,帮助读者深入理解该技术的实现过程。
目录
- 背景
- 实现步骤
- 一、读取文件
- 二、单应性矩阵计算
- 三、图像拼接
- 总结
背景
图像拼接可以应用到手机中的全景拍摄,也就是将多张图片根据关联信息拼成一张图片;
实现步骤
1、读文件并缩放图片大小;
2、根据特征点和计算描述子,得到单应性矩阵;
3、根据单应性矩阵对图像进行变换,然后平移;
4、图像拼接并输出拼接后结果图;
一、读取文件
第一步实现读取两张图片并缩放到相同尺寸;
代码如下:
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、单应性矩阵计算
实现代码:
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、输出结果
实现代码:
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实战之图像拼接的示例代码的文章就介绍到这了,更多相关OpenCV图像拼接内容请搜索编程笔记以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程笔记!