【持续更新篇】SLAM视觉特征点汇总+ORB特征点+VINS前端
Harris角点
opencv函数
cornerHarris提取输入图像的Harris角点
检测原理
检测思想:使用一个固定窗口在图像上进行任意方向的滑动,对比滑动前后的窗口中的像素灰度变化程度,如果存在任意方向上的滑动,都有较大灰度变化,则认为该窗口中存在角点。
E(u,v)=∑(x,y)∈Ww(x,y)[I(x+u,y+v)−I(x,y)]2E(u, v)=\sum_{(x, y) \in W} w(x, y)[I(x+u, y+v)-I(x, y)]^{2}E(u,v)=∑(x,y)∈Ww(x,y)[I(x+u,y+v)−I(x,y)]2
当窗口滑动时,滑动前后对应的窗口中的像素点灰度变化为E(u,v)E(u, v)E(u,v)
对E(u,v)E(u, v)E(u,v)进行泰勒展开,对公式进行化简,最终得到:
E(u,v)=[uv]M[uv]E(u, v)=\left[\begin{array}{ll}u & v\end{array}\right] M\left[\begin{array}{l}u \\ v\end{array}\right]E(u,v)=[uv]M[uv]
其中M为:
M=∑(x,y)∈Ww(x,y)[Ix2IxIyIxIyIy2]M = \sum_{(x, y) \in W} w(x, y)\left[\begin{array}{cc}I_{x}^{2} & I_{x} I y \\I_{x} I_{y} & I_{y}^{2}\end{array}\right]M=∑(x,y)∈Ww(x,y)[Ix2IxIyIxIyIy2]
IxI_xIx为图像在x方向的梯度,y方向同理。
如果M没有梯度变化较大的点,则当前没有角点或边缘点。如果M只在一个方向上有梯度变化很大的点,则当前可能只有边缘点。若M在xy方向上均变换很大,则当前框内有角点。
角点相应得分:
R=det(M)−k(trace(M))2R=\operatorname{det}(M)-k(\operatorname{trace}(M))^{2}R=det(M)−k(trace(M))2
其中
det(M)=λ1λ2\operatorname{det}(M)=\lambda_{1} \lambda_{2}det(M)=λ1λ2
trace(M)=λ1+λ2\operatorname{trace}(M)=\lambda_{1}+\lambda_{2}trace(M)=λ1+λ2
kkk在0.04到0.06之间。λ1λ2\lambda_{1} \lambda_{2}λ1λ2为MMM的两个特征值。
Harris角点性质
- 增大K值可以降低角点检测的灵敏度,减少被检测角点的数量
- Harris角点对亮度和对比度变化不灵敏
- Harris角点具有旋转不变性
- Harris角点不具有尺度不变性
FAST角点
opencv函数
fast = cv.FastFeatureDetector_create(threshold,nonmaxSuppression)
kp = fast.detect(Img, None)
cv.drawKeypoints (image,keypoints,outputimage,color,flags)
检测原理
取图像中的检测点,以该点为圆心的周围邻域内像素点判断检测点是否为角点。如果圆上有连续N个点的亮度大于或者小于阈值(如选取检测点的亮度的120%或80%),则认为该检测点为特征点。根据N的取值分为FAST-9,FAST-12等。
FAST加速方法
在FAST-12中可以检测圆上第1、5、9、13的像素的亮度,如果这四个像素中有三个同时大于或小于阈值,则该检测点才有可能是特征点,否则直接排除。
非极大值抑制
FAST角点会出现扎堆的现象,因此在第一遍检查过后还要使用非极大值抑制,在一定区域内仅保留响应极大值的角点,避免角点集中的问题。
FAST特征点性质
FAST特征点不具有方向信息和尺度信息。所以ORB在FAST基础上添加了图像金字塔解决尺度问题,添加灰度质心法解决特征的旋转问题。
SIFT特征点
src = cv.imread("123.png")
cv.namedWindow("input", cv.WINDOW_AUTOSIZE)
cv.imshow("input", src)
sift = cv.xfeatures2d.SIFT_create()
kps = sift.detect(src)
result = cv.drawKeypoints(src, kps, None, (0, 0, 255), cv.DrawMatchesFlags_DEFAULT)
cv.imshow("sift-detector", result)
SIFT原理
大致来说就是将图像进行多次下采样,构建出图像金字塔。
但是每层金字塔不止一张图像,而是类似于下面的一组图像。
原理是使用一个变化尺度的高斯函数与原图像进行卷积:
L(x,y,σ)=G(x,y,σ)∗I(x,y)L(x, y, \sigma)=G(x, y, \sigma) * I(x, y)L(x,y,σ)=G(x,y,σ)∗I(x,y)
其中高斯函数为:
G(x,y,σ)=12πσ2e−(x−m/2)2+(y−n/2)22σ2G(x, y, \sigma)=\frac{1}{2 \pi \sigma^{2}} e^{-\frac{(x-m / 2)^{2}+(y-n / 2)^{2}}{2 \sigma^{2}}}G(x,y,σ)=2πσ21e−2σ2(x−m/2)2+(y−n/2)2
然后
画叉的特征点需要和本层的8个点外加上下两层的9个点共26个点比较,若为最大值或最小值,则认为该点是初步判断的一个特征点。
关键点剔除工作
因为我们得到的特征点可能并不是真正的极值点,因此我们将得到离散空间点进行拟合,求出真正的极值点。
我们将检测得到的特征点反复的向计算出的极值点的方向进行偏移(实际是导数为0的方向),排除掉超出设定的迭代次数依然不能收敛的特征点和超出图像边界的特征点。同时也要排除数值小于某个经验值的特征点(如小于0.03或0.04),因为这种数值小的点容易收到噪声的干扰。
这步完成后,我们还需要去掉边缘点。我们初步检测出来的特征点有很多都是在边缘处,因为边缘点有较大的响应,但是这种响应也只发生在一个方向,因此采用了类似于Harris角点的检测方法,求出该检测点在两个方向的Hession矩阵,计算Hession矩阵的特征值,如果两个特征值的和的平方除以两特征值的积小于设定的阈值(如1.2),则认为该点并不是边缘点,保留。
主方向分配
简单点说就是求出特征点的所有邻域梯度的方向,然后统计一下,哪种方向最大则认为该特征点的梯度方向,再选一个大于主梯度80%的方向作为辅方向,增加鲁棒性。
描述子
在关键点的44的窗口中计算分别计算八个方向的梯度作为该特征点的描述子,维度为44*8=128维
检测匹配方法
Kd平衡二叉树,查找与目标图像的特征点最邻近的原图像特征点和次邻近的原图像特征点
SIFT特征点性质
- 检测非常稳定,应用广泛
- 计算量大,很难做到实时
SURF特征点
opencv函数
img = cv.imread('photo.png',0)
surf = cv.xfeatures2d.SURF_create(400)
kp, des = surf.detectAndCompute(img,None)
len(kp)
检测原理(类比SIFT)
Hessian矩阵近似
给定图像中一点,可以确定如下的Hessian矩阵:
H(x,y,σ)=(LxxLxyLxyLyy)H(x, y, \sigma)=\left(\begin{array}{ll} L_{x x} & L_{x y} \\ L_{x y} & L_{y y} \end{array}\right)H(x,y,σ)=(LxxLxyLxyLyy)
其中σ\sigmaσ为尺度大小
计算Hessian矩阵的行列式值DoH为:
detH=LxxLyy−Lxy2\operatorname{det} H=L_{x x} L_{y y}-L_{x y}^{2}detH=LxxLyy−Lxy2
因为此处是对Hessian矩阵进行处理,所以会自动过滤掉边缘点。
检测时选择不同大小的σ\sigmaσ生成不同的高斯卷积模版,同样生成图像金字塔,然后在不同位置空间和尺度空间搜索DoH的峰值(同样是26个点),并进行非极大值抑制,得到图像的极值点。
实际运用中对高斯滤波和行列式的计算进行了简化
与SIFT特征点不同的
- SURF并没有通过降采样的方式得到不同尺寸大小的图像建立金字塔,而是借助于不同的σ\sigmaσ构造金字塔。
- 特征点的主方向SIFT在方形邻域窗口内统计梯度方向直方图,而SURF在圆形区域内计算各个扇形范围内的方向,取响应累加和最大的扇形方向。
- 特征描述子,SIFT将关键点附近的邻域划分成4*4的区域,统计每个子区域的梯度方向直方图,统计成128维特征向量。SURF将20乘20像素点的邻域划分成4乘4个子块,计算每个子块的Haar小波响应,并统计4个特征量,得到4乘4乘4=64维度的特征向量。
BRIEF描述子
描述子原理
BRIEF是一种二进制的描述子,其描述向量是0和1表示的二进制串。0和1表示特征点邻域内两个像素(p和q)灰度值的大小:如果p比q大则选择1,反正就取0。在特征点的周围选择128对这样的p和q的像素对,就得到了128维由0,1组成的向量。
BRIEF使用随机选点的比较,速度很快,而且使用二进制串表示最终生成的描述子向量,在存储以及用于匹配的比较时都是非常方便的,其和FAST的搭配起来可以组成非常快速的特征点提取和描述算法。
ORB特征点提取opencv特征点与匹配
源代码来源
import cv2 as cvdef ORB_Feature(img1, img2):# 初始化ORBorb = cv.ORB_create()# 寻找关键点kp1 = orb.detect(img1)kp2 = orb.detect(img2)# 计算描述符kp1, des1 = orb.compute(img1, kp1)kp2, des2 = orb.compute(img2, kp2)# 画出关键点outimg1 = cv.drawKeypoints(img1, keypoints=kp1, outImage=None)outimg2 = cv.drawKeypoints(img2, keypoints=kp2, outImage=None)# 显示关键点# import numpy as np# outimg3 = np.hstack([outimg1, outimg2])# cv.imshow("Key Points", outimg3)# cv.waitKey(0)# 初始化 BFMatcherbf = cv.BFMatcher(cv.NORM_HAMMING)# 对描述子进行匹配matches = bf.match(des1, des2)# 计算最大距离和最小距离min_distance = matches[0].distancemax_distance = matches[0].distancefor x in matches:if x.distance < min_distance:min_distance = x.distanceif x.distance > max_distance:max_distance = x.distance# 筛选匹配点'''当描述子之间的距离大于两倍的最小距离时,认为匹配有误。但有时候最小距离会非常小,所以设置一个经验值30作为下限。'''good_match = []for x in matches:if x.distance <= max(2 * min_distance, 30):good_match.append(x)# 绘制匹配结果draw_match(img1, img2, kp1, kp2, good_match)def draw_match(img1, img2, kp1, kp2, match):outimage = cv.drawMatches(img1, kp1, img2, kp2, match, outImg=None)cv.imshow("Match Result", outimage)cv.waitKey(0)if __name__ == '__main__':# 读取图片image1 = cv.imread('1.png')image2 = cv.imread('2.png')ORB_Feature(image1, image2)
VINS前端光流法
vins-mono前端流程
光流追踪:基于灰度不变假设,以上一帧的特征点坐标为起点,在当前帧的同样的坐标下以一定范围找到与上一帧特征点附近区域灰度值相近的区域。
图像金字塔:vins中把上一层图像金字塔追踪的结果作为下一帧图像金字塔追踪的初值。保证了像素精度又保证了追踪结果在还原时的准确度。
相关文章:

