slam14讲(第8讲、前端里程计)LK光流、直接法

直接法的引出

因为第7讲大部分都是讲特征点法,通过提取orb特征点和点的描述子,来构建两帧图像之间的特征点对应关系。这种方法会有缺点:

  1. 关键点和描述子提取计算耗时,如果相机的频率高,则slam算法大部分耗时被占。
  2. 特征点是稀疏的,往往只有几百个,而且在我看来容易被一些动态物体干扰,就会对后续匹配造成影响。
  3. 在一些特征不明显的地方,大白墙或者没有明显角点的地方,特征点难提取,对后续计算相机运动造成影响。

光流法

光流可以分成稀疏光流和稠密光流。Lucas-Kanade光流跟踪部分像素点的运动成为稀疏光流,Horn-Schunck光流跟踪所有像素点的运动成为稠密光流。而书中主要是介绍了LK稀疏光流法。

个人见解

光流法的作用就是用来跟踪上一帧图片的像素点在当前帧图片中的位置,本质上也是特征匹配的一种方法,只是特征点法的特征匹配是通过点的描述子来进行匹配,而LK光流从图像入手,在灰度不变假设上,根据两帧图像求出跟踪像素点的运动速度,从而在第二帧图片中找到跟踪点的像素。后续就是简单列一下书里的公式。

公式推导

将图片看成是关于时间(t)和像素(u,v)的函数,即三元函数。根据灰度不变假设,对于t时刻在第一帧图片(x,y)的像素,根据灰度不变:
I ( x + d x , y + d y , t + d t ) = I ( x , y , t ) \boldsymbol{I}(x+\mathrm{d} x, y+\mathrm{d} y, t+\mathrm{d} t)=\boldsymbol{I}(x, y, t) I(x+dx,y+dy,t+dt)=I(x,y,t)
然后就是经典的一阶泰勒展开:
I ( x + d x , y + d y , t + d t ) ≈ I ( x , y , t ) + ∂ I ∂ x d x + ∂ I ∂ y d y + ∂ I ∂ t d t \boldsymbol{I}(x+\mathrm{d} x, y+\mathrm{d} y, t+\mathrm{d} t) \approx \boldsymbol{I}(x, y, t)+\frac{\partial \boldsymbol{I}}{\partial x} \mathrm{~d} x+\frac{\partial \boldsymbol{I}}{\partial y} \mathrm{~d} y+\frac{\partial \boldsymbol{I}}{\partial t} \mathrm{~d} t I(x+dx,y+dy,t+dt)I(x,y,t)+xI dx+yI dy+tI dt
因为灰度不变,所以只剩三项:
∂ I ∂ x d x + ∂ I ∂ y d y + ∂ I ∂ t d t = 0 \frac{\partial \boldsymbol{I}}{\partial x} \mathrm{~d} x+\frac{\partial \boldsymbol{I}}{\partial y} \mathrm{~d} y+\frac{\partial \boldsymbol{I}}{\partial t} \mathrm{~d} t=0 xI dx+yI dy+tI dt=0
然后就是除dt移项
∂ I ∂ x d x d t + ∂ I ∂ y d y d t = − ∂ I ∂ t \frac{\partial \boldsymbol{I}}{\partial x} \frac{\mathrm{d} x}{\mathrm{~d} t}+\frac{\partial \boldsymbol{I}}{\partial y} \frac{\mathrm{d} y}{\mathrm{~d} t}=-\frac{\partial \boldsymbol{I}}{\partial t} xI dtdx+yI dtdy=tI
对于上面这个式子, d x / d t dx/dt dx/dt d y / d t dy/dt dy/dt就是我们要求的像素点的运动速度,记为u和v。其他项就是图像关于x,y,t的梯度,通过opencv或者自己去计算都可以求。最终就有
[ I x I y ] [ u v ] = − I t \left[\begin{array}{ll}\boldsymbol{I}_x & \boldsymbol{I}_y\end{array}\right]\left[\begin{array}{l}u \\ v\end{array}\right]=-\boldsymbol{I}_t [IxIy][uv]=It
但是只有一个像素点只有一个方程,所以一般是假设在点附近的一个窗口具有同样的运动,所以取一个w*w的窗口,就有 w 2 w^2 w2个方程
[ I x I y ] k [ u v ] = − I t k , k = 1 , … , w 2 \left[\begin{array}{ll}\boldsymbol{I}_x & \boldsymbol{I}_y\end{array}\right]_k\left[\begin{array}{l}u \\ v\end{array}\right]=-\boldsymbol{I}_{t k}, \quad k=1, \ldots, w^2 [IxIy]k[uv]=Itk,k=1,,w2
这个就是用经典最小二乘法即可求出u和v,因为两帧图像的时间差是已知的,所以就可以在当前帧得到上一帧的对应点位置。

