百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

干货分享!OpenCV基于无标记的增强现实详解,你绝对能看懂

bigegpt 2024-08-09 11:20 2 浏览

基于无标记的增强现实

基于无标记的增强现实,可以从图像中推导出相机姿态估计,以找到环境中已知点与其相机投影之间的对应关系。在本节中,我们将看到如何从图像中提取特征以获得相机姿态。基于这些特征及其匹配,我们将看到如何最终推导出相机姿态估计。

特征检测

一个特征可以被描述为图像中的一小块区域,它对图像的缩放、旋转和照明尽可能保持不变。因此,可以从同一场景不同视角的不同图像中检测到相同的特征。综上,一个好的特征应具备以下特性:

  1. 可重复(可以从同一物体的不同图像中提取相同的特征)
  2. 可区分(不同结构的图像具有不同的特征)

OpenCV 提供了许多算法来检测图像的特征,包括:哈里斯角检测 (Harris Corner Detection)、Shi-Tomasi 角检测 (Shi-Tomasi Corner Detection)、SIFT (Scale Invariant Feature Transform)、SURF (Speeded-Up Robust Features)、FAST (Features from Accelerated Segment Test)、BRIEF (Binary Robust Independent Elementary Features) 以及 ORB (Oriented FAST and Rotated BRIEF) 等。

接下里,以ORB算法为例,对图像进行特征检测和描述。ORB可以看作是FAST关键点检测器和BRIE描述符的组合,并进行了关键改进以提高性能。

首先是检测关键点,ORB 使用修改后的 FAST-9 算法 (radius = 9 ,并存储检测到的关键点的方向)检测关键点 (keypoints, 默认为 500个)。一旦检测到关键点,下一步就是计算描述符以获得与每个检测到的关键点相关联的信息。ORB 使用改进的 BRIEF-32 描述符来获取每个检测到的关键点的描述符。检测到的关键点的描述符结构如下:

首先是检测关键点,ORB 使用修改后的 FAST-9 算法 (radius = 9 ,并存储检测到的关键点的方向)检测关键点 (keypoints, 默认为 500个)。一旦检测到关键点,下一步就是计算描述符以获得与每个检测到的关键点相关联的信息。ORB 使用改进的 BRIEF-32 描述符来获取每个检测到的关键点的描述符。检测到的关键点的描述符结构如下:
[ 43 106  98  30 127 147 250  72  95  68 244 175  40 200 247 164 254 168 146 197 198 191  46 255  22  94 129 171  95  14 122 207]

根据上述讲解,第一步是创建ORB检测器:

orb = cv2.ORB_create()

然后是检测图像中的关键点:

# 加载图像
image = cv2.imread('example.png')
# 检测图像中的关键点
keypoints = orb.detect(image, None)

检测到关键点后,下一步就是计算检测到的关键点的描述符::

keypoints, descriptors = orb.compute(image, keypoints)

请注意,也可以执行通过 orb.detectAndCompute(image, None) 函数同时检测关键点并计算检测到的关键点的描述符。

最后,使用cv2.drawKeypoints()函数绘制检测到的关键点:

image_keypoints = cv2.drawKeypoints(image, keypoints, None, color=(255, 0, 255), flags=0)

运行结果如下所示,右侧图像显示了由ORB关键点检测器检测到的关键点(为了更好的进行观察,对图像进行了局部放大):

特征匹配

接下来,将介绍如何匹配检测到的特征。OpenCV提供了两种匹配器:

1、蛮力 (Brute-Force, BF) 匹配器:该匹配器利用为第一组中检测到的特征计算的描述符与第二组中的所有描述符进行匹配。最后,它返回距离最近的匹配项。
2、Fast Library for Approximate Nearest Neighbors (
FLANN) 匹配器:对于大型数据集,此匹配器比 BF 匹配器运行速度更快,它利用了最近邻搜索的优化算法。

接下来,我们使用BF匹配器来查看如何匹配检测到的特征,第一步是检测关键点并计算描述符:

# 加载图像
image_1 = cv2.imread('example_1.png')
image_2 = cv2.imread('example_2.png')
# ORB 检测器初始化
orb = cv2.ORB_create()
# 使用 ORB 检测关键点并计算描述符
keypoints_1, descriptors_1 = orb.detectAndCompute(image_1, None)
keypoints_2, descriptors_2 = orb.detectAndCompute(image_2, None)

下一步是使用cv2.BFMatcher()创建 BF 匹配器对象:

bf_matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

cv2.BFMatcher() 函数的第一个参数 normType 用于设置距离测量方法,默认为 cv2.NORM_L2,如果使用 ORB 描述符(或其他基于二进制的描述符,例如 BRIEFBRISK),则要使用的距离测量方法 cv2.NORM_HAMMING;第二个参数 crossCheck (默认为 False) 可以设置为 True,以便在匹配过程中只返回两个集合中相互匹配的特征。

创建匹配器对象后,使用
BFMatcher.match()方法匹配检测到的描述符:

bf_matches = bf_matcher.match(descriptors_1, descriptors_2)

Descriptors_1descriptors_2是计算得到的描述符;返回值为两个图像中获得了最佳匹配,我们可以按距离的升序对匹配项进行排序:

bf_matches = sorted(bf_matches, key=lambda x: x.distance)

最后,我们可以使用cv2.drawMatches()函数绘制匹配特征对,为了更好的可视化效果,仅显示前 20 个匹配项:

result = cv2.drawMatches(image_query, keypoints_1, image_scene, keypoints_2, bf_matches[:20], None, matchColor=(255, 255, 0), singlePointColor=(255, 0, 255), flags=0)

Cv2.drawMatches()函数水平拼接两个图像,并绘制从第一个图像到第二个图像的线条以显示匹配特征对,程序的运行结果如下所示:

利用特征匹配和单应性计算以查找对象

最后我们将利用上述特征匹配和单应性计算查找对象。为了达到此目的,在完成特征匹配后,下一步需要使用cv2.findHomography()函数在两幅图像中找到匹配关键点位置之间的透视变换。

OpenCV提供了多种计算单应矩阵的方法,包括RANSAC、最小中值 (LMEDS) 和PROSAC(RHO)。我们以使用RANSAC方法为例:

# 提取匹配的关键点
pts_src = np.float32([keypoints_1[m.queryIdx].pt for m in best_matches]).reshape(-1, 1, 2)
pts_dst = np.float32([keypoints_2[m.trainIdx].pt for m in best_matches]).reshape(-1, 1, 2)
# 计算单应性矩阵
M, mask = cv2.findHomography(pts_src, pts_dst, cv2.RANSAC, 5.0)

其中,pts_src 是匹配的关键点在源图像中的位置,pts_dst 是匹配的关键点在查询图像中的位置。 第四个参数 ransacReprojThreshold 设置最大重投影误差以将点对视为内点,如果重投影误差大于 5.0,则相应的点对被视为异常值。此函数计算并返回由关键点位置定义的源平面和目标平面之间的透视变换矩阵 M

最后,基于透视变换矩阵M,计算查询图像中对象的四个角,用于绘制匹配的目标边界框。为此,需要根据原始图像的形状计算其四个角,并使用cv2.perspectiveTransform()函数将它们转换为目标角:

# 获取“查询”图像的角坐标
h, w = image_query.shape[:2]
pts_corners_src = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]).reshape(-1, 1, 2)
# 使用矩阵 M 和“查询”图像的角点执行透视变换,以获取“场景”图像中“检测”对象的角点:
pts_corners_dst = cv2.perspectiveTransform(pts_corners_src, M)

其中,pts_corners_src包含原图的四个角坐标,M为透视变换矩阵;pts_corners_dst输出包含查询图像中对象的四个角,之后,我们可以使用cv2.polyline()函数来绘制检测对象的轮廓:

img_obj = cv2.polylines(image_scene, [np.int32(pts_corners_dst)], True, (0, 255, 255), 10)

最后,使用cv2.drawMatches()函数绘制匹配特征点:

img_matching = cv2.drawMatches(image_query, keypoints_1, img_obj, keypoints_2, best_matches, None, matchColor=(255, 255, 0), singlePointColor=(255, 0, 255), flags=0)

