opencv学习:图像拼接及完整代码实现

news2025/1/15 21:03:38

概念

        图像拼接是计算机视觉领域中的一项技术,它涉及将多个图像合并成一个连续的、无缝的全景图像。在OpenCV中,图像拼接通常包括以下几个关键步骤:

1. 编写代码
  • 导入必要的库:导入syscv2numpy库。
  • 定义显示图像的函数:编写cv_show函数,用于在窗口中显示图像。
    import sys
    import cv2
    import numpy as np
    # 显示图像的函数
    def cv_show(name,img):
        cv2.imshow(name,img)
        cv2.waitKey(0)
    
  • 定义检测关键点和计算描述符的函数:编写detectAndDescribe函数,使用SIFT算法检测图像中的关键点并计算描述符。
    # 检测关键点并计算描述符的函数
    def detectAndDescribe(image):
        gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
        desciiptor=cv2.SIFT_create()#创建SIFT描述
        #检测关键点并计算描述符
        (kps,des)=desciiptor.detectAndCompute(gray,None)#kps 是检测到的关键点的列表,des 是关键点的描述符矩阵。
        kps_float=np.float32([kp.pt for kp in kps])#转换关键点坐标为浮点数:
        return (kps,kps_float,des)
    
2. 读取图像
  • 使用cv2.imread函数读取left.jpgright.jpg图像。
    imageA=cv2.imread('left.jpg')
    imageB=cv2.imread('right.jpg')
3. 检测关键点和计算描述符
  • 对两幅图像分别调用detectAndDescribe函数,获取关键点和描述符。
    #检测关键点并计算描述符
    (kpsA,kps_floatA,desA)=detectAndDescribe(imageA)
    (kpsB,kps_floatB,desB)=detectAndDescribe(imageB)
4. 特征匹配
  • 创建匹配器:使用cv2.BFMatcher创建暴力匹配器。
  • 进行K近邻匹配:对两幅图像的描述符进行K近邻匹配,获取匹配点对。
  • 筛选好的匹配点:使用Lowe's ratio test筛选出好的匹配点。
    #创建匹配器
    matcher=cv2.BFMatcher()
    #进行K近邻匹配
    rawMatches=matcher.knnMatch(desB,desA,2)
    good=[]
    matches=[]
    for m in rawMatches:
    
        if len(m)==2 and m[0].distance<0.65*m[1].distance:
            good.append(m)
            matches.append((m[0].trainIdx,m[0].queryIdx))
5. 计算单应性矩阵
  • 检查匹配点数量:如果匹配点数量大于4,则继续;否则,程序退出。
  • 计算单应性矩阵:使用cv2.findHomography函数和RANSAC算法计算匹配点之间的单应性矩
    #左侧连接
    # 如果匹配点足够多,则进行下一步
    if len(matches)>4:
        ptsA=np.float32([kps_floatA[i] for (i,_) in matches])
        ptsB=np.float32([kps_floatB[i] for (_,i) in matches])
        # 使用RANSAC算法计算单应性矩阵
        (H,mask)=cv2.findHomography(ptsB,ptsA,cv2.RANSAC,10)
    else:
        sys.exit()
    阵。
6. 图像变换和拼接
  • 应用单应性矩阵:使用cv2.warpPerspective函数对右图进行透视变换。
  • 显示变换后的图像:调用cv_show函数显示变换后的图像。
  • 拼接图像:将左图拼接到变换后的右图上。
  • 显示最终结果:调用cv_show函数显示最终的拼接结果。
    # 应用单应性矩阵进行透视变换
    result=cv2.warpPerspective(imageB,H,(imageB.shape[1]+imageA.shape[1],imageB.shape[0]))
    cv_show('resultB',result)
    # 将左图拼接到结果图像上
    result[0:imageA.shape[0],0:imageA.shape[1]]=imageA
    cv_show('result',result)
