[用紙ノート]でビルグラフィックスハードウェア上でシステムをマッチング正確なステレオ

- 同僚は、紙をお勧めします、それはパイプラインを感じているので、彼らはそれのための走査線の最適化の理由を使用していたかもしれないが、本当に好きで、それと一緒に書かれたSGBMのOpenCVのソースの研究ノートをしたい:)

序文

  1. 温首相は、シリーズの他のヘビー級のアルゴリズム(CC、CA、最適化、精密化)の基本的な種類ミドル、トップ10には、効果は非常によく、すべてであることを指摘し、トリックを使用したり、複雑なデータ構造を設計する必要モバイルデバイスで使用するために、GPUを使用して促進するために、性能心配。

  2. 組み合わさいくつかの軽量モジュールの作者は、GPUで加速させることができる、効果は、モバイルデバイス上で可能な限り利用して、かなり良いです。実際には、pipline比較的正常:AD国勢調査+ CBCA +スキャンライン最適化+従来の絞り込み、それぞれ、以下の参考文献から:

  • ADセンサス:
    X.日、X.メイ、S.交通、M.周、およびH.王。信頼性の高い視差伝播付きステレオマッチング。PROCで。3DIMPVT、ページ132-139、2011。
  • CBCA:
    K.チャン、J. Lu及びG. Lafruit。直交積分画像を使用してクロスベースのローカルステレオマッチング。IEEE TCSVT、19(7):1073年から1079年、2009年
  • スキャンラインの最適化:
    H.Hirschm¨uller。セミグローバルマッチングと相互情報によるステレオ処理。IEEE TPAMI、30(2):328から341、2008。

概要

紙へのリンク

論文

ソースリンク

コード

核となるアイデア

コスト計算(コスト計算、CC):AD +国勢調査は、すなわち:絶対差(AD)措置と国勢調査変換します

重合の検討(コスト集約、CA):CBCA、すなわち、交差窓のコストに基づく重合方法

視差(視差計算)を解く:スキャンライン最適化+ WTAは、従来のものであり、文献に走査線最適化SGM +勝者がすべて取り

処理後(ポストプロセス、絞り込み):+ +サブピクセルエッジ強調最適化+領域補間投票

貢献ポイント

上記パイプラインの建設に、達成CUDA GPUバージョンに基づいて

関連調査

アルゴリズム

所得階層

余談:

R. Zabih及びJ. Woodfill。視覚的な対応関係を計算するためのノンパラメトリックローカル変換します。PROCで。ECCV、ページ151-158、1994。

このホワイトペーパーでは、それが空のときに読み取られるように、同じよう国勢調査、ADなどのコスト計算方法、BTとSGBMの内部に言及します。

H.Hirschm¨ullerとD. Scharstein。放射違いで画像のステレオマッチングコストの評価。
IEEE TPAMI、31(9):1582年から1599年、2009年。

ダニエルH.Hirschm¨uller、以下の結論を評価するコストを計算する機能を実行します。

国勢調査ショーローカルおよびグローバルなステレオマッチング方法で最高の総合的な結果

国勢調査は考えました:

点の左のための\(\} P = {VECはI_} {(X、Y)\の左)、視差レベル\(D \)の下で、\(国勢調査C_ {}(\ VEC {P}、D )\)左の中点として定義される\ \(\ VEC {P} )全体近傍ウィンドウの中央の右側中点におけるセンサスコード、中心として(\ \ VEC {PD} = I_ {右} (XDの、Y)\)符号化されたセンサス隣接ウィンドウ間のハミング距離は、https://blog.csdn.net/qq_40313712/article/details/86349363は比較的簡単に説明プロファイルです。

センサス利点 - 現在地点近傍の画素点の相対値との関係及びそれらをコードするが、ノイズに対してロバストであり、異常値が導入された歪み

センサスは、輝度値そのもの以外の画素強度の相対的順序で局所的な画像構造をコードし、したがってによる放射の変化と画像ノイズに外れ値を許容します

- 不十分国勢調査区別できない近傍点と現在の点のような、地域に類似している:反復テクスチャシーン。

しかし、この資産はまた、反復または類似の局所構造を有する画像領域におけるマッチングの曖昧さを導入する可能性があります。

問題を解決するために国勢調査は、ADと一緒に使用するために提案しました:

次のようにADが定義されています。

