Stereo Matching文献笔记之(十):经典算法Semi-Global Matching(SGM)之碉堡的动态规划~

转载自:https://blog.csdn.net/wsj998689aa/article/details/50488249

上一篇博客中提到了SGM的第一部分,基于分层互信息(HMI)的代价计算,本文继续说说自己对SGM代价聚合部分的理解。

(转载请注明:http://blog.csdn.net/wsj998689aa/article/details/50488249, 作者:迷雾forest)


SGM的代价聚合,其实仔细看看,这并不是严格意义上的代价聚合,因为SGM是为了优化一个能量函数,这和一般的全局算法一样,如何利用优化算法求解复杂的能量函数才是重中之重,其能量函数如下所示:


其中,C(p, Dp)代表的就是基于互信息的代价计算项,后面两项指的是当前像素p和其邻域内所有像素q之间的约束,如果q和p的视差只差了1,那么惩罚P1,如果大于1,那么惩罚P2,这么做基本上是机器学习中的常用方法,即所谓的正则化约束。这里需要注意的是,P2要大于P1,这么做真心有用。

1. 假如不考虑像素之间的制约关系,不假设领域内像素应该具有相同的视差值,那么最小化E(D)就是最小化每一个C,这样的视差图效果很差,因为图像总会收到光照,噪声等因素的影响,最小的代价对应的视差往往是“假的”,并且这样做全然不考虑相邻之间的像素关系,例如,一个桌面的视差明显应该相同,但是可能由于倾斜光照的影响,每个像素的最小代价往往会不同,所以看起来就会乱七八糟,东一块西一块。这就是加上约束的目的。


2. 添加两个正则化项一方面是为了保证视差图平滑,另一方面为了保持边缘(保持边缘一直没想明白为什么?)。惩罚的越大,说明越不想看到这种情况发生,具体来说,如果q和p之间的视差有所差异但又不大,那么就要付出代价,你不是想最小化能量函数么?那么二者都要小,如果没有第二项,那么求出来的视差图将会有明显的锯齿现象,如果只有第三项,那么求出来的视差图边缘部分将会得到保持,但由于没有对相差为1的相邻像素进行惩罚,物体内部很可能出现一个“斜面”。


3. 这事情还没完,本文中有对这两项的解释,原文内容如下所示:



这句话的隐含意思是,如果我们让P1<P2,那么会允许出现小的斜面,也会保持边缘,前面一句我理解,惩罚的力度不大,就会导致这种事情还会发生,这也正是作者想看到的,水至清而无鱼嘛,不过,后一句中的P2并不是常数项,是根据相邻像素的差距来决定的,括号里面的“与大小无关”看起来就更加矛盾了,不知道哪位可以给好好解释一下这句话?


有了能量函数,下面要做的就是求解它了,这个时候问题来了,这个E对p是不可导的,这意味着我们常看到的梯度下降,牛顿高斯等等算法在这里都不适用,作者于是采用了动态规划来解决这一问题,动态规划相信大家都知道了,但是其真正的精髓却是深藏不露,我早在大三期间就接触到了动态规划算法,这么多年过去了,虽然时而会用到这个算法,但到现在仍旧不敢说自己彻底懂它。。。。


简单地说,p的代价想要最小,那么前提必须是邻域内的点q的代价最小,q想要代价最小,那么必须保证q的领域点m的代价最小,如此传递下去。


本文只说说作者是怎么利用动态规划来求解E,其实这个求解问题是NP完全问题,想在2D图像上直接利用动态规划求解是不可能的,只有沿着每一行或者每一列求解才能够满足多项式时间(又叫做扫描线优化),但是这里问题来了,如果我们只沿着每一行求解,那么行间的约束完全考虑不到,q是p的领域的点其实这个时候被弱化到了q是p的左侧点或者右侧点,这样的求优效果肯定很差。于是,大招来了!!我们索性不要只沿着横或者纵来进行优化,而是沿着一圈8个或者16个方向进行优化。


这是一幅神奇的图示,我一直没有弄明白它到底是什么意思,笨死了,直到有一天我终于领悟它的真谛(仰天长啸)。我们先来看看优化求解过程:






每一个点的代价聚合值是“当前代价+min(路径相邻点的当前视差代价聚合值,路径相邻点的视差差值为1的代价聚合值 + P1,路径相邻点的视差插值大于1的最小代价聚合值 + P2)- 路径相邻点的视差插值大于1的最小代价聚合值 ”,听起来够绕口的,其实就好比最小代价的蔓延,当前代价聚合值由当前代价和路径上一点的加了惩罚的最小代价聚合值所决定(最后那一项纯粹是为了防止数字过大,这是常用手段)。

其实为什么分解为8个方向想想看也很正常,能量函数E中每个p的能量是“自身代价本身+周围像素q带来的惩罚”,周围像素足足有8个,想求它们和的最小化十分难,最朴素的想法就是“分而求之”,我们就规定一个方向r,这个方向上p的邻居q只有一个,那么沿着这一方向的p的代价聚合值就成为了上面公式的样子。进一步,将8个方向的代价聚合值都加起来,就形成了p的最终代价聚合值。然后用WTA搞一下得到的视差图可以得到一个较小的能量E,目的就达到了。

我们来想想SGM的优化过程和DoubleBP有什么区别。
1. 先看能量函数,DoubleBP是每个像素自身代价加上周围像素的一个二元势函数值。SGM呢?是自身的代价加上周围像素带来的惩罚。其实二者是一个意思。
2. 再看优化过程,DoubleBP靠的是置信度传播算法,最后WTA的目标是一个置信度向量,这个置信度向量其实和向量没关系,每个分量都是去当前视差d的代价+周围像素的消息,这一点和SGM简直是太像了。
3. 再说说二者的区别,消息的每个分量可以理解为q对p取每个视差的支持力度,而SGM索性直接求取最小的惩罚,这点比DoubleBP要直接许多,所以SGM很快,DoubleBP很慢。

我认为这块内容非常值得单独拉出来说说,以后有时间好好的写写。


最后,我们可以看看SGM的整体流程图,这么长的流程图!!这个没啥好进一步解释的,唯一想说的就是我认为II-A那里多画了两个箭头,指向II-B的箭头应该只有MI一个。


OK,本文就说到这里,好久不写博客了,手都已经生锈了,请大家不吝赐教,帮我想想我问的问题啊!!!

猜你喜欢

转载自blog.csdn.net/cyem1/article/details/80805430