7. 可视化匹配的关键点
# 使用drawMatchesKnn函数绘制匹配的关键点
vis=cv2.drawMatchesKnn(imageB,kpsB,imageA,kpsA,good,None,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv_show('keypoint',vis)

运行结果

完整代码

# 图像拼接
import sys
import cv2
import numpy as np
# 显示图像的函数
def cv_show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey(0)

# 检测关键点并计算描述符的函数
def detectAndDescribe(image):
    gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    desciiptor=cv2.SIFT_create()#创建SIFT描述
    #检测关键点并计算描述符
    (kps,des)=desciiptor.detectAndCompute(gray,None)#kps 是检测到的关键点的列表,des 是关键点的描述符矩阵。
    kps_float=np.float32([kp.pt for kp in kps])#转换关键点坐标为浮点数:
    return (kps,kps_float,des)

imageA=cv2.imread('left.jpg')
imageB=cv2.imread('right.jpg')
#检测关键点并计算描述符
(kpsA,kps_floatA,desA)=detectAndDescribe(imageA)
(kpsB,kps_floatB,desB)=detectAndDescribe(imageB)
#创建匹配器
matcher=cv2.BFMatcher()
#进行K近邻匹配
rawMatches=matcher.knnMatch(desB,desA,2)
good=[]
matches=[]
for m in rawMatches:

    if len(m)==2 and m[0].distance<0.65*m[1].distance:
        good.append(m)
        matches.append((m[0].trainIdx,m[0].queryIdx))
# print(len(good))
# print(matches)
# 使用drawMatchesKnn函数绘制匹配的关键点
vis=cv2.drawMatchesKnn(imageB,kpsB,imageA,kpsA,good,None,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv_show('keypoint',vis)
#左侧连接
# 如果匹配点足够多,则进行下一步
if len(matches)>4:
    ptsA=np.float32([kps_floatA[i] for (i,_) in matches])
    ptsB=np.float32([kps_floatB[i] for (_,i) in matches])
    # 使用RANSAC算法计算单应性矩阵
    (H,mask)=cv2.findHomography(ptsB,ptsA,cv2.RANSAC,10)
else:
    sys.exit()
# 应用单应性矩阵进行透视变换
result=cv2.warpPerspective(imageB,H,(imageB.shape[1]+imageA.shape[1],imageB.shape[0]))
cv_show('resultB',result)
# 将左图拼接到结果图像上
result[0:imageA.shape[0],0:imageA.shape[1]]=imageA
cv_show('result',result)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2199138.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大文件-分片上传 vue3+java

0.需求背景 遇到大文件上传时&#xff0c;会存在文件过大&#xff0c;后端无法一次性接受上传过程中&#xff0c;异常失败后&#xff0c;需要重新上传&#xff0c;耗时单次请求时间过长&#xff0c;请求受限 分片上传&#xff0c;相比于普通的单线程上传&#xff0c;速度更快&…

利士策分享,婚姻为何被称为大事?

利士策分享&#xff0c;婚姻为何被称为大事&#xff1f; 在历史的长河中&#xff0c;婚姻一直被视为人生中的头等大事&#xff0c;这一观念跨越时空&#xff0c;深深植根于各种文化和社会结构中。 古人为何将婚姻称为“大事”&#xff0c;这背后蕴含着丰富的社会、文化和心理寓…

JUC高并发编程6:Callable接口

1 创建线程的方式 在 Java 中&#xff0c;创建线程的方式主要有以下几种&#xff1a; 继承 Thread 类&#xff1a; 通过继承 Thread 类并重写 run() 方法来创建线程。示例代码&#xff1a;class MyThread extends Thread {Overridepublic void run() {// 线程执行的代码} }pub…

LeetCode题练习与总结:生命游戏--289

一、题目描述 根据 百度百科 &#xff0c; 生命游戏 &#xff0c;简称为 生命 &#xff0c;是英国数学家约翰何顿康威在 1970 年发明的细胞自动机。 给定一个包含 m n 个格子的面板&#xff0c;每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态&#xff1a; 1 即…

如何运行服务器上的web页面,打开Outlook 365的全球离线通讯簿功能?

&#x1f3c6;本文收录于《全栈Bug调优(实战版)》专栏&#xff0c;主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&am…

Linux入门攻坚——35、Linux防火墙-iptables-1

Firewall&#xff1a;防火墙&#xff0c;就是一个隔离工具。工作于主机或网络的边缘&#xff0c;对于进出本主机或网络的报文根据事先定义好的检查规则做匹配检测&#xff0c;对于能够被规则所匹配到的报文做出相应处理的组件&#xff1a;这个组件可以是硬件&#xff0c;也可以…

WPS的JS宏实现删除某级标题下的所有内容

想要删除Word文档中&#xff0c;包含特定描述的标题下所有内容&#xff08;包含各级子标题以及正文描述&#xff09;。 例如下图中&#xff0c;想删除1.2.1.19.1业务场景下所有内容&#xff1a; 简单版&#xff1a; 删除光标停留位置的大纲级别下所有的内容。实现的JS代码如下…

机器学习笔记-2

文章目录 一、Linear model二、How to represent this function三、Function with unknown parameter四、ReLU总结、A fancy name 一、Linear model 线性模型过于简单&#xff0c;有很大限制&#xff0c;我们需要更多复杂模式 蓝色是线性模型&#xff0c;线性模型无法去表示…

ubuntu 开放 8080 端口快捷命令

文章目录 查看防火墙状态开放 80 端口开放 8080 端口开放 22端口开启防火墙重启防火墙**使用 xhell登录**&#xff1a; 查看防火墙状态 sudo ufw status [sudo] password for crf: Status: inactivesudo ufw enable Firewall is active and enabled on system startup sudo…

Flutter 3.24 发布:GPU模块及多视图嵌入功能

Flutter 3.24 发布&#xff1a;GPU模块及多视图嵌入功能 Flutter 3.24 带来了许多新功能和改进&#xff0c;让开发应用程序变得更加容易和有趣。这个版本重点展示了 Flutter GPU 的预览功能&#xff0c;让应用程序可以直接使用高级图形和 3D 场景功能。 此外&#xff0c;网页…

传智杯 第六届—B

题目&#xff1a; 擂台赛要开始了&#xff0c;现在有 n 名战士&#xff0c;其中第 i 名战士的战斗力为 ai​。现在准备从这些战士中挑两名战士进入擂台赛进行对战&#xff0c;由于观众们更喜欢看势均力敌的比赛&#xff0c;所以我们也要挑选两个战斗力尽可能相近的战士进行参赛…

Linux-分析 IO 瓶颈手册

分析IO瓶颈 此文主要内容&#xff1a;I/O性能重要指标、主要排查工具、主要排查手段、工具图示 磁盘 I/O 性能指标 四个核心的磁盘 I/O 指标 使用率&#xff1a;是指磁盘忙处理 I/O 请求的百分比。过高的使用率&#xff08;比如超过 60%&#xff09;通常意味着磁盘 I/O 存在…

Spring系列 Bean的生命周期

文章目录 初始化时机单例初始化流程getBeandoGetBeangetSingleton(String) 获取单例getSingleton(String, ObjectFactory) 创建单例beforeSingletonCreationcreateBeanafterSingletonCreation createBean 创建对象doCreateBeanaddSingletonFactory createBeanInstance 创建 Bea…

基于springboot vue 学生就业信息管理系统设计与实现

博主介绍&#xff1a;专注于Java&#xff08;springboot ssm springcloud等开发框架&#xff09; vue .net php phython node.js uniapp小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作☆☆☆ 精彩专栏推荐订阅☆☆☆☆…

水库大坝安全监测预警系统守护大坝安全卫士

一、系统背景 近年来&#xff0c;受全球气候变化和人类活动影响&#xff0c;极端天气发生频度强度增加&#xff0c;加之我国城市化进程中&#xff0c;水库下游人口聚集、基础设施密集&#xff0c;对水库工程安全运行提出了新的更高要求。“十四五”以来我国建成并投入使用37593…

NeRS: Neural Reflectance Surfaces for Sparse-view 3D Reconstruction in the Wild

1. 2.优点1&#xff1a;我们的方法仅依赖于近似的相机位姿估计和粗略的类别级形状模板。 3.我们的关键见解是&#xff0c;我们可以强制执行基于表面的 3D 表示&#xff0c;而不是允许广泛用于体积表示的无约束密度。重要的是&#xff0c;这允许依赖于视图的外观变化 4.更重要…

迪士尼数据泄露事件:全面审视数据安全策略与未来防护方向

迪士尼数据泄露事件概述 一、 事件背景以及影响 在全球数字化转型加速的浪潮中&#xff0c;数据安全已成为企业运营不可忽视的基石。 华特迪士尼公司&#xff0c;作为全球知名的娱乐传媒巨头&#xff0c;其数据泄露事件无疑为业界敲响了警钟。此次事件不仅揭示了数据保护的严…

从0开始下载安装并使用unity

首先我们要在浏览器上找到unity的官网 这一个就是了&#xff0c;我们点进去后是这个界面&#xff1a; 然后我们点击上面这张图的左下角的“下载Unity Hub”&#xff0c;推荐后续安装都装在D盘&#xff1a; 这里他会让我们注册一个账号&#xff0c;如果之前有的话登录就行了&am…

2024年第二届龙信杯 WP

2024年龙信杯 author&#xff1a;mumuzi date&#xff1a;2024/9/30 取证的一手更新都在自己的博客上&#xff0c;分区为Forensic&#xff0c;https://mumuzi7179.github.io/或https://mumuzi.blog/ DK盾云服务器&#xff1a;DK盾 镜像下载地址&#xff1a; https://pan.ba…

i18n多语言项目批量翻译工具(支持84种语言)

这里写自定义目录标题 打开‘i18n翻译助手’小程序快捷访问 打开‘i18n翻译助手’小程序 1.将需要翻译的json文件复制到输入框&#xff08;建议一次不要翻译过多&#xff0c;测试1000条以内没什么问题&#xff09; 2.等待翻译 3.翻译完成&#xff0c;复制结果 快捷访问