【持续更新篇】SLAM视觉特征点汇总+ORB特征点+VINS前端
Harris角点 opencv函数 cornerHarris提取输入图像的Harris角点 检测原理 检测思想:使用一个固定窗口在图像上进行任意方向的滑动,对比滑动前后的窗口中的像素灰度变化程度,如果存在任意方向上的滑动,都有较大灰度变化…...

【C语言】初阶指针(指针及其类型以及野指针)
简单不先于复杂,而是在复杂之后。 目录 1. 指针是什么? 2. 指针和指针类型 2.1 指针-整数 2.2 指针的解引用 3. 野指针 3.1 野指针成因 3.2 如何规避野指针 1. 指针是什么? 指针理解的两个要点: 1. 指针是内存中最小…...

UDS统一诊断服务【六】访问时序参数0X83服务
文章目录前言一、访问时序参数服务介绍二、数据格式2.1 请求报文2.2 子功能2.3 响应三、举例前言 本文介绍UDS统一诊断服务的访问时序参数0X83服务,希望能对你有所帮助 一、访问时序参数服务介绍 这个服务我目前在项目中没怎么用到过,先来看看ISO14229…...

Linux应用编程(文件属性与目录)
本章将会讨论如下主题内容。 ⚫ Linux 系统的文件类型; ⚫ stat 系统调用; ⚫ 文件各种属性介绍:文件属主、访问权限、时间戳; ⚫ 符号链接与硬链接; ⚫ 目录; ⚫ 删除文件与文件重命名。 一、Linux 系统中…...

