OpenCV--图像拼接

ops/2024/12/19 12:23:35/

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()

http://www.ppmy.cn/ops/143176.html

相关文章

基于yolov10的遥感影像目标检测系统,支持图像检测,视频检测和实时摄像检测功能(pytorch框架,python源码)

更多目标检测、图像分类识别、目标检测等其他项目可看我主页其他文章 功能演示&#xff1a; 基于yolov10的遥感影像目标检测系统&#xff0c;既支持图像检测&#xff0c;也支持视频和摄像实时检测【pytorch框架、python源码】_哔哩哔哩_bilibili &#xff08;一&#xff09;…

AtomGit 开源生态应用开发赛报名开始啦

目录 1、赛项背景2、赛项信息3、报名链接4、赛题一&#xff1a;开发者原创声明&#xff08;DCO&#xff09;应用开发赛题要求目标核心功能 5、赛题二&#xff1a;基于 OpenHarmony 的开源社区应用开发简介赛题要求 6、参赛作品提交初赛阶段决赛阶段 7、参赛作品提交方式 1、赛项…

Linux——Shell

if 语句 格式&#xff1a;if list; then list; [ elif list; then list; ] ... [ else list; ] fi 单分支 if 条件表达式; then 命令 fi 示例&#xff1a; #!/bin/bash N10 if [ $N -gt 5 ]; then echo yes fi # bash test.sh yes 双分支 if 条件表达式; then 命令 else 命令…

Linux安装部署Redis(超级详细)

前言 网上搜索了一筐如何在Linux下安装部署Redis的文章&#xff0c;各种文章混搭在一起勉强安装成功了。自己也记录下&#xff0c;方便后续安装时候有个借鉴之处。 Redis版本 5.0.4服务器版本 Linux CentOS 7.6 64位 下载Redis 进入官网找到下载地址 https://redis.io/down…

爬虫抓取的数据如何有效存储和管理?

在现代数据驱动的世界中&#xff0c;爬虫技术已成为获取网络数据的重要手段。然而&#xff0c;如何有效地存储和管理这些数据是一个关键问题。本文将详细介绍几种有效的数据存储和管理方法&#xff0c;并提供相应的Java代码示例。 1. 数据存储方式 1.1 文件存储 文件存储是最…

access数据库代做/mysql代做/Sql server数据库代做辅导设计服务

针对Access数据库、MySQL以及SQL Server数据库的代做和辅导设计服务&#xff0c;以下是一些关键信息和建议&#xff1a; 一、服务概述 这些服务通常包括数据库的设计、创建、优化、维护以及相关的编程和查询编写等。无论是Access这样的桌面关系数据库管理系统&#xff08;RDB…

【漏洞分析】DDOS攻防分析(四)——TCP篇

0x00 TCP DDOS攻击案例 政治因素一直是黑客发动网络攻击的一个重要动机。2015年12月&#xff0c;著名黑客组织匿名者(Anonymous)发布视频谴责土耳其支持ISIS&#xff0c;并向土耳其发动了史上最大规模的DDoS攻击。 2015年12月14日开始&#xff0c;大规模网络攻击导致土耳其银…

vue-element-admin npm install 安装失败,tui-editor更名导致

导语&#xff1a; 本失败原因是由于tui-editor&#xff08;富文本编辑器插件&#xff09;更名造成的&#xff0c;现在已经更名为toast-ui/editor&#xff1b; 在一个是一直以为是我的git问题 报错代码&#xff1a;code 128 ..........&#xff0c;困扰了我好长时间&#xff…