代码实现

书中除了直接用opencv去实现光流,同样通过高斯牛顿手写了一个光流法。本质上是求解一个优化问题:
min ⁡ Δ x , Δ y ∥ I 1 ( x , y ) − I 2 ( x + Δ x , y + Δ y ) ∥ 2 2 \min _{\Delta x, \Delta y}\left\|\boldsymbol{I}_1(x, y)-\boldsymbol{I}_2(x+\Delta x, y+\Delta y)\right\|_2^2 Δx,ΔyminI1(x,y)I2(x+Δx,y+Δy)22
这个写法有点像直接法的光度误差,只不过目标不一样,光流法求的是上一帧跟踪像素点在当前帧图片的像素位置。那么对应的雅可比就是 I 2 I_2 I2 x + Δ x , y + Δ y x+\Delta x, y+\Delta y x+Δx,y+Δy 处的梯度。但是这样子的定义感觉是有些歧义,最好是把 x + Δ x , y + Δ y x+\Delta x, y+\Delta y x+Δx,y+Δy当成一个整体 x 2 , y 2 x_2,y_2 x2,y2,优化目标就是 x 2 , y 2 x_2,y_2 x2,y2(即跟踪点在第二帧图片的位置)。
请添加图片描述
这样展开才能说得过去对应的雅可比就是 I 2 I_2 I2 x + Δ x , y + Δ y x+\Delta x, y+\Delta y x+Δx,y+Δy 处的梯度。也可以参考SLAM光流法、直接法代码踩坑记录

然后后续程序就是基于单层光流去构建构建图像金字塔从粗到细实现多层光流,多层光流实际上可以帮助整个优化问题更好逼近全局最优解,而不是受图像梯度影响陷入局部最优。
在这里插入图片描述

代码结果

很明显在目标函数优化后的误差,多层光流是优于单层光流的,也证明了多层光流的有效性。

直接法

直接法根据像素点的数量,可以分成稀疏、稠密和半稠密三种。与上面LK光流的区别在于,直接法通过构建两帧图片之间的光度误差,来直接优化两帧的R和t。而LK光流只是完成了像素点跟踪的问题。

公式推导

用下书的原图:
在这里插入图片描述
对于同一个三维点P,有下面的式子:其实就是相机模型的式子
p 1 = [ u v 1 ] 1 = 1 Z 1 K P , p 2 = [ u v 1 ] 2 = 1 Z 2 K ( R P + t ) = 1 Z 2 K ( T P ) 1 : 3 . \begin{aligned} & \boldsymbol{p}_1=\left[\begin{array}{l}u \\ v \\ 1\end{array}\right]_1=\frac{1}{Z_1} \boldsymbol{K} \boldsymbol{P}, \\ & \boldsymbol{p}_2=\left[\begin{array}{l}u \\ v \\ 1\end{array}\right]_2=\frac{1}{Z_2} \boldsymbol{K}(\boldsymbol{R} \boldsymbol{P}+\boldsymbol{t})=\frac{1}{Z_2} \boldsymbol{K}(\boldsymbol{T} \boldsymbol{P})_{1: 3} .\end{aligned} p1= uv1 1=Z11KP,p2= uv1 2=Z21K(RP+t)=Z21K(TP)1:3.

