经典算法Semi-Global Matching(SGM)文献笔记(一)

SGM算法源于《Stereo Processing by Semi-Global Matching and Mutual Information》一文,我认为这篇文章是立体匹配算法中最给力的,放眼KITTI

可以发现目前排名前五十的算法几乎一半都是对SGM的改进,具有最强的实用价值。SGM中文名称“半全局匹配”,顾名思义,其介于局部算法和全局算法

之间,所谓半全局指的是算法既没有只考虑像素的局部区域,也没有考虑所有的像素点。例如,BM计算某一点视差的时候,往往根据目标像素周围的矩形区

域进行代价聚合计算;DoubleBP在计算目的像素视差的时候,考虑的则是图像所有的像素点。抛开具体的方法不说,SGM中考虑到的只有非遮挡点,这正是

定义为半全局的原因。

有的童鞋这时可能会想到Non-Local,为啥它要叫“非局部”,难道也是一种半全局算法?我认为不是,NLCA的目的是构建代价聚合项,它没有能量函数构

建优化过程,而构建代价聚合基本上是局部算法才要做的事情,然而基于的却是所有的像素点,所以被称为非局部,并且NLCA和SGM的套路也完全不同。
SGM的文献比较晦涩,作者Heiko Hirschmuller进行了大篇幅的论述,其中涉及到了很多的细节,最开始读这篇文献的时候我完全不理解算法的细节,但是SGM

又经典的不行,没办法只能在反复理解论文的同时,结合代码进行理解。这篇文章主要涉及三个部分:分层互信息的代价计算+基于动态规划的代价聚合+其他,

我打算分别基于这三个部分写三篇博客,与童鞋们分享我对SGM的理解。

和所有的立体匹配算法一样,SGM的第一步也是代价计算,它采用了基于互信息的计算方法,互信息是一种熵。那我们就先说说熵,熵是用来表征随机变量的

不确定性(可以理解为变量的信息量),不确定性越强那么熵的值越大(最大为1),那么图像的熵其实就代表图像的信息量。互信息度量的是两个随机变量

之间的相关性,相关性越大,那么互信息就越大。可以想想看,两幅图像如果匹配程度非常高,说明这两幅图像相关性大还是小?显然是大,知道一幅图像,

另外一幅图像马上就知道了,相关性已经不能再大了!!!反之,如果两幅图像配准程度很低,那么两幅图像的互信息就会非常小。所以,

立体匹配的目的当然就是互信息最大化。这就是为什么使用互信息的原因。熵和互信息的定义分别如下所示:





其中,互信息的前两项是图像的熵,最后一项叫做联合熵,联合熵是熵的变种,其依赖的自然是联合概率分布(熵依赖的是概率分布),

联合熵的公式如下所示:



这时,一个最自然的问题是,图像的概率分布P是什么意思?答案一句话,图像的灰度直方图。图像的灰度值是0~255,每个灰度值对应的像素个数除以图像像素

个数就是该灰度值对应的概率,单幅图像的概率密度是一维的,那么自然地,两幅图像的联合概率密度就是二维的,它的定义域取值就是

(0,0)~(255,255),公式如下所示:




其中,(i,k)指的是像素灰度值对,I1和I2分别代表了左图和矫正之后的右图,p代表像素点,n代表着像素的总数,公式的含义是统计不同灰度值对的个数并

归一化。因此,两幅图像对应的概率分布可以用一幅图表示,这幅图的大小一定是256*256,弄清楚这点很重要,我之前一直误以为上述公式中的(i,k)指

的是像素坐标,其实上面的公式只想告诉我们一件事情:联合概率分布就是归一化之后的统计直方图。

弄清楚了P的含义,就可以进一步说说熵的构造了,作者先说了联合熵的定义,在这里作者引用了其他文献的研究成果,直接用泰勒展开近似联合熵为像素

和的形式,如下所示:



其中,作者称h为数据项,注意看它的自变量是像素灰度值,所以可以事先建立一个查表,将每个灰度值对的h值都保存下来(一共有256*256),那么联合

熵的计算速度就会很快,h的计算公式如下所示:



其中,g(i,k)指的是高斯平滑,正如前面所说,P是一幅表征概率值的图像(分辨率恒为256*256),正是针对这幅图像进行平滑处理,但是作者却在这里