第十四届蓝桥杯嵌入式详解
目录 第一部分 客观试题(15 分) 不定项选择(1.5 分/题) 第二部分 程序设计试题(85 分) 2.1 STM32CubeMX初始化配置 2.1.1 配置GPIO 2.1.2 配置ADC 2.1.3 配置RCC 2.1.4 配置定时器TIM 2.1.5 配置ADC1、AD…...

新建论文三线表模板,一键格式刷
论文三线表模板写在最前面①表设计,新建表格样式②三线表上下线③三线表标题线④设置表格居中⑤设置表头格式容易出错的步骤写在最前面 论文写完啦,准备调整格式 之前建模也是三线表,但只能基于该文档模板,所以重新设置一下。 如…...

攻防世界-web2(逆向加密算法)
打开链接是PHP源码 给了一串密文,并对这串密文进行了一系列操作加密,注释里说解密$miwen就是flag 在此我们先介绍一些PHP内置函数: strrev(string): 反转字符串 strlen(string): 返回字符串的长度 substr(string, start, length): 返回字符…...

C语言学习1--------Visual Studio集成开发环境的搭建
C语言学习1--------Visual Studio集成开发环境的搭建适合初学者适用集成开发环境下载 Visual Studio 2019安装 Visual Studio 2019安装工作负载为C自定义安装位置激活 Visual Studio适合初学者适用集成开发环境 建议初学者适用最新的——Visual Studio 2019为集成开发环境。 部…...