然后就是通过光度误差构建优化问题。
e = I 1 ( p 1 ) − I 2 ( p 2 ) e=\boldsymbol{I}_1\left(\boldsymbol{p}_1\right)-\boldsymbol{I}_2\left(\boldsymbol{p}_2\right) e=I1(p1)I2(p2)
min ⁡ T J ( T ) = ∥ e ∥ 2 \min _{\boldsymbol{T}} J(\boldsymbol{T})=\|e\|^2 minTJ(T)=e2
对于多个空间点就能构成多个误差项
min ⁡ T J ( T ) = ∑ i = 1 N e i T e i , e i = I 1 ( p 1 , i ) − I 2 ( p 2 , i ) \min _{\boldsymbol{T}} J(\boldsymbol{T})=\sum_{i=1}^N e_i^{\mathrm{T}} e_i, \quad e_i=\boldsymbol{I}_1\left(\boldsymbol{p}_{1, i}\right)-\boldsymbol{I}_2\left(\boldsymbol{p}_{2, i}\right) TminJ(T)=i=1NeiTei,ei=I1(p1,i)I2(p2,i)

接下来就是去求误差对位姿T的雅可比。定义两个中间变量:
q = T P , u = 1 Z 2 K q \begin{aligned} \boldsymbol{q} & =\boldsymbol{T} \boldsymbol{P}, \\ \boldsymbol{u} & =\frac{1}{Z_2} \boldsymbol{K} \boldsymbol{q} \end{aligned} qu=TP,=Z21Kq
q是图中三维点P经过T的变换后在第二帧图像的三维坐标,u就是其在第二帧图像对应的像素。接着也是一阶的泰勒展开:
∂ e ∂ T = ∂ I 2 ∂ u ∂ u ∂ q ∂ q ∂ δ ξ δ ξ \frac{\partial e}{\partial \boldsymbol{T}}=\frac{\partial \boldsymbol{I}_2}{\partial \boldsymbol{u}} \frac{\partial \boldsymbol{u}}{\partial \boldsymbol{q}} \frac{\partial \boldsymbol{q}}{\partial \delta \boldsymbol{\xi}} \delta \boldsymbol{\xi} Te=uI2quδξqδξ
最终可以得到:
J = − ∂ I 2 ∂ u ∂ u ∂ δ ξ \boldsymbol{J}=-\frac{\partial \boldsymbol{I}_2}{\partial \boldsymbol{u}} \frac{\partial \boldsymbol{u}}{\partial \delta \boldsymbol{\xi}} J=uI2δξu
其中
∂ u ∂ δ ξ = [ f x Z 0 − f x X Z 2 − f x X Y Z 2 f x + f x X 2 Z 2 − f x Y Z 0 f y Z − f y Y Z 2 − f y − f y Y 2 Z 2 f y X Y Z 2 f y X Z ] \frac{\partial \boldsymbol{u}}{\partial \delta \boldsymbol{\xi}}=\left[\begin{array}{cccccc}\frac{f_x}{Z} & 0 & -\frac{f_x X}{Z^2} & -\frac{f_x X Y}{Z^2} & f_x+\frac{f_x X^2}{Z^2} & -\frac{f_x Y}{Z} \\ 0 & \frac{f_y}{Z} & -\frac{f_y Y}{Z^2} & -f_y-\frac{f_y Y^2}{Z^2} & \frac{f_y X Y}{Z^2} & \frac{f_y X}{Z}\end{array}\right] δξu=[Zfx00ZfyZ2fxXZ2fyYZ2fxXYfyZ2fyY2fx+Z2fxX2Z2fyXYZfxYZfyX]
是前面BA也涉及到的雅可比,经典像素对左扰动的雅可比。

代码实现

书中的代码也是给出了手动高斯牛顿的方法,并且结合图像金字塔。结果也是显然,多层直接发的误差最终是更小,效果也更好。

总结

光流法总结

本质上做了特征匹配的工作,光流法通过估计像素的运动来得到上一帧跟踪点在当前帧图像的像素位置。
优点:

  1. 运算速度快,因为省去了计算特征点描述子和特征匹配的过程

缺点:

  1. 灰度不变是很强的假设,实际并不一定满足,对图像的连续性和光照稳定性要求高
  2. 如果在一些角点很难提取的地方,像素点的跟踪效果会变差,导致后续位姿估计的结果