称之为Parzen估计,我想来想去觉得是一个意思,Parzen估计是一种非参数估计方法,不需要事先假设数学模型的参数形式而直接估计单点的概率值,

最常用的Parzen窗函数就是高斯核函数。作者提供了一个图示也可以说明这个问题:



其中,第一个坐标系就是联合概率分布图,由于事先要对匹配图像(一般是右图)基于视差图进行修正(warp),调整右图像素的位置,使得左右两图

尽可能相同之后计算同一像素位置的联合概率,由此导致了诸如(10,10)、(25,25)、(125,125)这样的灰度值对的概率值更大一些。再对这样的

图像进行7*7窗口大小的高斯平滑处理,高斯平滑的目的是消除噪音,因为这里基于的视差图是很粗糙的,根据这样的视差图对右图进行处理,难免一些

位置所对应的两图灰度值不相等,体现在P图上就是噪音,这个时候当然要平滑。例如可能有(10,100)这样的灰度值对出现,这说明右图该点经过warp

之后很可能是错误的,但是这种情况肯定是少数,对应的概率值也就是很小,体现在P图上就是一个噪音点,用高斯平滑处理,一下子就没了。其实这就是

检测outlier,去除outlier的另外一种手段,只不过SGM是从概率分布的角度处理罢了,而其他的算法一般都是从空间分布来处理outlier。进一步,取负对

数便得到了h值的图示,最后得到了图像的联合熵图。



其实,平滑归平滑,也只是基于256*256的图像进行平滑,只需根据像素位置计算出权重即可,同样可以根据查表的方式实现,这和具体的双目图像大小

仍旧无关,一个不小的优点哦!

作者为什么要用互信息来计算代价匹配值?根据文献给出的信息,作者是考虑到了互信息对光照具有鲁棒性,我们注意看下面的公式,这个计算方式很有

意思,我们已经得到了互信息图,剩下要做的事情只是根据左图和右图挑选出来的像素点的灰度值对,在互信息图中直接查找就行(又是一个速度优势)

注意:要取个负号,这点直觉上很好理解,互信息越大->相关性越大->两个点的匹配程度越高->代价计算值理应越小

童鞋们千万不要忘记WTA是怎么运作的啊!!!!




本来熵和联合熵的计算方法不同,但是由于遮挡点的问题,将二者都设置为相同,都采用泰勒近似的方式。具体来说,图像的熵是基于图像的概率分布

来计算的,但由于遮挡点的存在,有些像素根本就不会有匹配点,如果也将这样的像素考虑在内恐怕不合适,别忘了我们的目的是令能够匹配的点尽量匹配,

不能匹配的点我们根本就没必要让它们匹配,于是将目光放在了联合熵的定义上,联合熵是基于联合概率分布的,其基于的点可以保证都是匹配点,

这样的概率公式如下所示:



进一步,基于这样的概率分布得到的图像熵公式如下所示:



最后,作者采用分层互信息(HMI)进行代价匹配计算,由于概率分布图和图像大小无关(一直都是256*256),所以可以采用分层计算的方式

来加速(反正不同层都是256*256),每一层的计算对应一次迭代,别忘记首次迭代需要基于视差图对右图进行warp,没有视差图怎么办?

文章里面说是随机生成就好,并且由于像素个数很多,随机生成的个别错误可以被容忍,warp之后的右图和左图的匹配程度还是会比较高,

迭代次数也相对较低,这也是SGM的一大优点。



作者还对HMI的时间复杂度进行了计算,由于单次迭代的时间复杂度是O(WHD),每次下采样都会令三个参数同时减半,所以上次迭代将会

是当前迭代速度的1/8,假设我们有4次迭代,那么相比较于BT算法,只比它慢了14%,注意,算法首次迭代使用的是最小的视差图,

且乘以3的原因是随机生成的视差图十分不靠谱,需要反复迭代3次才能得到同样分辨率下的靠谱视差图,然后再参与后续高分辨率的计算。




总结:HMI是SGM的重要一步骤,通过HMI计算得到的代价匹配值对光照鲁棒,一旦这步做好了,后续的代价聚合,迭代求精等等操作弄起来就轻松多了。

你可能感兴趣的:(立体视觉)