腾讯云轻量应用服务器搭建网站教程(WordPress为例)
腾讯云轻量应用服务器搭建WordPress网站教程,先安装WordPress应用镜像,然后远程连接轻量应用服务器获取WP用户名和密码,域名DNS解析到轻量服务器IP地址,登陆WordPress后台管理全过程,腾讯云百科来详细说下腾讯云轻量服…...
mac上的PCB设计软件现状
Altium Designer是一款商业化的电路板设计软件,目前没有Mac版本。但是,MacOS上有一些类似Altium Designer的电路板设计软件,以下是一些常用的软件: Eagle:Eagle是一款商业化的电路板设计软件,具有强大的功能…...
【面试题】JavaScript 你常用的 函数有哪些呢? (12个)
大厂面试题分享 面试题库 前后端面试题库 (面试必备) 推荐:★★★★★ 地址:前端面试题库 web前端面试题库 VS java后端面试题库大全 本文收集了 12 个在日常开发中非常常用的函数,有些可能很复杂,有些可…...

Java集合——Set接口学习总结
一、HashSet实现类 1.常用方法 增加:add(E e)删除:remove(Object o)、clear()修改:查看:iterator()判断:contains(Object o)、isEmpty()常用遍历方式:Set<String> set new HashSet<String>()…...

2023最全的自动化测试入门基础知识(建议收藏)
1)首先,什么是自动化测试? 自动化测试是把以人为驱动的测试行为转化为机器执行的一种过程。通常,在设计了测试用例并通过评审之后,由测试人员根据测试用例中描述的过程一步步执行测试,得到实际结果与期望结果的比较。…...

【RabbitMQ】SpringBoot整合RabbitMQ、实现RabbitMQ五大工作模式(万字长文)
目录 一、准备 1、创建SpringBoot项目 2、添加配置信息 3、创建配置类 二、RabbitMQ的配置类里创建队列 三、RabbitMQ的配置类里创建交换机及绑定队列 四、SpringBoot整合RabbitMQ入门案例 1、生产者 2、消费者 四、SpringBoot里实现RabbitMQ五大工作模式 1、简单模式…...
ES6(函数扩展、数组扩展)
一、 函数扩展 1. 参数可以默认 ES5调用函数:如果给参数设置默认需要进行判断 ES6可以直接给参数设置默认 //ES5 function log(x, y) {//两种判断方法(传统分支判断、利用逻辑符)if (typeof y undefined) {y World;}//y y || World;cons…...

postman汉化教程
文章目录1. 下载对应版本的postman2.下载对应版本的汉化包2.1. github下载地址 : (9.12.2)2.2 百度网盘(9.12.2)3. 打开postman安装位置4. 压缩包解压到/resources目录下5. 重启postman即可汉化成中文了1. 下载对应版本的postman …...
java day8
第8章 数据结构8.1 超越数组8.2 java数据结构8.2.1 Iterator8.2.2 位组8.2.3 链表8.2.4 遍历数据结构8.2.5 堆栈8.1 超越数组 java类库的java.util包中有一组数据结构,它们让您能够更灵活地组织和操纵数据。 8.2 java数据结构 8.2.1 Iterator 接口Iterator提供了…...

口令暴力破解--Telnet协议暴力破解、数据库暴力破解与远程桌面暴力破解
Telnet协议暴力破解 Telnet Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式。它为用户提供了在本地计算机上完成远程主机工作的能力。要开始一个telnet会话,必须输入用户名和密码来登录服务器。而一般服务器不会对用户名…...

[译]什么是SourceMap
原文链接: https://web.dev/source-maps/使用 SourceMap 来提升 web 调试体验。今天,我们要讨论的是 SourceMap,这是现代 Web 开发中至关重要的工具,它能够显著地简化调试工作。在本文中,我们将探讨 SourceMap 的基础知识…...
saga模式、Seata saga模式详解
文章目录 一、前言二、SAGA模式0、saga论文摘要1、什么是长事务?2、saga的组成3、saga的两种执行场景1)forward recovery2)backward recovery4、saga log5、saga协调(saga实现方式)1)SAGA - Choreography 策略2)SAGA - Orchestration 策略3)如何选择三、Seata saga模式…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...