直接发总结

直接基于两帧图片,构建光度误差优化两帧图像之间的R和t。避免了跟踪点的过程。
优点:

  1. 直接法根据点的来源分成稀疏直接法,半稠密直接法,稠密直接法。一般稀疏直接法用于实时性要求高的视觉定位系统中。稠密直接法一般用于结构重建上。
  2. 稀疏直接法计算速度快,省去计算特征点和描述子的时间,实时性较好。
  3. 有像素梯度即可,不要求特征点,所以在一些特征缺失的场景可以使用。

缺点:

  1. 本质上图像是非凸函数,所以优化的过程中会容易陷入局部最优。可以通过图像金字塔改善效果。
  2. 直接法在选点少的情况下,效果不好,一般建议500个点以上。
  3. 灰度不变假设,实际不一定满足。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HaloDB 的 Oracle 兼容模式

↑ 关注“少安事务所”公众号,欢迎⭐收藏,不错过精彩内容~ 前倾回顾 前面介绍了“光环”数据库的基本情况和安装办法。 哈喽,国产数据库!Halo DB! 三步走,Halo DB 安装指引 ★ HaloDB是基于原生PG打造的新一代高性能安…

基于 FastAI 文本迁移学习的情感分类(93%+Accuracy)

前言 系列专栏:【深度学习:算法项目实战】✨︎ 涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域,讨论了各种复杂的深度神经网络思想,如卷积神经网络、循环神经网络、生成对…

JAVA:多线程常见的面试题和答案

请关注微信公众号:拾荒的小海螺 博客地址:http://lsk-ww.cn/ 1、并发编程三要素? 原 子 性 原子性指的是一个或者多个操作,要么全部执行并且在执行的过程中不被其他操作打断,要么就全部都不执行。可 见 性 可见性指多…

NSSCTF | [SWPUCTF 2021 新生赛]no_wakeup

打开题目后&#xff0c;点击三个&#xff1f;&#xff0c;发现是一个php序列化脚本 <?phpheader("Content-type:text/html;charsetutf-8"); error_reporting(0); show_source("class.php");class HaHaHa{public $admin;public $passwd;public function…

CentOS下安装SVN客户端及使用方法

一、前言 Subversion&#xff08;SVN&#xff09;是一款开源的版本控制系统&#xff0c;它可以帮助开发者追踪和管理代码、文档或其他文件的更改历史。在Linux系统中&#xff0c;特别是在CentOS环境下&#xff0c;安装和使用SVN客户端是日常工作中常见的任务。本文将介绍如何在…

数学建模--LaTex插入表格详细介绍

目录 1.插入普通的边线表格 3.三线表的插入和空格说明 3.基于复杂情况下表格的插入 1.插入普通的边线表格 &#xff08;1&#xff09;像这个右边的生成的这个比较普通的表格&#xff0c;我们是使用下面的代码实现的&#xff1a; &#xff08;2&#xff09;和插入一个一个图片…

【漏洞复现】大华智能物联综合管理平台 log4j远程代码执行漏洞

0x01 产品简介 大华ICC智能物联综合管理平台对技术组件进行模块化和松耦合&#xff0c;将解决方案分层分级&#xff0c;提高面向智慧物联的数据接入与生态合作能力。 0x02 漏洞概述 大华ICC智能物联综合管理平台/evo-apigw/evo-brm/1.2.0/user/is-exist 接口处存在 l0g4i远程…

基于FMEA保证汽车电控系统的可靠性

随着汽车技术的飞速发展&#xff0c;电控系统已成为现代汽车的“大脑”&#xff0c;掌控着车辆的方方面面。然而&#xff0c;这一复杂的系统也面临着诸多潜在失效风险&#xff0c;如何确保汽车电控系统的可靠性&#xff0c;成为汽车制造业亟待解决的问题。幸运的是&#xff0c;…

SQL刷题笔记day6-1

1从不订购的客户 分析&#xff1a;从不订购&#xff0c;就是购买订单没有记录&#xff0c;not in 我的代码&#xff1a; select c.name as Customers from Customers c where c.id not in (select o.customerId from Orders o) 2 部门工资最高的员工 分析&#xff1a;每个部…

