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

相关文章

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

Java MCP 的鉴权深度解析

《JavaMCP的鉴权深度解析》文章介绍JavaMCP鉴权的实现方式,指出客户端可通过queryString、header或env传递鉴权信息,服务器端支持工具单独鉴权、过滤器集中鉴权及启动时鉴权... 目录一、MCP Client 侧(负责传递,比较简单)(1)常见的 mcpServers json 配置

从基础到高级详解Python数值格式化输出的完全指南

《从基础到高级详解Python数值格式化输出的完全指南》在数据分析、金融计算和科学报告领域,数值格式化是提升可读性和专业性的关键技术,本文将深入解析Python中数值格式化输出的相关方法,感兴趣的小伙... 目录引言:数值格式化的核心价值一、基础格式化方法1.1 三种核心格式化方式对比1.2 基础格式化示例

redis-sentinel基础概念及部署流程

《redis-sentinel基础概念及部署流程》RedisSentinel是Redis的高可用解决方案,通过监控主从节点、自动故障转移、通知机制及配置提供,实现集群故障恢复与服务持续可用,核心组件包... 目录一. 引言二. 核心功能三. 核心组件四. 故障转移流程五. 服务部署六. sentinel部署

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

Maven中生命周期深度解析与实战指南

《Maven中生命周期深度解析与实战指南》这篇文章主要为大家详细介绍了Maven生命周期实战指南,包含核心概念、阶段详解、SpringBoot特化场景及企业级实践建议,希望对大家有一定的帮助... 目录一、Maven 生命周期哲学二、default生命周期核心阶段详解(高频使用)三、clean生命周期核心阶

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Java Scanner类解析与实战教程

《JavaScanner类解析与实战教程》JavaScanner类(java.util包)是文本输入解析工具,支持基本类型和字符串读取,基于Readable接口与正则分隔符实现,适用于控制台、文件输... 目录一、核心设计与工作原理1.底层依赖2.解析机制A.核心逻辑基于分隔符(delimiter)和模式匹

Java+AI驱动实现PDF文件数据提取与解析

《Java+AI驱动实现PDF文件数据提取与解析》本文将和大家分享一套基于AI的体检报告智能评估方案,详细介绍从PDF上传、内容提取到AI分析、数据存储的全流程自动化实现方法,感兴趣的可以了解下... 目录一、核心流程:从上传到评估的完整链路二、第一步:解析 PDF,提取体检报告内容1. 引入依赖2. 封装