Stereo Processing by Semi-Global Matching and Mutual Information基础算法解析

本文主要是介绍Stereo Processing by Semi-Global Matching and Mutual Information基础算法解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

*原创文章,非作者允许,禁止一切形式的转载。

Stereo Processing by Semi-Global Matching and Mutual Information 是立体匹配中一个非常有名的算法,算法快、重建精度也不错、非常适合并行加速。

 

A.匹配代价计算

这部分作者在讲匹配代价计算,作者用的是信息熵,然而在实际应用中发现这一匹配代价好像效果也比较一般,使用census transform的很多。如果对信息熵想仔细了解,可以参考 @迷雾forest 这篇文章。

代价计算这一步,首先要确定disparity range(就是你觉得这张图片中场景的深度范围,比如是20),然后对disparity range划分间隔,可以把间隔划分为256份,这里间隔是多少,就决定了视差图的分辨率。每一个深度值都可以计算出每个像素处的匹配代价,那么就得到了一个cost volume,如图1所示,宽width高height分别对应图像的宽和高 ,disparity range是深度空间,每一个小格子是一个匹配代价。

图1. 匹配代价图

 

B.代价聚合

匹配代价是有噪音的,有时候错误的深度对应的匹配代价反而会比正确深度对应的匹配代价小。因此需要进行优化,也就是代价聚合。论文中构建的能量函数是:

\small E(D)=\sum_{p}(C(p,D_{p})+\sum_{ q\in N_{p}}P_{1}T[|D_{p}-D_{q}|=1]+\sum_{ q\in N_{p}}P_{2}T[|D_{p}-D_{q}|>1]) \quad (1) 

第一项是匹配代价,第二项表示如果该像素的视差与周围像素相差1,则要加一个值为P1的惩罚,注意这里是累加符号,表明周围有几个视差相差1的像素,则要加几个P1,第三项表示如果该像素的视差与周围像素相差大于1,则要加一个值为P2的惩罚。也是周围有多少个像素满足就要加几个P2.。为什么要有第二项和第三项呢?这两项往往也被称为平滑项,可以这样理解,一个像素点的视差值取决于他自身的cost以及周围像素的视差情况,如果完全相信自身,那就是第一项,但是自身有误差,所以要考虑周围的像素的视差,那么就是后两项,但是要想相信周围的视差必须要加一个惩罚项,表明来自周围的信息的可靠程度没有自身cost的可靠程度高,P1的惩罚主要是为了在弯曲或者倾斜的表面进行调整(深度变化小),P2的惩罚则主要是为了处理深度不连续的情况(深度变化大)。

要最小化这个能量函数,直接求解很困难,论文中说是NPcomplete 问题,但是如果在单独的行上进行1D的求解,求解将会非常的快,所以作者把这个问题分成了在多个方向上进行1D的求解,把一个二维问题分解成多个一维求解问题,注意这里只是一种近似,因此最终的结果并不一定是最优的。下面先说1D方向上的代价聚合:

\large L_{r}^{'}(p,d)}=C(p,d)+min(L_{r}^{'}(p-r,d),L_{r}^{'}(p-r,d-1)+P1,L_{r}^{'}(p- r,d+1)+P1,min_{i}}L_{r}^{'}(p-r,i)+P2) \qquad \qquad (2)

第一项是匹配代价,后面的项是传播项。公式的意思是说当前像素某个深度对应的聚合的代价=自己本身的代价(就是census计算的代价)+传播过来的代价,传播过来的代价根据深度不同分为四类:a,等于当前深度 b,比当前深度少1 c,比当前深度大1 d,其他深度值,会在这四类深度中选择一个对应的代价最小的深度,如果是a类深度,就直接是对应代价,如果是b,c类深度,需要在对应代价的基础上加上P1,如果是d类深度,需要在对应代价的基础上加P2。 如下图:注意这里有个简化是d类深度加P2,只需找到d类深度的最小代价加P2即可

图2. 一个方向上某个像素的代价聚合过程

 

图2是一个方向上的某个像素代价聚合的过程,假设有10个深度空间,d=1,2...10,分别对应10个匹配代价,该匹配代价就是第一步计算的匹配代价聚合后的结果,当前像素的匹配代价就是第一步直接计算出的匹配代价,然后每个匹配代价都按照公式(2)进行代价更新,更新后的匹配代价作为继续向下一个像素传播,重复该过程。

要求解(1)式,可以把它近似看成在多个1D方向上的聚合, 就可以近似求解这个问题了。要注意的是:

  • 代价聚合的方向一般要不少于8个,每个像素最终的代价是所有方向相加的结果。
  • 随着代价聚合的进行,匹配代价会很大造成具体实现时的数据溢出,一般会在代价聚合的时候减去当前像素所有匹配代价中的最小值,对于这个例子来说就是减去11.这个操作对应sgm论文中的公式(13)。
  • p1,p2的选取可以根据具体的应用进行调整,一般p1是一个定值,p2可以随着图像梯度变化而变化,往往要保证p2>=p1
  • 时间复杂度是o(whd)

C.视差计算

代价聚合后,选择每个像素处最小的代价所对应的深度作为该像素的深度,至于亚像素级的深度预测,使用二次曲线进行拟合。

论文后面部分还讲了multi-baseline情况的处理、视差图优化,以及视差图融合等内容,直接利用sgm算法计算出的深度图一般是有很大噪声的,后面的视差图的优化和融合在实际应用中是一个非常重要的部分,不过我认为这些优化和融合策略可以根据自己的具体应用去设计,论文的后面的部分这里不再讨论。

总结:sgm算法重建精度还可以,非常适合cuda加速,加速之后速度可以很快,缺点是有些细小的物体可能不太容易建出来,由于算法是基于前向平行假设的,与成像平面非平行的平面重建的不是太好,尤其是与与成像平面垂直的平面。

 

这篇关于Stereo Processing by Semi-Global Matching and Mutual Information基础算法解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/695404

相关文章

Java的IO模型、Netty原理解析

《Java的IO模型、Netty原理解析》Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等,这篇... 目录1.什么是IO2.同步与异步、阻塞与非阻塞3.三种IO模型BIO(blocking I/O)NI

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

C#基础之委托详解(Delegate)

《C#基础之委托详解(Delegate)》:本文主要介绍C#基础之委托(Delegate),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 委托定义2. 委托实例化3. 多播委托(Multicast Delegates)4. 委托的用途事件处理回调函数LINQ

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

Redis中高并发读写性能的深度解析与优化

《Redis中高并发读写性能的深度解析与优化》Redis作为一款高性能的内存数据库,广泛应用于缓存、消息队列、实时统计等场景,本文将深入探讨Redis的读写并发能力,感兴趣的小伙伴可以了解下... 目录引言一、Redis 并发能力概述1.1 Redis 的读写性能1.2 影响 Redis 并发能力的因素二、

Spring MVC使用视图解析的问题解读

《SpringMVC使用视图解析的问题解读》:本文主要介绍SpringMVC使用视图解析的问题解读,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring MVC使用视图解析1. 会使用视图解析的情况2. 不会使用视图解析的情况总结Spring MVC使用视图

利用Python和C++解析gltf文件的示例详解

《利用Python和C++解析gltf文件的示例详解》gltf,全称是GLTransmissionFormat,是一种开放的3D文件格式,Python和C++是两个非常强大的工具,下面我们就来看看如何... 目录什么是gltf文件选择语言的原因安装必要的库解析gltf文件的步骤1. 读取gltf文件2. 提

Java中的runnable 和 callable 区别解析

《Java中的runnable和callable区别解析》Runnable接口用于定义不需要返回结果的任务,而Callable接口可以返回结果并抛出异常,通常与Future结合使用,Runnab... 目录1. Runnable接口1.1 Runnable的定义1.2 Runnable的特点1.3 使用Ru

使用EasyExcel实现简单的Excel表格解析操作

《使用EasyExcel实现简单的Excel表格解析操作》:本文主要介绍如何使用EasyExcel完成简单的表格解析操作,同时实现了大量数据情况下数据的分次批量入库,并记录每条数据入库的状态,感兴... 目录前言固定模板及表数据格式的解析实现Excel模板内容对应的实体类实现AnalysisEventLis