作者:盼小辉丶
链接:https://juejin.cn/post/7065138664367456287
来源:稀土掘金

相关推荐

10w qps缓存数据库——Redis(redis缓存调优)

一、Redis数据库介绍:Redis:非关系型缓存数据库nosql:非关系型数据库没有表,没有表与表之间的关系,更不存在外键存储数据的形式为key:values的形式c语言写的服务(监听端口),用来存...

Redis系列专题4--Redis配置参数详解

本文基于windowsX64,3.2.100版本讲解,不同版本默认配置参数不同在Redis中,Redis的根目录中有一个配置文件(redis.conf,windows下为redis.windows....

开源一夏 | 23 张图,4500 字从入门到精通解释 Redis

redis是目前出场率最高的NoSQL数据库,同时也是一个开源的数据结构存储系统,在缓存、数据库、消息处理等场景使用的非常多,本文瑞哥就带着大家用一篇文章入门这个强大的开源数据库——Redis。...

redis的简单与集群搭建(redis建立集群)

Redis是什么?是开源免费用c语言编写的单线程高性能的(key-value形式)内存数据库,基于内存运行并支持持久化的nosql数据库作用主要用来做缓存,单不仅仅是做缓存,比如:redis的计数器生...

推荐几个好用Redis图形化客户端工具

RedisPlushttps://gitee.com/MaxBill/RedisPlusRedisPlus是为Redis可视化管理开发的一款开源免费的桌面客户端软件,支持Windows、Linux...

关于Redis在windows上运行及fork函数问题

Redis在将数据库进行持久化操作时,需要fork一个进程,但是windows并不支持fork,导致在持久化操作期间,Redis必须阻塞所有的客户端直至持久化操作完成。微软的一些工程师花费时间在解决在...

你必须懂的Redis十大应用场景(redis常见应用场景)

Redis作为一款高性能的键值存储数据库,在互联网业务中有着广泛的应用。今天,我们就来详细盘点一下Redis的十大常用业务场景,并附上Golang的示例代码和简图,帮助大家更好地理解和应用Redis。...

极简Redis配置(redis的配置)

一、概述Redis的配置文件位于Redis安装目录下,文件名为redis.conf(Windows名为redis.windows.conf,linux下的是redis.conf)你可以通过C...

什么是redis,怎么启动及如何压测

从今天起咱们一起来学习一下关于“redis监控与调优”的内容。一、Redis介绍Redis是一种高级key-value数据库。它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富。...

一款全新Redis UI可视化管理工具,支持WebUI和桌面——P3X Redis UI

介绍P3XRedisUI这是一个非常实用的RedisGUI,提供响应式WebUI访问或作为桌面应用程序使用,桌面端是跨平台的,而且完美支持中文界面。Githubhttps://github....

windows系统的服务器快速部署java项目环境地址

1、mysql:https://dev.mysql.com/downloads/mysql/(msi安装包)2、redis:https://github.com/tporadowski/redis/r...

window11 下 redis 下载与安装(windows安装redis客户端)

#热爱编程是一种怎样的体验#window11下redis下载与安装1)各个版本redis下载(windows)https://github.com/MicrosoftArchive/r...

一款轻量级的Redis客户端工具,贼好用!

使用命令行来操作Redis是一件非常麻烦的事情,我们一般会选用客户端工具来操作Redis。今天给大家分享一款好用的Redis客户端工具TinyRDM,它的界面清新又优雅,希望对大家有所帮助!简介Ti...

一个.NET开发且功能强大的Windows远程控制系统

我们致力于探索、分享和推荐最新的实用技术栈、开源项目、框架和实用工具。每天都有新鲜的开源资讯等待你的发现!项目介绍SiMayRemoteMonitorOS是一个基于Windows的远程控制系统,完...

Redis客户端工具详解(4款主流工具)

大家好,我是mikechen。Redis是大型架构的基石,也是大厂最爱考察内容,今天就给大家重点详解4款Redis工具@mikechen本篇已收于mikechen原创超30万字《阿里架构师进阶专题合集...