LPDDR6带宽预计将翻倍增长:应对低功耗挑战与AI时代能源需求激增

在当前科技发展的背景下&#xff0c;低能耗问题成为了业界关注的焦点。国际能源署(IEA)近期报告显示&#xff0c;日常的数字活动对电力消耗产生显著影响——每次Google搜索平均消耗0.3瓦时&#xff08;Wh&#xff09;&#xff0c;而向OpenAI的ChatGPT提出的每一次请求则消耗2.9…

008-Linux后台进程管理(作业控制:、jobs、fg、bg、ctrl + z、nohup)

文章目录 前言 1、& 2、ctrl z 3、jobs 4、fg&#xff1a;将后台进程调到前台执行 5、bg&#xff1a;将一个暂停的后台进程变为执行 6、&和nohup 总结 前言 有时候我们需要将一个进程放到后台去运行&#xff0c;或者将后台程序切换回前台&#xff0c;这时候就…

【笔记】Pytorch安装配置

参考视频 安装前建议预留至少10个G的空间&#xff0c;会省下很多麻烦 查看安装是否成功&#xff0c;可以在Anaconda Prompt里输入conda list查看conda环境是否配置了pytorch/torchvision 1.安装anaconda 2.安装 CUDA CUDA在官网直接安装即可&#xff0c;需要先查看自己电脑…

文件IO(二)

文件IO&#xff08;二&#xff09; 标准IO缓冲类型全缓冲行缓冲不缓冲 打开文件fopen 操作文件按字符读写(fgetc fputc)按行读写&#xff08;fgets fputs&#xff09;按块&#xff08;对象&#xff09;读写&#xff08;fread fwrite&#xff09;按格式化读写&#xff08;fscanf…

计算机网络学习笔记——应用层

一、应用层概述 二、客户/服务器方式(C/S方式)和对等方式(P2P方式) 客户/服务器(Client/Server&#xff0c;C/S)方式 服务器总是处于运行状态&#xff0c;并等待客户的服务请求。服务器具有固定端口号(例如HTTP服务器的默认端口号为80)&#xff0c;而运行服务器的主机也具有固…

使用git生成SSH公钥,并设置SSH公钥

1、在git命令行里输入以下命令 ssh-keygen -t rsa 2、按回车&#xff0c;然后会看到以下字眼 Generating public/private rsa key pair. Enter file in which to save the key (/c/Users/xxx/.ssh/id_rsa) 例&#xff1a; 3、继续回车&#xff0c;然后会看到以下字眼 Enter…

Linux中断

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、中断的相关概念1.中断号2.中断的申请和释放申请API函数如下&#xff1a;释放API函数如下&#xff1a;中断处理函数如下&#xff1a;使能和禁止中断 二、上半…

Mac安装tomcat

代码 brew install tomcat 运行结果如下&#xff1a; 如果要启动输入&#xff1a; brew services start tomcat

Linux学习笔记(epoll,IO多路复用)

Linux learning note 1、epoll的使用场景2、epoll的使用方法和内部原理2.1、创建epoll2.2、使用epoll监听和处理事件 3、示例 1、epoll的使用场景 epoll的英文全称是extend poll&#xff0c;顾名思义是poll的升级版。常见的IO复用技术有select&#xff0c;poll&#xff0c;epo…

连锁收银系统支持带结算功能

连锁实体店的收银系统需要支持结算功能&#xff0c;以适应连锁运营效率和提升连锁管理的水平。商淘云连锁收银系统与您一起分享连锁收银系统需支持结算功能的三大必要点。大家点赞收藏&#xff0c;以免划走后找不到了。 一是&#xff0c;连锁模式的运营比较复杂&#xff0c;有加…

同时执行多个python脚本扫描,报如下错误,原因为文件越大读取到内存占用内存越多。

killed nohup python $file unable to fork process cannot allocate memory ls: error while loading shared libraries: libdl.so.2 failed to map segment from shared object cannot allocate memory python进程被系统或者某个用户通过 kill 命令强制终止了