\ [C_ {AD}(\ VEC {P}、D)= \ FRAC {1}、{3} \ sum_ {iは= R、G、B} | I_I ^ {左}(\ VEC {P}) - I_I ^ {右}(\ VEC {PD})| \タグ{1} \]

次のようにAD国勢調査で定義されました:

\ [C_ {収入} = \のRho(C_ {お金}(\ VEC {P} D)\ lambda_ {お金})+ \のRho(C_ {AD}(\ VEC {P} D)\ {})\タグ{2} \にlambda_]

ここで、\(\のRho(C、\ラムダ)\)は次のように定義されます。

\(\ロー(C、\ラムダ)= 1- EXP( - \ FRAC {C} {\ラムダ})\タグ{3} \)

:以下の単純な比較

CBCA

キューブの価格はリファインプロセスを作ったとして、重合の検討を見ることができ、重合は後で視差計算上のノイズの影響を低減させるための伝説的で、CBCA名はクロスベースのコスト集約され、基本的にクロスタイプの窓の一種であります次のように平均値フィルタの考え方は次のとおりです。

として

図CBCAから2つの段階にまとめることができます。

  1. クロス窓建設
  2. ウィンドウ内の平均フィルタ

クロス窓建設

クロスウィンドウは、ウィンドウは現在のポイント間の距離の左境界上の上限と下限についてがあるだろう、クロスで、テキストを上下に「左腕」を、言う、そして右のも事実です。

各クロスポイントは、以下の重合を実装するためのコストを、独自のウィンドウを持つことになります。

今の質問は、垂直方向と水平方向の境界を決定する方法を、解決すべきクロス窓構造のコア問題があります。

利用可能なリソースを通じて、以下の情報を使用する必要がある場合があります

  • 現在の色点間と近傍距離の点D_C(\ VEC {P_1(\ I_I(\ VEC {P_1}) - I_I(|}、\ VEC {P})= MAX_ {iが= R、G、B} \ VEC {P})| \ )
  • 近傍距離の現在の点と点の間の間隔\(D_S(\ VEC {P_1 } \ VEC {P})= | \ VEC {P1} - \ VEC {P} | \)

次のようにいくつかの基準の現在のウィンドウクロス点近傍の点が定義されているかどうかを決定します。

  1. \(D_C(\ VEC {P_1} \ VEC {P})<\ tau_1 \)同时\(D_C(\ VEC {P_1} \ VEC {P_1} +(1、0))<\ tau_1 \)
  2. \(D_S(\開始{P_1} \場合{P})<L1 \)
  3. もし\(L2 <D_S(\ VEC {P_1} \ VEC {P})<L1 \) 満足しなければならない:\(D_C(\ P_1 VEC {}、\ VEC {P})<\ tau_2 \)

1是保证不跨边缘做聚合,需要当前点和邻域点之间的颜色距离小于\(\tau_1\),同时,该邻域点和它往外一点之间的颜色距离也要小于\(\tau_1\);

2以及3,是为了cover住无纹理场景足够的平滑性,通过设定一个较大的\(L_1\)来对无纹理场景保证有足够大的窗口,如果窗口半径大于预设的半径\(L2\),则需满足\(D_c(\vec{p_1}, \vec{p}) < \tau_2\)才可以。

窗口内的均值滤波

一些先验知识:

  • 均值滤波基于积分图来实现可以达到O(n)的复杂度,并实现radius-free;

  • 分离为一维均值滤波行列方向交替进行,会比直接算二维均值滤波快;

在上面构造好cross窗口后,构造代价立方体的积分图,根据上一步计算得到的窗口半径即可实现cross型窗口的代价聚合;

由于cross型窗口均值滤波并非常规均值滤波,在经历行列交替的一维滤波后,通常会存在条状artifacts,因此,便有了作者下边的这部分迭代操作:

  • 做4次迭代,一次迭代包含行方向和列方向;
  • 1,3次迭代先行后列
  • 2,4次迭代先列后行

引用一句作者的评价:

our improved method are presented in Figure 3, which shows that the enhanced cross construction rules and aggregation strategy can produce more accurate results in large textureless regions and near depth discontinuities.

​ 对于一个研究滤波起家的人来看,这简直就是传说中的保边平滑性嘛,哈哈

Scanline Optimization

扫描线优化是从SGM原文里边引用的,核心思想可借用SGM原文的公式来表述:

\[E(D)=\sum_\vec{p}(C(\vec{p}, D_p) + \sum_{\vec{q}\isin{N_p}}P1T[|D_p-D_q|=1]+\sum_{\vec{q}\isin{N_p}}P2T[|D_p-D_q|>1])\tag{4}\]

为了得到一个全局最优结果,通常会构建一个包含数据项和平滑项的能量函数,通过最小化能量函数值来求得最优视差解。代价立方体本身存在一个代价,对于邻域内的像素点和当前点视差相差1的点做P1的惩罚,大于1的点做P2的惩罚。因此,第一项即为数据项,后面两项则为平滑项。

但由于在立体匹配中,代价立方体维度都会很大,想要求解这个最优化问题,直接用传统方法,内存和耗时都会很大。于是,SGM原文提出可使用动态规划求出近似解,代价函数简化成了下式:

\[C_\vec{r}=C_1(\vec{p}, d) + min(C_\vec{r}(\vec{p}-\vec{r}, d), C_\vec{r}(\vec{p}-\vec{r}, d \pm 1) + P1, min_kC_\vec{r}(\vec{p} - \vec{r} , k) + P2) - min_kC_\vec{r}(\vec{p}-\vec{r}, k)\tag{5}\]

定义 \(D_1 = d_c(\vec{p}, \vec{p}-\vec{r})\)\(D_2 = D_c(\vec{pd}, \vec{pd}-\vec{r})\), 通过\(D_1\)\(D_2\)的值来控制\(P_1, P_2\)的值:

  1. \(P_1 = \Pi_1, P_2 = \Pi_2, if D_1 < \tau_{SO}, D_2 < \tau_{SO}\)
  2. \(P_1 = \Pi_1 / 4, P_2 = \Pi_2 / 4, if D_1 < \tau_{SO}, D_2 > \tau_{SO}\)
  3. \(P_1 = \Pi_1 / 4, P_2 = \Pi_2 / 4, if D_1 > \tau_{SO}, D_2 < \tau_{SO}\)
  4. \(P_1 = \Pi_1 / 10, P_2 = \Pi_2 / 10, if D_1 > \tau_{SO}, D_2 > \tau_{SO}\)

最终的代价立方体结果为: \(C_2(\vec{p}, d) = \frac{1}{4}\sum_\vec{r}C_\vec{r}(\vec{p}, d)\)

最终的视差图用WTA即可得到,即:对每个像素点,取代价最小的那个视差值作为当前点视差

Post-process & Refine

经由WTA计算得到的视差图通常在遮挡区域存在着无效视差,同时也会存在一些噪声点甚至是大面积出错的情况,作者用了以下几个模块来做refine:

  1. Outlier Detection

    • 这部分主要是基于左右视差图的一致性检测来提取出视差不准确区域,简单而粗暴的设一个阈值,左右图匹配点对应的左右视差大于某个阈值,则该点即为视差不准确点;

    • 视差不准确点可分为两种:1)遮挡点;2)误匹配点

    • 对于上述两种点的区分,作者使用的是SGM原文里的方法:
      1) 在极线上搜索,若在右视差图上找到相交的点,则该点为误匹配点

      2) 在极线上右视差图上没有搜索到相交的点,则该点为遮挡点

  2. Iterative Region Voting

    对于上一步检测出来的outlier,统计其cross窗口中可靠点的视差直方图\(H_\vec{p}\),分为\(d_{max}+1\)个bins,对于可靠点数最多的bin即为\(d_\vec{p}^*\),记所有可靠像素点数为\(S_\vec{p} = \sum_{d=0}^{d=d_{max}}H_\vec{p}(d)\),当\(H_\vec{p}\)满足以下条件时:

    \(S_\vec{p} > \tau_S, \frac{H_\vec{p}(d_\vec{p}^*)}{S_\vec{p}} > \tau_H\)

    outlier处的视差由\(d_\vec{p}^*\)替代,五次迭代后,错误区域会少很多

  3. Proper Interpolation

    经由上一步之后,错误点会少很多。这一步会对误匹配点&遮挡点区别对待;

    搜寻outliter周围最相近的16个方向上的可靠点;

    对于遮挡点,选取其中最小的视差最为其视差值;

    对于误匹配点,选取和其最相似的那个点的视差作为其视差值;

  4. Depth Discontinuity Adjustment

    Step 1: 检测视差图的边缘

    Step 2: 判断边界点两边点的代价值,如果低于当前点的代价值,则调整当前边界点的视差至边界两边的那个点

  5. Sub-pixel Enhancement

    ——基于quadratic polynomial interpolation的亚像素增强方法

