双目视觉学习[1]——OpenCV源码StereoBM笔记

写在最前面

之前曾经尝试过将一些笔记放出来,然后发现有错。有一次被一个暴躁的网友直接开喷,导致不开心了好久、、、想想也确实要审核一下自己分享的东西,毕竟很容易误导别人。
这里要说明的是,这只是一篇笔记,知识有限,肯定还存在错误,也希望各位能够直接提出来,且一切以OpenCV源码为准,特别是源码是直接操作指针的,兜兜转转有点晕,很可能导致理解的地址重叠了。且这里仅仅是源代码解读,因为如何调用StereoBM类以实现基于SAD的匹配只要随便搜一下就有,因此这篇文章不包括如何使用。
先放出参考文章:
OpenCV官方文档:https://docs.opencv.org/3.4.8/d2/d75/namespacecv.html
StereoBM各参数意义:https://blog.csdn.net/KinboSong/article/details/72918432
北络前辈的源码解读:https://blog.csdn.net/wangbaodong070411209/article/details/86633595
以及github上前辈的解读:https://jiweibo.github.io/StereoBM/
OpenCV指针对齐函数alignPtr说明:https://www.tuicool.com/articles/q2QrQr
OpenCV并行计算函数及其使用:https://blog.csdn.net/qq_28087491/article/details/118992396

StereoBM计算流程

以我个人学习到的知识,在学习一段代码之前,应当站在一个大一统的高度去了解它的目的、实现方法及技巧。
双目视觉四步骤分别为:

  1. 匹配代价计算
  2. 代价聚合
  3. 视差计算
  4. 视差精化
    下面将展开讲讲OpenCV中StereoBM(以下简称BM)是如何实现以上4个步骤的

匹配代价计算

BM中选择绝对差值SAD(Sum of Absolute Difference)算子计算匹配代价,常用的还包括差值平方和SSD、归一化相关系数NCC、零均值绝对值和ZSAD等,其余的诸如Harris角点、SIFT特征子以及频域特征等由于计算成本过于昂贵,一般不怎么用。
所谓的绝对差值即是将对应位置的像素相减,然后求绝对值之和:
C ( x , y , d ) = ∑ x ∈ S ∣ I R ( x , y ) − I M ( x + d , y ) ∣ C(x,y,d)=\sum_{x\in S}{|I_{R}(x,y)-I_{M}(x+d,y)|} C(x,y,d)=xSIR(x,y)IM(x+d,y)
其中 I R I_{R} IR I M I_{M} IM分别为参考图像和匹配图像, S S S则为 x x x的邻域,邻域大小由SAD窗口大小决定,且窗口一般取奇数,如5×5等,窗口越大感受野越大,匹配效果会好一些,但计算量也在逐渐增加。
其实这种滑动块的代价计算算子存在大量重复计算的计算冗余,如下图所示,当换行或者换列时,两个SAD窗口重叠部分的像素均是重复运算的。
双目视觉学习[1]——OpenCV源码StereoBM笔记_第1张图片

为此OpenCV源码中的BM算法中加入了Box-Filter优化方法。通俗点讲就是边吃边拉,且将矩形框(一般SADWindow是正方形框)拆分成行和列即1×n和n×1矩形框,先计算行的吃拉,再计算列的,如下图所示。不得不说,传统的算法的智慧真的博大精深,甚至感觉深度可分离卷积核(Depthwise Separable Convolution)的灵感来自如此。
双目视觉学习[1]——OpenCV源码StereoBM笔记_第2张图片
在OpenCV源码中,在计算行的SAD时,会将所计算每个像素位置的绝对差值储存在内存中,是典型的以空间换时间的编码策略。

代价聚合

BM算法的代价聚合比较简单,直接选择赢者通吃WTA(Winner Takes All)策略。如图所示:
双目视觉学习[1]——OpenCV源码StereoBM笔记_第3张图片

  • 图源https://jiweibo.github.io/StereoBM/

视差计算

选择最小值所对应的视差即为当前位置的视差值

视差精化

视差精化主要包括过滤噪点值以及亚像素视差计算等。BM算法则包括了纹理检测、唯一性检测以及左右一致性检测。
1、纹理检测
BM算法除了计算每个位置不同视差对应的SAD代价外,还会通过查表的方式计算每个位置的纹理(这个纹理计算方法没找到公式,光看程序看不太懂就不贴出来了。)。对于纹理强度较弱的位置,BM算法会认为该位置的视差不可信,并用-1替代。
2、唯一性检测
双目视觉普遍约定,视差值存在则必然唯一,即一个位置不存在多个视差值的可能。BM算法中的唯一性检测则是在一个位置中,第二小匹配代价的视差值必须要小于或等于最优视差所对应视差值的(1+uniquenessRatio/100)倍:
C s m i n ≤ C m i n ⋅ ( 1 + u n i q u e n e s s R a t i o / 100 ) C_{smin} \le C_{min} \cdot (1+uniquenessRatio/100) CsminCmin(1+uniquenessRatio/100)
其中 s m i n smin smin表示第二小。否则这个位置所计算的视差值不可信并用-1代替。
3、左右一致性检测(可选)
在BM算法中,左右一致性检测是可选的,可以不执行。一般来说,第一次匹配都是以左图像为参考图,右图像为匹配图,这样得到第一幅视差图。所谓的左右一致性检测则是第二次以右图像为参考图,左图像为匹配图计算得到第二幅视差图。当两张视差图在同一位置的差值大于disp12MaxDiff的时候,则认为当前位置所计算的视差不可信,用-1代替。

源代码解读

由于代码量较大,直接把代码文件和笔记文件放到资源贴里了。如果要会员什么的就从百度云下载。
链接: link.

百度云:
链接:https://pan.baidu.com/s/16o0gTnR4O-4KbOXmjTNtww
提取码:faps

你可能感兴趣的:(C++,OpenCV源码注释,opencv,学习,计算机视觉)