画像-20200113230301596

后面再跟一个3x3的中值滤波

refine各个stage带来的收益:

实验

测试平台

PC with Core2Duo 2.20GHz CPU and NVIDIA GeForce GTX 480 graphics card

数据集

Middlebury

参数设置

性能

Tsukuba Venus Teddy Cones
CPU 2.5s 4.5s 15s 15s
GPU 0.016s 0.032s 0.095s 0.094s

tips

调参很重要

后记——SGBM OpenCV源码学习笔记

在opencv源码的位置:

opencv-4.0.0_src\opencv-4.0.0\modules\calib3d\src\stereosgbm.cpp

推荐博客:

https://blog.csdn.net/wwp2016/article/details/86080722

https://zhuanlan.zhihu.com/p/53060518

pipeline

pipeline很符合常规立体匹配pipeline:代价计算 -> 代价聚合 -> 视差计算 -> 视差后处理,和上面paper的逻辑极为相近,可以串起来做相关优化和尝试,所以把他们写在了一篇文档里。

函数调用与参数解析

SGBM opencv源码将上述pipeline封装为两个接口供外界调用:1)通过带参数设置的构造函数设置参数;2)算法核心;

    StereoSGBMImpl()
    {
        params = StereoSGBMParams();
    }

    StereoSGBMImpl( int _minDisparity, int _numDisparities, int _SADWindowSize,
                    int _P1, int _P2, int _disp12MaxDiff, int _preFilterCap,
                    int _uniquenessRatio, int _speckleWindowSize, int _speckleRange,
                    int _mode )
    {
        params = StereoSGBMParams( _minDisparity, _numDisparities, _SADWindowSize,
                                   _P1, _P2, _disp12MaxDiff, _preFilterCap,
                                   _uniquenessRatio, _speckleWindowSize, _speckleRange,
                                   _mode );
        // _minDisparity: 最小视差,默认为0; 对于实际应用中可能存在负视差的场景,可适当是设置为负视差,e.g. -3;
        
        // _numDisparities: 视差层级,需设置为16的倍数,默认为16;
        //                注意:输出视差图的视差层级为(16 * _minDisparity + _numDisparities);
        
        // _SADWindowSize: SAD窗口直径,代价聚合部分,形同boxfilter的窗口直径,默认为5;
        
        // _P1: 邻域点视差和当前点相差1的惩罚量,即上面eq4的P1,默认为2;
        
        // _P2: 邻域点视差和当前点相差大于1的惩罚量,即上面eq4的P2, 默认:max(params.P2 > 0 ? params.P2 : 5, P1+1);
        
        // _disp12MaxDiff: LR Check中不匹配点检测的阈值,默认:1;
        
        // _preFilterCap: SGBM 代价计算是基于BT特征的,这个值是将每个匹配点对的匹配代价值抑制在_preFilterCap - 2 * _preFilterCap范围内;
        //                 注意:该值会影响到匹配代价的数量级,P1, P2的调参需要和该值协同修改;
        //                 BT的大概思想:
        //                 if k < 256*4 - _preFilterCap, 则CC = _preFilterCap;
        //                 if 256*4 - _preFilterCap < k < 256*4 + _preFilterCap, 则CC = k - 256*4 + _preFilterCap;
        //                 if k > 256*4 + _preFilterCap, 则CC = 2 * _preFilterCap;
        
        // _uniquenessRatio: 唯一匹配检测阈值。要求除了bestDisp前后各一个视差之外,其余视差值对应的S必须大于minS * 1.x,默认为10, 大于1.1;
        
        // _speckleWindowSize & _speckleRange: filterSpeckle的参数,用于对视差对做斑点去除的函数;
        
        // _mode: 
        //       - MODE_SGBM_3WAY:
        //       - MODE_HH4:
        //       - MODE_HH:默认模式
    }

    void compute( InputArray leftarr, InputArray rightarr, OutputArray disparr ) CV_OVERRIDE
    {
        CV_INSTRUMENT_REGION();

        Mat left = leftarr.getMat(), right = rightarr.getMat();
        CV_Assert( left.size() == right.size() && left.type() == right.type() &&
                   left.depth() == CV_8U );

        disparr.create( left.size(), CV_16S );
        Mat disp = disparr.getMat();

        if(params.mode==MODE_SGBM_3WAY)
            computeDisparity3WaySGBM( left, right, disp, params, buffers, num_stripes );
        else if(params.mode==MODE_HH4)
            computeDisparitySGBM_HH4( left, right, disp, params, buffer );
        else
            computeDisparitySGBM( left, right, disp, params, buffer );

        medianBlur(disp, disp, 3);

        if( params.speckleWindowSize > 0 )
            filterSpeckles(disp, (params.minDisparity - 1)*StereoMatcher::DISP_SCALE, params.speckleWindowSize,
                           StereoMatcher::DISP_SCALE*params.speckleRange, buffer);
    }

一些代码细节

SGBM的三个模式

  1. MODE_SGBM_3WAY
  2. MODE_SGBM_HH
  3. MODE_SGBM_HH4

SGBM的内存管理

核心算法思想

  1. 基于BT的代价计算

    ——Birchfield-Tomasi metric

    from BT org paper

    最初是在A Pixel Dissimilarity Measure That Is Insensitive to Image Sampling中由Stan Birchfield and Carlo Tomasi提出,旨在提升相似性度量对image sampling的鲁棒,BT在该paper的Section 2中提出了BT的基本思路,在Section 3从理论上和实验中证明了该算法的有效性,具体的内容没有很清楚,但对BT的主要思想做了下梳理,内容如下:

    对于两幅连续的立体对\(I_L(x_L)\), \(I_R(x_R)\),经过硬件处理、图像采样后,左图和右图匹配点的灰度值可能会出现一些偏差,而BT的思想就是基于简单的线性插值,搜索\(x+1, x-1\)\(I_{min},I_{max}\)来协同表征当前位置下左右视图的相似度:

画像-20200121121127286

数学表达如下:

\(I_R^- \equiv \hat{I_R}(x_R - \frac{1}{2}) = \frac{1}{2}(I_R(x_R) + I_R(x_R - 1))\)\(I_R^+ \equiv \hat{I_R}(x_R + \frac{1}{2}) = \frac{1}{2}(I_R(x_R) + I_R(x_R + 1))\)

\(I_{min} = \min{I_R^-, I_R^+, I_R(x_R)}\), \(I_{max} = \max{I_R^-, I_R^+, I_R(x_R)}\)

则コスト为\(\バー{D}(X_L、X_R、I_L、I_R)= \最大{\ {0、I_L(X_L) - } {maxのI_、I_ {分} - I_L(X_L)\}} \ )

ショー具体的な例以下AD対BT:

画像-20200121122743104

BTのSGBM

  1. スキャンラインの最適化最適化のコストに基づいて、

    - 近所の重合至るまでの方法ポイントのコスト

コールデモ

#include "stdafx.h"
#include "opencv2/opencv.hpp
using namespace std;
using namespace cv;
int _tmain(int argc, _TCHAR* argv[])
{
    Mat left = imread("imgL.jpg", IMREAD_GRAYSCALE);
    Mat right = imread("imgR.jpg", IMREAD_GRAYSCALE);
    Mat disp;
    int mindisparity = 0;
    int ndisparities = 64;  
    int SADWindowSize = 11; 
    //SGBM
    cv::Ptr<cv::StereoSGBM> sgbm = cv::StereoSGBM::create(mindisparity, ndisparities, SADWindowSize);
    int P1 = 8 * left.channels() * SADWindowSize* SADWindowSize;
    int P2 = 32 * left.channels() * SADWindowSize* SADWindowSize;
    sgbm->setP1(P1);
    sgbm->setP2(P2);
    sgbm->setPreFilterCap(15);
    sgbm->setUniquenessRatio(10);
    sgbm->setSpeckleRange(2);
    sgbm->setSpeckleWindowSize(100);
    sgbm->setDisp12MaxDiff(1);
    //sgbm->setMode(cv::StereoSGBM::MODE_HH);
    sgbm->compute(left, right, disp);
    disp.convertTo(disp, CV_32F, 1.0 / 16);                //除以16得到真实视差值
    Mat disp8U = Mat(disp.rows, disp.cols, CV_8UC1);       //显示
    normalize(disp, disp8U, 0, 255, NORM_MINMAX, CV_8UC1);
    imwrite("results/SGBM.jpg", disp8U);
    return 0;
}

おすすめ

転載: www.cnblogs.com/nico-1729/p/12233586.html