【视觉-立体视觉】全局匹配算法SGBM实现(含动态规划DP)详解

转载于http://www.opencv.org.cn/forum.php?mod=viewthread&tid=23854

最近一直在学习SGBM算法,作为一种全局匹配算法,立体匹配的效果明显好于局部匹配算法,但是同时复杂度上也要远远大于局部匹配算法。算法主要是参考Stereo Processing by Semiglobal Matching and Mutual Information,里面有讲完整的算法实现。
OpenCV中实际上是提供了SGBM类进行SGBM算法的实现。
#include <highgui.h>
#include <cv.h>
#include <cxcore.h>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
        
    IplImage * img1 = cvLoadImage(&quot;left.png&quot;,0);
    IplImage * img2 = cvLoadImage(&quot;right.png&quot;,0);
    cv::StereoSGBM sgbm;
        int SADWindowSize = 9;
        sgbm.preFilterCap = 63;
        sgbm.SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 3;
        int cn = img1->nChannels;
        int numberOfDisparities=64;
        sgbm.P1 = 8*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
        sgbm.P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
        sgbm.minDisparity = 0;
        sgbm.numberOfDisparities = numberOfDisparities;
        sgbm.uniquenessRatio = 10;
        sgbm.speckleWindowSize = 100;
        sgbm.speckleRange = 32;
        sgbm.disp12MaxDiff = 1;
        Mat disp, disp8;
        int64 t = getTickCount();
        sgbm((Mat)img1, (Mat)img2, disp);
        t = getTickCount() – t;
        cout<<&quot;Time elapsed:&quot;<<t*1000/getTickFrequency()<<endl;
        disp.convertTo(disp8, CV_8U, 255/(numberOfDisparities*16.));
        
        namedWindow(&quot;left&quot;, 1);
        cvShowImage(&quot;left&quot;, img1);
        namedWindow(&quot;right&quot;, 1);
        cvShowImage(&quot;right&quot;, img2);
        namedWindow(&quot;disparity&quot;, 1);
        imshow(&quot;disparity&quot;, disp8);
        waitKey();
        imwrite(&quot;sgbm_disparity.png&quot;, disp8);   
    cvDestroyAllWindows();
        return 0;
}
贴出效果:

//深度图

但是仅仅用OpenCV自带的SGBM类来实现并不能满足,我还是希望能够自己实现该算法,然后最关键是移植到FPGA上去。

于是我尝试自已去写SGBM的代码,论文中提高Dynamic programming算法,实际上SGBM中也用到了多方向的Dynamic programming,但是我目前只是实现了单方向的DP。

//引入概率公式

//引入CBT的插值方法
//加上相邻匹配点位置之间的限制
#include <cstdio>
#include <cstring>
#include <iostream>
#include<cv.h>
#include<highgui.h>
#include <cmath>

using namespace std;
const int Width =  1024;
const int Height = 1024;
int Ddynamic[Width][Width];

//使用钟形曲线作为匹配概率,差值越小则匹配的概率越大,最终的要求是使匹配的概率最大,概率曲线使用matlab生成

//均方差30
//int Probability[256] = {
//   255, 255, 254, 252, 250, 247, 244, 240, 235, 230, 225, 219, 213, 206, 200, 192, 185, 178, 170, 162, 
//   155, 147, 139, 132, 124, 117, 110, 103, 96, 89, 83, 77, 71, 65, 60, 55, 50, 46, 42, 38, 35, 31, 28, 
//   25, 23, 20, 18, 16, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 
//   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
//   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
//   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
//   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
//   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
//   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
//};

//均方差 5
int Probability[256] = {
    255, 250, 235, 213, 185, 155, 124, 96, 71, 50, 35, 23, 14, 9, 5, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

int  main()
{  
  
    IplImage * leftImage = cvLoadImage(&quot;l2.jpg&quot;,0);
    IplImage * rightImage = cvLoadImage(&quot;r2.jpg&quot;,0);

    //IplImage * leftImage = cvLoadImage(&quot;left.bmp&quot;,0);                           
    //IplImage * rightImage = cvLoadImage(&quot;right.bmp&quot;,0);

    int imageWidth = leftImage->width;
    int imageHeight =leftImage->height;

    IplImage * DPImage = cvCreateImage(cvGetSize(leftImage),leftImage->depth,1);
    IplImage * effectiveImage = cvCreateImage(cvGetSize(leftImage),leftImage->depth,1);
    IplImage * FilterImage = cvCreateImage(cvGetSize(leftImage),leftImage->depth,1);

    unsigned char * pPixel = NULL;
    unsigned char  pixel;
    unsigned char * pPixel2 = NULL;
    unsigned char  pixel2;
    for (int i = 0; i< imageHeight;i++)
    {
        for (int j =0; j < imageWidth;j++ )
        {
            pPixel = (unsigned char *)DPImage->imageData + i*DPImage->widthStep + j;
            *pPixel = 0;
            pPixel = (unsigned char *)effectiveImage->imageData + i*effectiveImage->widthStep + j;
            *pPixel = 0;
        }
    }

    cvNamedWindow(&quot;Left&quot;,1);
    cvNamedWindow(&quot;Right&quot;,1);
    cvNamedWindow(&quot;Depth&quot;,1);
    cvNamedWindow(&quot;effectiveImage&quot;,1);

    cvShowImage(&quot;Left&quot;,leftImage);
    cvShowImage(&quot;Right&quot;,rightImage);

    int minD = 0;
    int maxD = 31;
    //假设图像是经过矫正的,那么每次都只是需要搜搜同一行的内容
    int max12Diff = 10;
   
    for (int i = 0;i < imageWidth;i++)
    {
        Ddynamic[0] = 0;
        Ddynamic[0] = 0;
    }

    unsigned char * pLeftPixel  = NULL;
    unsigned char * pRightPixel = NULL;
    unsigned char leftPixel = 0;
    unsigned char leftMax = 0;
    unsigned char leftMin = 0;
    unsigned char tempLeft1 = 0;
    unsigned char tempLeft2 = 0;
    unsigned char rightPixel =0;
    unsigned char difPixel = 0;
    int m,n,l;

    int t1 = clock();
    for (int i = 0 ; i < imageHeight;i++)
    {
        for (int j = 0; j<imageWidth;j++)
        {
            for (int k = j + minD; k <= j + maxD;k++)
            {
                if (k <= 0 || k >= imageWidth -1)
                {

                }else {
                    pLeftPixel = (unsigned char*)leftImage->imageData + i*leftImage->widthStep + k;
                    pRightPixel= (unsigned char*)rightImage->imageData+i*rightImage->widthStep + j;
                    leftPixel  = *pLeftPixel;
                    rightPixel = *pRightPixel;
                    leftPixel  = *pLeftPixel;
                    tempLeft1 = (*pLeftPixel +(*(pLeftPixel -1)))/2;
                    tempLeft2 = (*pLeftPixel +(*(pLeftPixel +1)))/2;

                    leftMax = max(max(tempLeft1,tempLeft2),leftPixel);
                    leftMin = min(min(tempLeft1,tempLeft2),leftPixel);
                    difPixel = max(max(rightPixel – leftMax,leftMin – rightPixel),0);

                    if (difPixel <= max12Diff)
                    {
                        Ddynamic[j + 1][k + 1] = Ddynamic[j][k] + Probability[difPixel]; 
                    }else if (Ddynamic[j][k+1] > Ddynamic[j+1][k])
                    {
                        Ddynamic[j + 1][k + 1] = Ddynamic[j][k+1];
                    }else{
                        Ddynamic[j+1][k+1] = Ddynamic[j+1][k];
                    }
   
                    //cout<<Ddynamic[j +1][k+1]<<&quot;  &quot;;
                }
               
            }
             //cout<<&quot;\n&quot;;
        }
        //逆向搜索,找出最佳路径
         m = imageWidth;
         n = imageWidth;
         int m2 = imageWidth, n2 = imageWidth;
         l = Ddynamic[imageWidth][imageWidth];
        while( m >= 1 && n >= 1)
        {
            if ((m2 == m + 1 && n2 >= n +1) || ( m2 > m +1 && n2 == n + 1))
            {
                pPixel = (unsigned char *)DPImage->imageData + i*DPImage->widthStep + m;
                *pPixel = (n-m)*10;
                //标记有效匹配点
                pPixel = (unsigned char *)effectiveImage->imageData + i*effectiveImage->widthStep + m;
                *pPixel = 255;

                m2 = m;
                n2 = n;

            }
            if (Ddynamic[m-1][n-1] >= Ddynamic[m][n -1] && Ddynamic[m-1][n -1] >= Ddynamic[m-1][n])
            {

                m–; 
                n–;
            }else if (Ddynamic[m-1][n] >= Ddynamic[m][n -1] && Ddynamic[m-1][n] >= Ddynamic[m-1][n -1])
            { 
                m–;
            }
            else
            { 
                n–;
            }
           
        }

       //cvWaitKey(0);
    }
    int t2 = clock();
    cout<<&quot;dt: &quot;<<t2-t1<<endl;

    //显示Ddynamic最后一行
   /* for (int i = 0 ;i<= imageWidth;i++)
    {
        for (int j= 0; j<= imageWidth;j++)
        {
           cout<<Ddynamic[j]<<&quot;  &quot;;
        }
        cout<<&quot;\n\n&quot;;
    }*/

    //refine the depth image  7*7中值滤波
    //统计未能匹配点的个数
    int count = 0;
    for (int i = 0 ;i< imageHeight;i++)
    {
        for (int j= 0; j< imageWidth;j++)
        {
            pPixel = (unsigned char *)effectiveImage->imageData + i*effectiveImage->widthStep + j;
            pixel = *pPixel;
            if (pixel == 0)
            {
                count++;
            }
        }
    }
    
    cout<<&quot;Count:  &quot;<<count<<&quot;  &quot;<<(double)count/(imageWidth*imageHeight)<<endl;
    cvShowImage(&quot;Depth&quot;,DPImage);
    cvShowImage(&quot;effectiveImage&quot;,effectiveImage);
   // cvWaitKey(0);

    FilterImage = cvCloneImage(DPImage);

    //7*7中值滤波
    int halfMedianWindowSize = 3;
    int medianWindowSize = 2*halfMedianWindowSize + 1;
    int medianArray[100] = {0};
    count = 0;
    int temp = 0;
    int medianVal = 0;

    for (int i = halfMedianWindowSize + 1 ;i< imageHeight – halfMedianWindowSize;i++)
    {
        for (int j = halfMedianWindowSize; j< imageWidth – halfMedianWindowSize;j++)
        {
            pPixel = (unsigned char *)effectiveImage->imageData + i*effectiveImage->widthStep + j;
            pixel = *pPixel;
            if (pixel == 0)
            {
                count = 0;
                for (int m = i – halfMedianWindowSize ; m <= i + halfMedianWindowSize ;m++)
                {
                    for (int n = j – halfMedianWindowSize; n <= j + halfMedianWindowSize ;n++)
                    {
                        pPixel2 = (unsigned char *)DPImage->imageData + m*DPImage->widthStep + n;
                        pixel2 = *pPixel2;
                        if (pixel2 != 0)
                        {
                             medianArray[count] = pixel2;
                             count++;
                        }
       
                    }
                    //排序
                    for (int k = 0; k< count;k++)
                    {
                        for (int l = k + 1; l< count;l++)
                        {
                            if (medianArray[l] < medianArray[l-1] )
                            {
                                temp = medianArray[l];
                                medianArray[l] = medianArray[l-1];
                                medianArray[l-1] = temp;
                            }
                        }
                    }
                    medianVal = medianArray[count/2];
                    pPixel = (unsigned char *)FilterImage->imageData + i*DPImage->widthStep + j;
                    *pPixel = medianVal;
                }

            }
        }
    }
    cvShowImage(&quot;Depth&quot;,DPImage);
    cvShowImage(&quot;effectiveImage&quot;,effectiveImage);
    cvShowImage(&quot;Filter&quot;,FilterImage);

    cvSaveImage(&quot;depth.jpg&quot;,DPImage);
    cvSaveImage(&quot;Filter.jpg&quot;,FilterImage);
    cvSaveImage(&quot;effective.jpg&quot;,effectiveImage);

    cvWaitKey(0);
    return 0;
}
//效果

但是论文中多方向的DP却看了好几天都没有头绪该怎么写?因此这里贴出进展,希望各位大侠能够帮帮忙,共同学习。

opencvSGBM半全局立体匹配算法的研究

转载请说明出处:http://blog.csdn.net/zhubaohua_bupt/article/details/51866700

自己在stereosgbm.cpp的最后加了一个把灰度图像显示成伪彩色图像的函数,为的是更好的观察视差图。

[html] 
view plain
 copy

  1. myStereoSGBM::GenerateFalseMap(cv::Mat &src, cv::Mat &disp)  

下面分别给出 main.cpp、stereosgbm.h(从calib3d.hpp里面提取出来,opencv版本2.4.9)、stereosgbm.cpp。配置完opencv环境后即可使用。有兴趣的朋友可以研究一下代码。

main.cpp

[html] 
view plain
 copy

  1. #include”sgbm.h”  
  2. int main()  
  3. {  
  4.       
  5.     Mat img111 =  imread(“E:/matchpic/testbanch_data/raindeer_left.pgm”, 0);  
  6.     Mat img222 = imread(“E:/matchpic/testbanch_data/raindeer_right.pgm”, 0);      
  7.     imshow(“left”,img111);  
  8.     waitKey(10);  
  9.   
  10. cv::myStereoSGBM sgbm;  
  11.       
  12. int SADWindowSize = 5;  
  13. sgbm.preFilterCap = 63 ;   
  14. sgbm.SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 3;  
  15. int cn = img111.channels();  
  16. int numberOfDisparities=128;  
  17. sgbm.P1 = 8*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;  
  18. sgbm.P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;   
  19. sgbm.minDisparity = 0;  
  20. sgbm.numberOfDisparities = numberOfDisparities;  
  21. sgbm.uniquenessRatio = 10;  
  22. sgbm.speckleWindowSize =100;  
  23. sgbm.speckleRange = 10;  
  24. sgbm.disp12MaxDiff = 1;  
  25. Mat disp;  
  26. sgbm( img111, img222,disp );//disp经过处理输出的是short类型  
  27. Mat disp8,color(disp.size(),CV_8UC3);  
  28.  disp.convertTo(disp8, CV_8U, 255/(numberOfDisparities*16.));//转化成uchar显示  
  29.   
  30. sgbm.GenerateFalseMap(disp8,color);  
  31. imshow(“”,color);  
  32. imshow(“”,disp8);  
  33. waitKey(10);  
  34. }   

stereosgbm.h

[html] 
view plain
 copy

  1. <pre name=“code” class=“html”><pre name=“code” class=“html”>#include”opencv2/opencv.hpp”  
  2. #include<iostream>  
  3. using namespace cv;  
  4. using namespace std;  
  5. namespace cv  
  6. {   
  7. class myStereoSGBM  
  8. {  
  9. public:  
  10.     myStereoSGBM( int _minDisparity=0, int _numDisparities=0, int _SADWindowSize=0,  
  11. int _P1=0, int _P2=0, int _disp12MaxDiff=0, int _preFilterCap=0,   
  12. int _uniquenessRatio=0, int _speckleWindowSize=0, int _speckleRange=0,   
  13. bool _fullDP=false ) ;  
  14. //  myStereoSGBM();  
  15.     virtual void operator()(cv::InputArray _left, InputArray _right, OutputArray _disp ) ;  
  16.     void GenerateFalseMap(cv::Mat &src, cv::Mat &disp);  
  17.     ~myStereoSGBM() ;  
  18.   
  19.     enum{DISP_SHIFT=4,DISP_SCALE=(1<<DISP_SHIFT)};  
  20.     int minDisparity;  
  21.     int numberOfDisparities;  
  22.     int SADWindowSize;   
  23. int P1; int P2;  
  24. int disp12MaxDiff;  
  25. int preFilterCap;  
  26.   
  27. int uniquenessRatio;  
  28. int speckleWindowSize;  
  29. int speckleRange;  
  30. bool fullDP ;  
  31. protected :  
  32.     Mat buffer;  
  33. };  
  34. void filterSpeckles( InputOutputArray _img, double _newval, int maxSpeckleSize, double _maxDiff, InputOutputArray __buf ) ;  
  35. void validateDisparity( InputOutputArray _disp, InputArray _cost, int minDisparity, int numberOfDisparities, int disp12MaxDiff ) ;  
  36. CvRect cvGetValidDisparityROI( CvRect roi1, CvRect roi2, int minDisparity, int numberOfDisparities, int SADWindowSize ) ;  
  37. //void cvValidateDisparity( CvArr* _disp, const CvArr* _cost, int minDisparity, int numberOfDisparities, int disp12MaxDiff ) ;  
  38. }  

stereosgbm.cpp

[html] 
view plain
 copy

  1. <pre name=“code” class=“html”>   
  2.   
  3. /*M/////////////////////////////////////////////////////////////////////////////////  
  4.   
  5. //////   
  6. //   
  7. // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.   
  8. //   
  9. // By downloading, copying, installing or using the software you agree to this   
  10.   
  11. license.   
  12. // If you do not agree to this license, do not download, install,   
  13. // copy or use the software.   
  14. //   
  15. //   
  16. // License Agreement   
  17. // For Open Source Computer Vision Library   
  18. //   
  19. // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.   
  20. // Copyright (C) 2009, Willow Garage Inc., all rights reserved.   
  21. // Third party copyrights are property of their respective owners.   
  22. //   
  23. // Redistribution and use in source and binary forms, with or without modification,   
  24. // are permitted provided that the following conditions are met:   
  25. //   
  26. // * Redistribution’s of source code must retain the above copyright notice,   
  27. // this list of conditions and the following disclaimer.   
  28. //   
  29. // * Redistribution’s in binary form must reproduce the above copyright notice,   
  30. // this list of conditions and the following disclaimer in the documentation   
  31. // and/or other materials provided with the distribution.   
  32. //   
  33. // * The name of the copyright holders may not be used to endorse or promote   
  34.   
  35. products   
  36. // derived from this software without specific prior written permission.   
  37. //   
  38. // This software is provided by the copyright holders and contributors “as is” and   
  39. // any express or implied warranties, including, but not limited to, the implied   
  40. // warranties of merchantability and fitness for a particular purpose are   
  41.   
  42. disclaimed.   
  43. // In no event shall the Intel Corporation or contributors be liable for any direct,   
  44. // indirect, incidental, special, exemplary, or consequential damages   
  45. // (including, but not limited to, procurement of substitute goods or services;   
  46. // loss of use, data, or profits; or business interruption) however caused   
  47. // and on any theory of liability, whether in contract, strict liability,   
  48. // or tort (including negligence or otherwise) arising in any way out of   
  49. // the use of this software, even if advised of the possibility of such damage.   
  50. //   
  51. //M*/   
  52. /*   
  53. This is a variation of   
  54. “Stereo Processing by Semiglobal Matching and Mutual Information”   
  55. by Heiko Hirschmuller.   
  56. We match blocks rather than individual pixels, thus the algorithm is called   
  57. SGBM (Semi-global block matching)   
  58. */   
  59. //#include “precomp.hpp”   
  60.   
  61. #include <limits.h>   
  62. #include”sgbm.h”  
  63. #include<fstream>  
  64. namespace cv   
  65. {   
  66. typedef unsigned char PixType;   
  67. typedef short CostType;   
  68. typedef short DispType;   
  69. enum { NR = 16 , NR2 = NR/2 }; //NR=16  
  70. //myStereoSGBM::myStereoSGBM()   
  71. //{   
  72. //minDisparity = numberOfDisparities = 0;   
  73. //SADWindowSize = 0;   
  74. //P1 = P2 = 0;   
  75. //disp12MaxDiff = 0;   
  76. //preFilterCap = 0;   
  77. //uniquenessRatio = 0;   
  78. //speckleWindowSize = 0;   
  79. //speckleRange = 0;   
  80. //fullDP = false;   
  81. //}   
  82. myStereoSGBM::myStereoSGBM( int _minDisparity, int _numDisparities, int _SADWindowSize, int _P1, int _P2, int _disp12MaxDiff,  
  83.                        int _preFilterCap, int _uniquenessRatio, int _speckleWindowSize, int _speckleRange, bool _fullDP )  
  84.   
  85. {   
  86. minDisparity = _minDisparity;   
  87. numberOfDisparities = _numDisparities;   
  88. SADWindowSize = _SADWindowSize;   
  89. P1 = _P1;   
  90. P2 = _P2;   
  91. disp12MaxDiff = _disp12MaxDiff;   
  92. preFilterCap = _preFilterCap;   
  93. uniquenessRatio = _uniquenessRatio;   
  94. speckleWindowSize = _speckleWindowSize;   
  95. speckleRange = _speckleRange;   
  96. fullDP = _fullDP;   
  97. }   
  98. myStereoSGBM::~myStereoSGBM()   
  99. {   
  100. }   
  101. /*   
  102. For each pixel row1[x], max(-maxD, 0) <= minX <= x < maxX <= width – max(0, -minD),   
  103. and for each disparity minD<=d<maxD the function   
  104. computes the cost (cost[(x-minX)*(maxD – minD) + (d – minD)]), depending on the   
  105. difference between row1[x] and row2[x-d]. The subpixel algorithm from   
  106. “Depth Discontinuities by Pixel-to-Pixel Stereo” by Stan Birchfield and C. Tomasi //亚像素插值  
  107. is used, hence the suffix BT.   
  108. the temporary buffer should contain width2*2 elements   
  109. */   
  110. static void calcPixelCostBT( const Mat& img1, const Mat& img2, int y, int minD, int maxD, CostType* cost,   
  111.                             PixType* buffer, const PixType* tab, int tabOfs, int )   
  112.                               
  113. {   
  114.       
  115. int x, c, width = img1.cols, cn = img1.channels();   
  116. int minX1 = max(-maxD, 0), maxX1 = width + min(minD, 0);   
  117. int minX2 = max(minX1 – maxD, 0), maxX2 = min(maxX1 – minD, width);   
  118. int D = maxD – minD, width1 = maxX1 – minX1, width2 = maxX2 – minX2;   
  119. const PixType *row1 = img1.ptr<PixType>(y), *row2 = img2.ptr<PixType>(y);   
  120. PixType *prow1 = buffer + width2*2, *prow2 = prow1 + width*cn*2;   
  121. tab += tabOfs;   
  122. for( c = 0; c < cn*2; c++ )   
  123. {   
  124. prow1[width*c] = prow1[width*c + width-1] = prow2[width*c] = prow2[width*c + width-1] = tab[0];   
  125. }   
  126. int n1 = y > 0 ? -(int)img1.step : 0, s1 = y < img1.rows-1 ? (int)img1.step : 0;   
  127. int n2 = y > 0 ? -(int)img2.step : 0, s2 = y < img2.rows-1 ? (int)img2.step : 0;   
  128. if( cn == 1 )   
  129.     {   
  130.           
  131.         for( x = 1; x < width-1; x++ )   
  132.         {   
  133.           prow1[x] = tab[(row1[x+1] – row1[x-1])*2 + row1[x+n1+1] – row1[x+n1-1] + row1[x+s1+1] – row1[x+s1-1]];   
  134.            
  135.           prow2[width-1-x] = tab[(row2[x+1] – row2[x-1])*2 + row2[x+n2+1] – row2[x+n2-1] +  row2[x+s2+1] – row2[x+s2-1]];   
  136.            prow1[x+width] = row1[x];   
  137.            prow2[width-1-x+width] = row2[x];   
  138.         }   
  139.     }   
  140. else   
  141. {   
  142.     for( x = 1; x < width-1; x++ )   
  143.     {   
  144.     prow1[x] = tab[(row1[x*3+3] – row1[x*3-3])*2 + row1[x*3+n1+3] – row1[x*3+n1-3] + row1[x*3+s1+3] – row1[x*3+s1-3]];   
  145.     prow1[x+width] = tab[(row1[x*3+4] – row1[x*3-2])*2 + row1[x*3+n1+4] – row1[x*3+n1-2] + row1[x*3+s1+4] – row1[x*3+s1-2]];   
  146.     prow1[x+width*2] = tab[(row1[x*3+5] – row1[x*3-1])*2 + row1[x*3+n1+5] – row1[x*3+n1-1] + row1[x*3+s1+5] – row1[x*3+s1-1]];   
  147.     prow2[width-1-x] = tab[(row2[x*3+3] – row2[x*3-3])*2 + row2[x*3+n2+3] – row2[x*3+n2-3] + row2[x*3+s2+3] – row2[x*3+s2-3]];   
  148.     prow2[width-1-x+width] = tab[(row2[x*3+4] – row2[x*3-2])*2 + row2[x*3+n2+4] – row2[x*3+n2-2] + row2[x*3+s2+4] – row2[x*3+s2-2]];   
  149.     prow2[width-1-x+width*2] = tab[(row2[x*3+5] – row2[x*3-1])*2 + row2[x*3+n2+5] – row2[x*3+n2-1] + row2[x*3+s2+5] – row2[x*3+s2-1]];   
  150.   
  151.     prow1[x+width*3] = row1[x*3];   
  152.     prow1[x+width*4] = row1[x*3+1];   
  153.     prow1[x+width*5] = row1[x*3+2];   
  154.    
  155.     prow2[width-1-x+width*3] = row2[x*3];   
  156.     prow2[width-1-x+width*4] = row2[x*3+1];   
  157.     prow2[width-1-x+width*5] = row2[x*3+2];   
  158.     }   
  159. }   
  160. memset( cost, 0, width1*D*sizeof(cost[0]) );   
  161.   
  162. buffer minX2;   
  163. cost minX1*D + minD; // simplify the cost indices inside the loop   
  164.   
  165. /*#if CV_SSE2   
  166. volatile bool useSIMD = checkHardwareSupport(CV_CPU_SSE2);   
  167. #endif*/   
  168. #if 1   
  169. for( c = 0; c < cn*2; c++, prow1 += width, prow2 += width )   
  170. {   
  171. int diff_scale = c < cn ? 0 : 2; //对预处理之后的图像和原图像生成的代价加权相加        C=Cpreprocess+1/4*C原图  
  172. // precompute   
  173. // v0 = min(row2[x-1/2], row2[x], row2[x+1/2]) and   
  174. // v1 = max(row2[x-1/2], row2[x], row2[x+1/2]) and   
  175. for( x = minX2; x < maxX2; x++ )   
  176.         {   
  177.             int v = prow2[x];   
  178.             int vl = x > 0 ? (v + prow2[x-1])/2 : v;   
  179.             int vr = x < width-1 ? (v + prow2[x+1])/2 : v;   
  180.             int v0 = min(vl, vr); v0 = min(v0, v);   
  181.             int v1 = max(vl, vr); v1 = max(v1, v);   
  182.             buffer[x] = (PixType)v0;   
  183.             buffer[x + width2] = (PixType)v1;   
  184.         }   
  185.   
  186. for( x = minX1; x < maxX1; x++ )   
  187.   {   
  188.             int u = prow1[x];   
  189.             int ul = x > 0 ? (u + prow1[x-1])/2 : u;   
  190.             int ur = x < width-1 ? (u + prow1[x+1])/2 : u;   
  191.             int u0 = min(ul, ur); u0 = min(u0, u);   
  192.             int u1 = max(ul, ur); u1 = max(u1, u);   
  193. //#if CV_SSE2   
  194. //if( useSIMD )   
  195. //{   
  196. //__m128i _u = _mm_set1_epi8((char)u), _u0 = _mm_set1_epi8((char)u0);   
  197. //__m128i _u1 = _mm_set1_epi8((char)u1), z = _mm_setzero_si128();   
  198. //__m128i ds = _mm_cvtsi32_si128(diff_scale);   
  199. //for( int d = minD; d < maxD; d += 16 )   
  200. //{   
  201. //__m128i _v = _mm_loadu_si128((const __m128i*)(prow2 + width-x-1 + d));   
  202. //__m128i _v0 = _mm_loadu_si128((const __m128i*)(buffer + width-x-1 + d));   
  203. //__m128i _v1 = _mm_loadu_si128((const __m128i*)(buffer + width-x-1 + d + width2));   
  204. //__m128i c0 = _mm_max_epu8(_mm_subs_epu8(_u, _v1), _mm_subs_epu8(_v0, _u));   
  205. //__m128i c1 = _mm_max_epu8(_mm_subs_epu8(_v, _u1), _mm_subs_epu8(_u0, _v));   
  206. //__m128i diff = _mm_min_epu8(c0, c1);   
  207. //c0 = _mm_load_si128((__m128i*)(cost + x*D + d));   
  208. //c1 = _mm_load_si128((__m128i*)(cost + x*D + d + 8));   
  209. //_mm_store_si128((__m128i*)(cost + x*D + d), _mm_adds_epi16(c0, _mm_srl_epi16  
  210. //  
  211. //(_mm_unpacklo_epi8(diff,z), ds)));   
  212. //_mm_store_si128((__m128i*)(cost + x*D + d + 8), _mm_adds_epi16(c1, _mm_srl_epi16  
  213. //  
  214. //(_mm_unpackhi_epi8(diff,z), ds)));   
  215. //}   
  216. //}   
  217. //else   
  218. //#endif   
  219.         {   
  220.                     for( int d = minD; d < maxD; d++ )   
  221.                     {   
  222.                     int v = prow2[width-x-1 + d];   
  223.                     int v0 = buffer[width-x-1 + d];   
  224.                     int v1 = buffer[width-x-1 + d + width2];   
  225.                     int c0 = max(0, u – v1); c0 = max(c0, v0 – u);   
  226.                     int c1 = max(0, v – u1); c1 = max(c1, u0 – v);   
  227.                                                                                     //cout<<cost[x*D + d]<<endl;  
  228.                     cost[x*D + d] = (CostType)(cost[x*D+d] + (min(c0, c1) >> diff_scale)); //代价由预处理后的图像和原图两部分共同组成  
  229.                     //if(c==0) continue;  
  230.                     //else                                                    
  231.                     //cost[x*D + d] = (CostType)( (min(c0, c1) >> diff_scale));   
  232.                     //  cout<<”  +=”<<cost[x*D + d]<<endl;  
  233.                                                                   
  234.                     }   
  235.                       
  236.         }   
  237.     }   
  238.   
  239. }   
  240. #else   
  241. for( c = 0; c < cn*2; c++, prow1 += width, prow2 += width )   
  242. {   
  243. for( x = minX1; x < maxX1; x++ )   
  244. {   
  245. int u = prow1[x];   
  246. #if CV_SSE2   
  247. if( useSIMD )   
  248. {   
  249. __m128i _u = _mm_set1_epi8(u), z = _mm_setzero_si128();   
  250. for( int d = minD; d < maxD; d += 16 )   
  251. {   
  252. __m128i _v = _mm_loadu_si128((const __m128i*)(prow2 + width-1-x + d));   
  253. __m128i diff = _mm_adds_epu8(_mm_subs_epu8(_u,_v), _mm_subs_epu8(_v,_u));   
  254. __m128i c0 = _mm_load_si128((__m128i*)(cost + x*D + d));   
  255. __m128i c1 = _mm_load_si128((__m128i*)(cost + x*D + d + 8));   
  256. _mm_store_si128((__m128i*)(cost + x*D + d), _mm_adds_epi16(c0, _mm_unpacklo_epi8  
  257.   
  258. (diff,z)));   
  259. _mm_store_si128((__m128i*)(cost + x*D + d + 8), _mm_adds_epi16(c1,   
  260.   
  261. _mm_unpackhi_epi8(diff,z)));   
  262. }   
  263. }   
  264. else   
  265. #endif   
  266. {   
  267. for( int d = minD; d < maxD; d++ )   
  268. {   
  269. int v = prow2[width-1-x + d];   
  270. cost[x*D + d] = (CostType)(cost[x*D + d] + (CostType)std::abs(u – v));   
  271. }   
  272. }   
  273. }   
  274. }   
  275. #endif   
  276. }   
  277. /*   
  278. computes disparity for “roi” in img1 w.r.t. img2 and write it to disp1buf.   
  279. that is, disp1buf(x, y)=d means that img1(x+roi.x, y+roi.y) ~ img2(x+roi.x-d, y+roi.y).   
  280. minD <= d < maxD.   
  281. disp2full is the reverse disparity map, that is:   
  282. disp2full(x+roi.x,y+roi.y)=d means that img2(x+roi.x, y+roi.y) ~ img1(x+roi.x+d, y+roi.y)   
  283. note that disp1buf will have the same size as the roi and   
  284. disp2full will have the same size as img1 (or img2).   
  285. On exit disp2buf is not the final disparity, it is an intermediate result that   
  286.   
  287. becomes   
  288. final after all the tiles are processed.   
  289. the disparity in disp1buf is written with sub-pixel accuracy   
  290. (4 fractional bits, see CvmyStereoSGBM::DISP_SCALE),   
  291. using quadratic interpolation, while the disparity in disp2buf   
  292. is written as is, without interpolation.   
  293. disp2cost also has the same size as img1 (or img2).   
  294. It contains the minimum current cost, used to find the best disparity, corresponding   
  295.   
  296. to the minimal cost.   
  297. */   
  298. static void computeDisparitySGBM( const Mat& img1, const Mat& img2, Mat& disp1, const myStereoSGBM& params, Mat& buffer )   
  299. {   
  300. //#if CV_SSE2/*   
  301. //      static const uchar LSBTab[] =   
  302. //      {   
  303. //      0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0,   
  304. //  
  305. //      2, 0, 1, 0,   
  306. //      5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0,   
  307. //  
  308. //      2, 0, 1, 0,   
  309. //      6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0,   
  310. //  
  311. //      2, 0, 1, 0,   
  312. //      5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0,   
  313. //  
  314. //      2, 0, 1, 0,   
  315. //      7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0,   
  316. //  
  317. //      2, 0, 1, 0,   
  318. //      5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0,   
  319. //  
  320. //      2, 0, 1, 0,   
  321. //      6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0,   
  322. //  
  323. //      2, 0, 1, 0,   
  324. //      5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0,   
  325. //  
  326. //      2, 0, 1, 0   
  327. //      };   
  328. //      volatile bool useSIMD = checkHardwareSupport(CV_CPU_SSE2); */  
  329. //#endif   
  330.     const int ALIGN = 16;   
  331.     const int DISP_SHIFT = myStereoSGBM::DISP_SHIFT;   
  332.     const int DISP_SCALE = myStereoSGBM::DISP_SCALE;   
  333.     const CostType MAX_COST = SHRT_MAX;   
  334.     int minD = params.minDisparity, maxD = minD + params.numberOfDisparities;   
  335.     Size SADWindowSize; //5,5  
  336.     SADWindowSize.width = SADWindowSize.height = params.SADWindowSize > 0 ? params.SADWindowSize : 5;   
  337.     int ftzero = max(params.preFilterCap, 15) | 1; //63  最小为15  
  338.     int uniquenessRatio = params.uniquenessRatio >= 0 ? params.uniquenessRatio : 10;   
  339.     int disp12MaxDiff = params.disp12MaxDiff > 0 ? params.disp12MaxDiff : 1;   
  340.     int P1 = params.P1 > 0 ? params.P1 : 2, P2 = max(params.P2 > 0 ? params.P2 : 5, P1+1);   
  341.     int k, width = disp1.cols, height = disp1.rows;   
  342.     int minX1 = max(-maxD, 0), maxX1 = width + min(minD, 0); //minX1=0,maxX1=width  
  343.     int D = maxD – minD, width1 = maxX1 – minX1; //D=DMax=64,width1=width  
  344.     int INVALID_DISP = minD – 1, INVALID_DISP_SCALED = INVALID_DISP*DISP_SCALE; //INVALID_DISP=-1,INVALID_DISP_SCALED=-16  
  345.     int SW2 = SADWindowSize.width/2, SH2 = SADWindowSize.height/2;   
  346.       
  347.     int npasses = params.fullDP ? 2 : 1; //  
  348.     const int TAB_OFS = 256*4, TAB_SIZE = 256 + TAB_OFS*2;   
  349.     PixType clipTab[TAB_SIZE];   
  350.     for( k = 0; k < TAB_SIZE; k++ )   
  351.     {  
  352.     clipTab[k] = (PixType)(min(max(k – TAB_OFS, -ftzero), ftzero) + ftzero);   
  353.     //cout<<“clipTab[“<<k<<“] :”<<(int )clipTab[k]<<endl;  
  354.     }  
  355.         if( minX1 >= maxX1 )   
  356.         {   
  357.         disp1 = Scalar::all(INVALID_DISP_SCALED);   
  358.         return;   
  359.         }   
  360. CV_Assert( D % 16 == 0 );   
  361. // NR – the number of directions. the loop on x below that computes Lr assumes that NR == 8.   
  362. // if you change NR, please, modify the loop as well.   
  363.   int D2 = D+16, NRD2 = NR2*D2;   
  364. // the number of L_r(.,.) and min_k L_r(.,.) lines in the buffer:   
  365. // for 8-way dynamic programming we need the current row and   
  366. // the previous row, i.e. 2 rows in total   
  367.   const int NLR = 2;   
  368.   const int LrBorder = NLR – 1;   
  369. // for each possible stereo match (img1(x,y) <=> img2(x-d,y))   
  370. // we keep pixel difference cost (C) and the summary cost over NR directions (S).   
  371. // we also keep all the partial costs for the previous line L_r(x,d) and also min_k  L_r(x, k)   
  372.     size_t costBufSize = width1*D;   
  373.     size_t CSBufSize = costBufSize*(params.fullDP ? height : 1);   
  374.     size_t minLrSize = (width1 + LrBorder*2)*NR2, LrSize = minLrSize*D2;   
  375.     int hsumBufNRows = SH2*2 + 2;   
  376.   
  377.     size_t totalBufSize = (LrSize + minLrSize)*NLR*sizeof(CostType) + // minLr[] and Lr[]   
  378.     costBufSize*(hsumBufNRows + 1)*sizeof(CostType) + // hsumBuf, pixdiff   
  379.     CSBufSize*2*sizeof(CostType) + // C, S   
  380.     width*16*img1.channels()*sizeof(PixType) + // temp buffer for computing per-pixel cost //  
  381.     width*(sizeof(CostType) + sizeof(DispType)) + 1024; // disp2cost + disp2   
  382.         if( !buffer.data || !buffer.isContinuous() || buffer.cols*buffer.rows*buffer.elemSize() < totalBufSize )   
  383.               buffer.create(1, (int)totalBufSize, CV_8U);   
  384. // summary cost over different (nDirs) directions   
  385.             CostType* Cbuf = (CostType*)alignPtr(buffer.data, ALIGN);   
  386.             CostType* Sbuf = Cbuf + CSBufSize;   
  387.             CostType* hsumBuf = Sbuf + CSBufSize;   
  388.             CostType* pixDiff = hsumBuf + costBufSize*hsumBufNRows;   
  389.             CostType* disp2cost = pixDiff + costBufSize + (LrSize + minLrSize)*NLR;   
  390.             DispType* disp2ptr = (DispType*)(disp2cost + width);   
  391.             PixType* tempBuf = (PixType*)(disp2ptr + width);   
  392.               
  393. // add P2 to every C(x,y). it saves a few operations in the inner loops   
  394.    for( k = 0; k < width1*D; k++ )   
  395.         Cbuf[k] = (CostType)P2; //立方体的一层大小  
  396.   
  397.     for( int pass = 1; pass <= npasses; pass++ ) //npasses=1  
  398.     {   
  399.      int x1, y1, x2, y2, dx, dy;   
  400.         if( pass == 1 )   
  401.         {   
  402.             y1 = 0y2 = heightdy = 1;   
  403.             x1 = 0x2 = width1dx = 1;   
  404.         }   
  405.     else   
  406.         {   
  407.             y1 = height-1; y2 = -1; dy = -1;   
  408.             x1 = width1-1; x2 = -1; dx = -1;   
  409.         }   
  410.     CostType *Lr[NLR]={0}, *minLr[NLR]={0};   
  411.         for( k = 0; k < NLR; k++ )   
  412.             {   
  413.    
  414.             // shift Lr[k] and minLr[k] pointers, because we allocated them with the borders,   
  415.             // and will occasionally use negative indices with the arrays   
  416.             // we need to shift Lr[k] pointers by 1, to give the space for d=-1.   
  417.             // however, then the alignment will be imperfect, i.e. bad for SSE,   
  418.             // thus we shift the pointers by 8 (8*sizeof(short) == 16 – ideal alignment)   
  419.                     Lr[k] = pixDiff + costBufSize + LrSize*k + NRD2*LrBorder + 8;             // Lr[0]  NR2向动态规划数据存储           
  420.                                                                                                 //Lr[1]    
  421.                     memset( Lr[k] – LrBorder*NRD2 – 8, 0, LrSize*sizeof(CostType) );   
  422.   
  423.                     minLr[k] = pixDiff + costBufSize + LrSize*NLR + minLrSize*k + NR2*LrBorder; //每行像素点最小代价  缓存  
  424.   
  425.                     memset( minLr[k] – LrBorder*NR2, 0, minLrSize*sizeof(CostType) );   
  426.             }   
  427.                                                                               
  428.        for( int y = y1; y != y2; y += dy )   
  429.             {   
  430.                       
  431.             int x, d;   
  432.             DispType* disp1ptr = disp1.ptr<DispType>(y);   
  433.             CostType* C = Cbuf + (!params.fullDP ? 0 : y*costBufSize);   
  434.                                                                                                         //for(int i=0;i<width*D;i++)  
  435.                                                                                                         //  cout<<C[i]<<endl;  
  436.             CostType* S = Sbuf + (!params.fullDP ? 0 : y*costBufSize);   
  437.       
  438.             if( pass == 1 ) // compute C on the first pass, and reuse it on the second pass, if any.   
  439.              {   
  440.             int dy1 = y == 0 ? 0 : y + SH2, dy2 = y == 0 ? SH2 : dy1;   
  441.             for( k = dy1; k <= dy2; k++ )   
  442.                 {   
  443.                     CostType* hsumAdd = hsumBuf + (min(k, height-1) % hsumBufNRows)*costBufSize; // costBufSize* 4   hsumBufNRows=4  
  444.                     if( k < height )   
  445.                     {   
  446.                                                                                                               
  447.                                                                                                       
  448.                         calcPixelCostBT( img1, img2, k, minD, maxD, pixDiff, tempBuf, clipTab, TAB_OFS, ftzero );   
  449.                         memset(hsumAdd, 0, D*sizeof(CostType));   
  450.                         for( x = 0; x <= SW2*D; x += D )   
  451.                         {   
  452.                             int scale = x == 0 ? SW2 + 1 : 1;   
  453.                             for( d = 0; d < D; d++ )   
  454.                             hsumAdd[d] = (CostType)(hsumAdd[d] + pixDiff[x + d]*scale);   
  455.                         }   
  456.                         if( y > 0 )   
  457.                             {   
  458.                                 const CostType* hsumSub = hsumBuf + (max(y – SH2 – 1, 0) % hsumBufNRows)*costBufSize;   
  459.                                 const CostType* Cprev = !params.fullDP || y == 0 ? C : C – costBufSize;   
  460.                                 for( x = D; x < width1*D; x += D )   
  461.                                 {   
  462.                                     const CostType* pixAdd = pixDiff + min(x + SW2*D, (width1-1)*D);   
  463.                                     const CostType* pixSub = pixDiff + max(x – (SW2+1)*D, 0);   
  464.                                 //#if CV_SSE2/*   
  465.                                 //if( useSIMD )   
  466.                                 //{   
  467.                                 //  for( d = 0; d < D; d += 8 )   
  468.                                 //      {   
  469.                                 //              __m128i hv = _mm_load_si128((const __m128i*)(hsumAdd + x – D + d));   
  470.                                 //              __m128i Cx = _mm_load_si128((__m128i*)(Cprev + x + d));   
  471.                                 //              hv = _mm_adds_epi16(_mm_subs_epi16(hv,   
  472.                                 //              _mm_load_si128((const __m128i*)(pixSub + d))),   
  473.                                 //              _mm_load_si128((const __m128i*)(pixAdd + d)));   
  474.                                 //              Cx = _mm_adds_epi16(_mm_subs_epi16(Cx,   
  475.                                 //              _mm_load_si128((const __m128i*)(hsumSub + x + d))),   
  476.                                 //              hv);   
  477.                                 //              _mm_store_si128((__m128i*)(hsumAdd + x + d), hv);   
  478.                                 //              _mm_store_si128((__m128i*)(C + x + d), Cx);   
  479.                                 //      }   
  480.                                 //}   
  481.                                 //else */  
  482.                                 //#endif   
  483.                                     {   
  484.                                     for( d = 0; d < D; d++ )   
  485.                                         {   
  486.                                             int hv = hsumAdd[x + d] = (CostType)(hsumAdd[x – D + d] + pixAdd[d] – pixSub[d]);   
  487.                                             C[x + d] = (CostType)(Cprev[x + d] + hv – hsumSub[x + d]);   
  488.                                               
  489.                                         }   
  490.                                     }   
  491.                                 }   
  492.                             }   
  493.                         else   
  494.                             {   
  495.                               
  496.                             for( x = D; x < width1*D; x += D )   
  497.                                 {   
  498.                                     const CostType* pixAdd = pixDiff + min(x + SW2*D, (width1-1)*D);   
  499.                                     const CostType* pixSub = pixDiff + max(x – (SW2+1)*D, 0);   
  500.                                     for( d = 0; d < D; d++ )   
  501.                                     hsumAdd[x + d] = (CostType)(hsumAdd[x – D + d] + pixAdd[d] – pixSub[d]);   
  502.                                 }   
  503.                             }   
  504.                      }   
  505.    
  506.                     if( y == 0 )   
  507.                         {   
  508.                               
  509.                             int scale = k == 0 ? SH2 + 1 : 1;   
  510.                             for( x = 0; x < width1*D; x++ )   
  511.                             C[x] = (CostType)(C[x] + hsumAdd[x]*scale);   
  512.                         }   
  513.                 }   
  514.    
  515.             // also, clear the S buffer   
  516.                     for( k = 0; k < width1*D; k++ )   
  517.                     {  
  518.                         S[k] = 0;   
  519.                     }  
  520.             }   
  521.                                                                                             if(y==11)  
  522.                                                                                             {  
  523.                                                                                                     ofstream  cost0(“D:\\cpp_project\\test\\opencv_stereo\\opencv_stereo\\cost0.txt”);    
  524.                                                                                                         for(int i=0;i<width*D;i++)  
  525.                                                                                                         cost0<<“C[“<<i<<“]: “<<C[i]<<endl;  
  526.                                                                                                         cost0.close();  
  527.                                                                                             }                                                                                         
  528.             // clear the left and the right borders   
  529.             memset( Lr[0] – NRD2*LrBorder – 8, 0, NRD2*LrBorder*sizeof(CostType) );   
  530.             memset( Lr[0] + width1*NRD2 – 8, 0, NRD2*LrBorder*sizeof(CostType) ); // NRD2 = 8*D2;   
  531.             memset( minLr[0] – NR2*LrBorder, 0, NR2*LrBorder*sizeof(CostType) );   
  532.             memset( minLr[0] + width1*NR2, 0, NR2*LrBorder*sizeof(CostType) );   
  533.             /*   
  534.             [formula 13 in the paper]   
  535.             compute L_r(p, d) = C(p, d) +   
  536.             min(L_r(p-r, d),   
  537.             L_r(p-r, d-1) + P1,   
  538.             L_r(p-r, d+1) + P1,   
  539.             min_k L_r(p-r, k) + P2) – min_k L_r(p-r, k)   
  540.             where p = (x,y), r is one of the directions.   
  541.             we process all the directions at once:   
  542.             0: r=(-dx, 0)   
  543.             1: r=(-1, -dy)   
  544.             2: r=(0, -dy)   
  545.             3: r=(1, -dy)   
  546.             4: r=(-2, -dy)   
  547.             5: r=(-1, -dy*2)   
  548.             6: r=(1, -dy*2)   
  549.             7: r=(2, -dy)   
  550.             */   
  551.                     for( x = x1; x != x2; x += dx )   
  552.                      {   
  553.                             int xm = x*NR2, xd = xm*D2;   
  554.                             int delta0 = minLr[0][xm – dx*NR2] + P2, delta1 = minLr[1][xm – NR2 + 1] + P2;   
  555.                             int delta2 = minLr[1][xm + 2] + P2, delta3 = minLr[1][xm + NR2 + 3] + P2;   
  556.                             CostType* Lr_p0 = Lr[0] + xd – dx*NRD2;   
  557.                             CostType* Lr_p1 = Lr[1] + xd – NRD2 + D2;   
  558.                             CostType* Lr_p2 = Lr[1] + xd + D2*2;   
  559.                             CostType* Lr_p3 = Lr[1] + xd + NRD2 + D2*3;   
  560.                             Lr_p0[-1] = Lr_p0[D] = Lr_p1[-1] = Lr_p1[D] =   
  561.                             Lr_p2[-1] = Lr_p2[D] = Lr_p3[-1] = Lr_p3[D] = MAX_COST;   
  562.                             CostType* Lr_p = Lr[0] + xd;   
  563.                             const CostType* Cp = C + x*D;   
  564.                             CostType* Sp = S + x*D;   
  565.                     //#if CV_SSE2/*   
  566.                     //if( useSIMD )   
  567.                     //{   
  568.                     //  __m128i _P1 = _mm_set1_epi16((short)P1);   
  569.                     //  __m128i _delta0 = _mm_set1_epi16((short)delta0);   
  570.                     //  __m128i _delta1 = _mm_set1_epi16((short)delta1);   
  571.                     //  __m128i _delta2 = _mm_set1_epi16((short)delta2);   
  572.                     //  __m128i _delta3 = _mm_set1_epi16((short)delta3);   
  573.                     //  __m128i _minL0 = _mm_set1_epi16((short)MAX_COST);   
  574.                     //for( d = 0; d < D; d += 8 )   
  575.                     //{   
  576.                     //__m128i Cpd = _mm_load_si128((const __m128i*)(Cp + d));   
  577.                     //__m128i L0, L1, L2, L3;   
  578.                     //L0 = _mm_load_si128((const __m128i*)(Lr_p0 + d));   
  579.                     //L1 = _mm_load_si128((const __m128i*)(Lr_p1 + d));   
  580.                     //L2 = _mm_load_si128((const __m128i*)(Lr_p2 + d));   
  581.                     //L3 = _mm_load_si128((const __m128i*)(Lr_p3 + d));   
  582.                     //L0 = _mm_min_epi16(L0, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p0 + d –   
  583.                     //1)), _P1));   
  584.                     //L0 = _mm_min_epi16(L0, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p0 + d +   
  585.                     //1)), _P1));   
  586.                     //L1 = _mm_min_epi16(L1, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p1 + d –   
  587.                     //1)), _P1));   
  588.                     //L1 = _mm_min_epi16(L1, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p1 + d +   
  589.                     //1)), _P1));   
  590.                     //L2 = _mm_min_epi16(L2, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p2 + d –   
  591.                     //1)), _P1));   
  592.                     //L2 = _mm_min_epi16(L2, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p2 + d +   
  593.                     //1)), _P1));   
  594.                     //L3 = _mm_min_epi16(L3, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p3 + d –   
  595.                     //1)), _P1));   
  596.                     //L3 = _mm_min_epi16(L3, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p3 + d +   
  597.                     //1)), _P1));   
  598.                     //L0 = _mm_min_epi16(L0, _delta0);   
  599.                     //L0 = _mm_adds_epi16(_mm_subs_epi16(L0, _delta0), Cpd);   
  600.                     //L1 = _mm_min_epi16(L1, _delta1);   
  601.                     //L1 = _mm_adds_epi16(_mm_subs_epi16(L1, _delta1), Cpd);   
  602.                     //L2 = _mm_min_epi16(L2, _delta2);   
  603.                     //L2 = _mm_adds_epi16(_mm_subs_epi16(L2, _delta2), Cpd);   
  604.                     //L3 = _mm_min_epi16(L3, _delta3);   
  605.                     //L3 = _mm_adds_epi16(_mm_subs_epi16(L3, _delta3), Cpd);   
  606.                     //_mm_store_si128( (__m128i*)(Lr_p + d), L0);   
  607.                     //_mm_store_si128( (__m128i*)(Lr_p + d + D2), L1);   
  608.                     //_mm_store_si128( (__m128i*)(Lr_p + d + D2*2), L2);   
  609.                     //_mm_store_si128( (__m128i*)(Lr_p + d + D2*3), L3);   
  610.                     //__m128i t0 = _mm_min_epi16(_mm_unpacklo_epi16(L0, L2), _mm_unpackhi_epi16(L0, L2));   
  611.                     //__m128i t1 = _mm_min_epi16(_mm_unpacklo_epi16(L1, L3), _mm_unpackhi_epi16(L1, L3));   
  612.                     //t0 = _mm_min_epi16(_mm_unpacklo_epi16(t0, t1), _mm_unpackhi_epi16(t0, t1));   
  613.                     //_minL0 = _mm_min_epi16(_minL0, t0);   
  614.                     //__m128i Sval = _mm_load_si128((const __m128i*)(Sp + d));   
  615.                     //L0 = _mm_adds_epi16(L0, L1);   
  616.                     //L2 = _mm_adds_epi16(L2, L3);   
  617.                     //Sval = _mm_adds_epi16(Sval, L0);   
  618.                     //Sval = _mm_adds_epi16(Sval, L2);   
  619.                     //_mm_store_si128((__m128i*)(Sp + d), Sval);   
  620.                     //}   
  621.                     //_minL0 = _mm_min_epi16(_minL0, _mm_srli_si128(_minL0, 8));   
  622.                     //_mm_storel_epi64((__m128i*)&minLr[0][xm], _minL0);   
  623.                     //}   
  624.                     //else */  
  625.                     //#endif   
  626.                             {   
  627.                             int minL0 = MAX_COSTminL1 = MAX_COSTminL2 = MAX_COSTminL3 = MAX_COST;   
  628.                             for( d = 0; d < D; d++ )   
  629.                                 {   
  630.                                   int Cpd = Cp[d], L0, L1, L2, L3;   
  631.                                         L0 = Cpd + min((int)Lr_p0[d], min(Lr_p0[d-1] + P1, min(Lr_p0[d+1] + P1, delta0))) – delta0;   
  632.                                         L1 = Cpd + min((int)Lr_p1[d], min(Lr_p1[d-1] + P1, min(Lr_p1[d+1] + P1, delta1))) – delta1;   
  633.                                         L2 = Cpd + min((int)Lr_p2[d], min(Lr_p2[d-1] + P1, min(Lr_p2[d+1] + P1, delta2))) – delta2;   
  634.                                         L3 = Cpd + min((int)Lr_p3[d], min(Lr_p3[d-1] + P1, min(Lr_p3[d+1] + P1, delta3))) – delta3;   
  635.   
  636.                                           
  637.   
  638.                                   Lr_p[d] = (CostType)L0;  minL0 = min(minL0, L0);   
  639.                                   Lr_p[d + D2] = (CostType)L1; minL1 = min(minL1, L1);   
  640.                                   Lr_p[d + D2*2] = (CostType)L2; minL2 = min(minL2, L2);   
  641.                                   Lr_p[d + D2*3] = (CostType)L3; minL3 = min(minL3, L3);   
  642.    
  643.                                    Sp[d] = saturate_cast<CostType>(Sp[d] + L0 + L1 + L2 + L3); //原来  
  644.                                   //Sp[d] = saturate_cast<CostType>(  L0 + L1 + L2 + L3);   
  645.                                    
  646.                                 }   
  647.   
  648.                                     minLr[0][xm] = (CostType)minL0;   
  649.                                     minLr[0][xm+1] = (CostType)minL1;   
  650.                                     minLr[0][xm+2] = (CostType)minL2;   
  651.                                     minLr[0][xm+3] = (CostType)minL3;   
  652.                             }   
  653.                               
  654.                         }   
  655.                     ///////////////////////////////////////////////  
  656.       
  657.   
  658.  //////////////////////////////////////  
  659.                     if( pass == npasses )   
  660.                     {   
  661.                         for( x = 0; x < width; x++ )   
  662.                             {   
  663.                             disp1ptr[x] = disp2ptr[x] = (DispType)INVALID_DISP_SCALED;   
  664.                             disp2cost[x] = MAX_COST;   
  665.                             }   
  666.                         for( x = width1 – 1; x >= 0; x– )   
  667.                         ///////////////////////////////////////////////////////////////  
  668.                         //for( x = 0; x <=width-1; x++ )   
  669.                                 {   
  670.                                     CostType* Sp = S + x*D;   
  671.                                     int minS = MAX_COSTbestDisp = -1;   
  672.                                     if( npasses == 1 ) //  
  673.                                         {                 
  674.                                             int xm = x*NR2, xd = xm*D2;   
  675.                                             int minL0 = MAX_COST;   
  676.                                             int delta0 = minLr[0][xm + NR2] + P2;   
  677.                                             CostType* Lr_p0 = Lr[0] + xd + NRD2;   
  678.                                             Lr_p0[-1] = Lr_p0[D] = MAX_COST;   
  679.                                             CostType* Lr_p = Lr[0] + xd;   
  680.                                             const CostType* Cp = C + x*D;   
  681.                                             //#if CV_SSE2/*   
  682.                                             //if( useSIMD )   
  683.                                             //{   
  684.                                             //__m128i _P1 = _mm_set1_epi16((short)P1);   
  685.                                             //__m128i _delta0 = _mm_set1_epi16((short)delta0);   
  686.                                             //__m128i _minL0 = _mm_set1_epi16((short)minL0);   
  687.                                             //__m128i _minS = _mm_set1_epi16(MAX_COST), _bestDisp = _mm_set1_epi16(-1);   
  688.                                             //__m128i _d8 = _mm_setr_epi16(0, 1, 2, 3, 4, 5, 6, 7), _8 = _mm_set1_epi16(8);   
  689.                                             //for( d = 0; d < D; d += 8 )   
  690.                                             //{   
  691.                                             //__m128i Cpd = _mm_load_si128((const __m128i*)(Cp + d)), L0;   
  692.                                             //L0 = _mm_load_si128((const __m128i*)(Lr_p0 + d));   
  693.                                             //L0 = _mm_min_epi16(L0, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p0 + d – 1)), _P1));   
  694.                                             //L0 = _mm_min_epi16(L0, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p0 + d + 1)), _P1));   
  695.                                             //L0 = _mm_min_epi16(L0, _delta0);   
  696.                                             //L0 = _mm_adds_epi16(_mm_subs_epi16(L0, _delta0), Cpd);   
  697.                                             //_mm_store_si128((__m128i*)(Lr_p + d), L0);   
  698.                                             //_minL0 = _mm_min_epi16(_minL0, L0);   
  699.                                             //L0 = _mm_adds_epi16(L0, *(__m128i*)(Sp + d));   
  700.                                             //_mm_store_si128((__m128i*)(Sp + d), L0);   
  701.                                             //__m128i mask = _mm_cmpgt_epi16(_minS, L0);   
  702.                                             //_minS = _mm_min_epi16(_minS, L0);   
  703.                                             //_bestDisp = _mm_xor_si128(_bestDisp,   
  704.                                             //_mm_and_si128(_mm_xor_si128(_bestDisp,_d8), mask));   
  705.                                             //_d8 = _mm_adds_epi16(_d8, _8);   
  706.                                             //}   
  707.                                             //short CV_DECL_ALIGNED(16) bestDispBuf[8];   
  708.                                             //_mm_store_si128((__m128i*)bestDispBuf, _bestDisp);   
  709.                                             //_minL0 = _mm_min_epi16(_minL0, _mm_srli_si128(_minL0, 8));   
  710.                                             //_minL0 = _mm_min_epi16(_minL0, _mm_srli_si128(_minL0, 4));   
  711.                                             //_minL0 = _mm_min_epi16(_minL0, _mm_srli_si128(_minL0, 2));   
  712.                                             //__m128i qS = _mm_min_epi16(_minS, _mm_srli_si128(_minS, 8));   
  713.                                             //qS = _mm_min_epi16(qS, _mm_srli_si128(qS, 4));   
  714.                                             //qS = _mm_min_epi16(qS, _mm_srli_si128(qS, 2));   
  715.                                             //minLr[0][xm] = (CostType)_mm_cvtsi128_si32(_minL0);   
  716.                                             //minS = (CostType)_mm_cvtsi128_si32(qS);   
  717.                                             //qS = _mm_shuffle_epi32(_mm_unpacklo_epi16(qS, qS), 0);   
  718.                                             //qS = _mm_cmpeq_epi16(_minS, qS);   
  719.                                             //int idx = _mm_movemask_epi8(_mm_packs_epi16(qS, qS)) & 255;   
  720.                                             //bestDisp = bestDispBuf[LSBTab[idx]];   
  721.                                             //}   
  722.                                             //else */  
  723.                                             //#endif   
  724.                                             {   
  725.                                                 for( d = 0; d < D; d++ )   
  726.                                                     {   
  727.                                                     int L0 = Cp[d] + min((int)Lr_p0[d], min(Lr_p0[d-1] + P1, min(Lr_p0[d+1] + P1, delta0))) – delta0;   
  728.                                                                                             Lr_p[d] = (CostType)L0;   
  729.                                                     minL0 = min(minL0, L0);   
  730.    
  731.                                                     int Sval = Sp[d] = saturate_cast<CostType>(Sp[d] + L0);   
  732.                                                     if( Sval < minS )   
  733.                                                         {   
  734.                                                             minS = Sval;   
  735.                                                             bestDisp = d;   
  736.                                                         }   
  737.                                                     }   
  738.                                                 minLr[0][xm] = (CostType)minL0;   
  739.                                             }   
  740.                                          }   
  741.                                         else   
  742.                                             {   
  743.                                                   
  744.                                                 for( d = 0; d < D; d++ )   
  745.                                                     {   
  746.                                                         int Sval = Sp[d];   
  747.                                                         if( Sval < minS )   
  748.                                                             {   
  749.                                                                 minS = Sval;   
  750.                                                                 bestDisp = d;   
  751.                                                             }   
  752.                                                     }   
  753.                                             }   
  754.                                   
  755.                                     for( d = 0; d < D; d++ )   
  756.                                         {   
  757.                                         if( Sp[d]*(100 – uniquenessRatio) < minS*100 && std::abs(bestDisp – d) > 1 )   
  758.                                         break;   
  759.                                         }   
  760.                                     if( d < D )   
  761.                                         continue;   
  762.                                         d = bestDisp;   
  763.                                         int _x2 = x + minX1 – d – minD;   
  764.                                             if( disp2cost[_x2] > minS )   
  765.                                             {   
  766.                                                 disp2cost[_x2] = (CostType)minS;   
  767.                                                 disp2ptr[_x2] = (DispType)(d + minD);   
  768.                                             }   
  769.                                         if( 0 < d && d < D-1 ) //亚像素插值  
  770.                                         {   
  771.                                         // do subpixel quadratic interpolation:   
  772.                                         // fit parabola into (x1=d-1, y1=Sp[d-1]), (x2=dy2=Sp[d]), (x3=d+1, y3=Sp[d+1])   
  773.                                         // then find minimum of the parabola.   
  774.                                             int denom2 = max(Sp[d-1] + Sp[d+1] – 2*Sp[d], 1);   
  775.                                             d = d*DISP_SCALE + ((Sp[d-1] – Sp[d+1])*DISP_SCALE + denom2)/(denom2*2);   
  776.                                         }   
  777.                                         else   
  778.                                             d *= DISP_SCALE;   
  779.   
  780.                                    disp1ptr[x + minX1] = (DispType)(d + minD*DISP_SCALE);   
  781.                                      
  782.                                  //  cout<<(float)disp1ptr[x + minX1]/16<<endl;  
  783.                                 }   
  784.   
  785.                                              //LRcheck  
  786.                             for( x = minX1; x < maxX1; x++ )   
  787.                                 {   
  788.                                     // we round the computed disparity both towards -inf and +inf and check   
  789.                                     // if either of the corresponding disparities in disp2 is consistent.   
  790.                                     // This is to give the computed disparity a chance to look valid if it is.   
  791.                                     int d1 = disp1ptr[x];   
  792.                                     if( d1 == INVALID_DISP_SCALED )   
  793.                                     continue;   
  794.                                     int _d = d1 >> DISP_SHIFT;   
  795.                                     int d_ = (d1 + DISP_SCALE-1) >> DISP_SHIFT;   
  796.                                     int _x = x – _d, x_ = x – d_;   
  797.                                     if( 0 <= _x && _x < width && disp2ptr[_x] >= minD && std::abs(disp2ptr[_x] – _d) > disp12MaxDiff&& 0 <= x_ && x_ < width && disp2ptr[x_] >= minD && std::abs(disp2ptr[x_] – d_) > disp12MaxDiff )   
  798.                                     disp1ptr[x] = (DispType)INVALID_DISP_SCALED;   
  799.                                 }   
  800.                      }   
  801.    
  802.             // now shift the cyclic buffers   
  803.                 std::swap( Lr[0], Lr[1] );   
  804.                 std::swap( minLr[0], minLr[1] );   
  805.            }   
  806.       }   
  807. }   
  808. typedef cv::Point_<short> Point2s;   
  809.   
  810. void myStereoSGBM::operator() ( InputArray _left, InputArray _right, OutputArray _disp )  
  811. {   
  812.         Mat left = _left.getMat(), right = _right.getMat();   
  813.               CV_Assert( left.size() == right.size() && left.type() == right.type() && left.depth() == DataType<PixType>::depth );   
  814.         _disp.create( left.size(), CV_16S );   
  815.         Mat disp = _disp.getMat();   
  816.           
  817.           computeDisparitySGBM( left, right, disp, *this, buffer );   
  818.            medianBlur(disp, disp, 3);   
  819.   
  820.                                                                                                   
  821.                         if( speckleWindowSize > 0 )   
  822.                         cv::filterSpeckles(disp, (minDisparity – 1)*DISP_SCALE, speckleWindowSize, DISP_SCALE*speckleRange, buffer);//连通区域检测  
  823.                                                                                                           
  824. }   
  825.   
  826. Rect getValidDisparityROI( Rect roi1, Rect roi2, int minDisparity, int numberOfDisparities, int SADWindowSize )   
  827. {   
  828. int SW2 = SADWindowSize/2;   
  829. int minD = minDisparitymaxD = minDisparity + numberOfDisparities – 1;   
  830. int xmin = max(roi1.x, roi2.x + maxD) + SW2;   
  831. int xmax = min(roi1.x + roi1.width, roi2.x + roi2.width – minD) – SW2;   
  832. int ymin = max(roi1.y, roi2.y) + SW2;   
  833. int ymax = min(roi1.y + roi1.height, roi2.y + roi2.height) – SW2;   
  834. Rect r(xmin, ymin, xmax – xmin, ymax – ymin);   
  835. return r.width > 0 && r.height > 0 ? r : Rect();   
  836. }   
  837. }   
  838. namespace   
  839. {   
  840.             template <typename T>   
  841.             void filterSpecklesImpl(cv::Mat& img, int newVal, int maxSpeckleSize, int maxDiff, cv::Mat& _buf)   
  842.             {   
  843.                 //filterSpecklesImpl<short>(img, newVal, maxSpeckleSize, maxDiff, _buf);   
  844.                  using namespace cv;   
  845.                  int width = img.cols, height = img.rows, npixels = width*height;   
  846.                  size_t bufSize = npixels*(int)(sizeof(cv::Point_<short>) + sizeof(int) + sizeof(uchar)); //存了三部分东西  
  847.                  if( !_buf.isContinuous() || !_buf.data || _buf.cols*_buf.rows*_buf.elemSize() < bufSize )   
  848.                 _buf.create(1, (int)bufSize, CV_8U);   
  849.                 uchar* buf = _buf.data;   
  850.                 int i, j, dstep = (int)(img.step/sizeof(T));   
  851.                 int* labels = (int*)buf;   
  852.                 buf += npixels*sizeof(labels[0]);   
  853.                 cv::Point_<short>wbuf = (cv::Point_<short>*)buf;   
  854.                 buf += npixels*sizeof(wbuf[0]);   
  855.                 uchar* rtype = (uchar*)buf;   
  856.                 int curlabel = 0;   
  857.             // clear out label assignments   
  858.             memset(labels, 0, npixels*sizeof(labels[0]));   
  859.             for( i = 0; i < height; i++ )   
  860.             {   
  861.                 T* ds = img.ptr<T>(i);   
  862.                 int* ls = labels + width*i;   
  863.                 for( j = 0; j < width; j++ )   
  864.                 {   
  865.                     if( ds[j] != newVal ) // not a bad disparity   
  866.                         {   
  867.                             if( ls[j] ) // has a label, check for bad label   
  868.                                 {   
  869.                                       
  870.                                 if( rtype[ls[j]] ) // small region, zero out disparity   
  871.                                 ds[j] = (T)newVal;   
  872.                                 }   
  873.             // no label, assign and propagate   
  874.                             else   
  875.                             {   
  876.                                 cv::Point_<short>ws = wbuf; // initialize wavefront   
  877.                                 cv::Point_<short> p((short)j, (short)i); // current pixel   
  878.                                 curlabel++; // next label   
  879.                                 int count = 0; // current region size   
  880.                                 ls[j] = curlabel;   
  881.                             // wavefront propagation   
  882.                             while( ws >= wbuf ) // wavefront not empty   
  883.                                 {   
  884.                                     count++;   
  885.                                     // put neighbors onto wavefront   
  886.                                     T* dpp = &img.at<T>(p.y, p.x);   
  887.                                     T dp = *dpp; //p(x,y)的像素值  
  888.                                     int* lpp = labels + width*p.y + p.x;   
  889.                                     if( p.y < height-1 && !lpp[+width] && dpp[+dstep] != newVal && std::abs(dp – dpp[+dstep]) <= maxDiff )   
  890.                                         {   
  891.                                             lpp[+width] = curlabel;   
  892.                                             *ws++ = cv::Point_<short>(p.x, p.y+1);   
  893.                                         }   
  894.                                     if( p.y > 0 && !lpp[-width] && dpp[-dstep] != newVal && std::abs(dp – dpp[-dstep]) <= maxDiff )   
  895.                                         {   
  896.                                             lpp[-width] = curlabel;   
  897.                                             *ws++ = cv::Point_<short>(p.x, p.y-1);   
  898.                                         }   
  899.                                     if( p.x < width-1 && !lpp[+1] && dpp[+1] != newVal && std::abs(dp – dpp[+1]) <= maxDiff )   
  900.                                         {   
  901.                                             lpp[+1] = curlabel;   
  902.                                             *ws++ = cv::Point_<short>(p.x+1, p.y);   
  903.                                         }   
  904.                                     if( p.x > 0 && !lpp[-1] && dpp[-1] != newVal && std::abs(dp – dpp[-1]) <= maxDiff )   
  905.                                         {   
  906.                                             lpp[-1] = curlabel;   
  907.                                             *ws++ = cv::Point_<short>(p.x-1, p.y);   
  908.                                         }   
  909.                                     // pop most recent and propagate   
  910.                                     // NB: could try least recent, maybe better convergence   
  911.                                     p = *–ws;   
  912.                                 }   
  913.    
  914.                                 // assign label type   
  915.                                 if( count <= maxSpeckleSize ) // speckle region   
  916.                                 {   
  917.                                     rtype[ls[j]] = 1; // small region label   
  918.                                     ds[j] = (T)newVal;   
  919.                                 }   
  920.                                 else   
  921.                                 rtype[ls[j]] = 0; // large region label   
  922.                              }   
  923.                         }   
  924.                   }   
  925.    
  926.           }   
  927.     }   
  928. }   
  929. void cv::filterSpeckles( InputOutputArray _img, double _newval, int maxSpeckleSize, double _maxDiff, InputOutputArray __buf )   
  930.     //cv::filterSpeckles(disp, (minDisparity – 1)*DISP_SCALE, speckleWindowSize, DISP_SCALE*speckleRange, buffer);  
  931. {   
  932. Mat img = _img.getMat();   
  933. Mat temp, &_buf = __buf.needed() ? __buf.getMatRef() : temp;   
  934. CV_Assert( img.type() == CV_8UC1 || img.type() == CV_16SC1 );   
  935. int newVal = cvRound(_newval);   
  936. int maxDiff = cvRound(_maxDiff);   
  937.    
  938. if (img.type() == CV_8UC1)   
  939. filterSpecklesImpl<uchar>(img, newVal, maxSpeckleSize, maxDiff, _buf);   
  940. else   
  941. filterSpecklesImpl<short>(img, newVal, maxSpeckleSize, maxDiff, _buf);   
  942. }   
  943.    
  944. void cv::validateDisparity( InputOutputArray _disp, InputArray _cost, int minDisparity, int numberOfDisparities, int disp12MaxDiff )   
  945. {   
  946. Mat disp = _disp.getMat(), cost = _cost.getMat();   
  947. int cols = disp.cols, rows = disp.rows;   
  948. int minD = minDisparitymaxD = minDisparity + numberOfDisparities;   
  949. int x, minX1 = max(maxD, 0), maxX1 = cols + min(minD, 0);   
  950. AutoBuffer<int> _disp2buf(cols*2);   
  951. int* disp2buf = _disp2buf;   
  952. int* disp2cost = disp2buf + cols;   
  953. const int DISP_SHIFT = 4DISP_SCALE = 1 << DISP_SHIFT;   
  954. int INVALID_DISP = minD – 1, INVALID_DISP_SCALED = INVALID_DISP*DISP_SCALE;   
  955. int costType = cost.type();   
  956. disp12MaxDiff *= DISP_SCALE;   
  957. CV_Assert( numberOfDisparities > 0 && disp.type() == CV_16S && (costType == CV_16S || costType == CV_32S) && disp.size() == cost.size() );   
  958. for( int y = 0; y < rows; y++ )   
  959.   {   
  960.         short* dptr = disp.ptr<short>(y);   
  961.         for( x = 0; x < cols; x++ )   
  962.             {   
  963.                 disp2buf[x] = INVALID_DISP_SCALED;   
  964.                 disp2cost[x] = INT_MAX;   
  965.             }   
  966.     if( costType == CV_16S )   
  967.     {   
  968.     const short* cptr = cost.ptr<short>(y);   
  969.         for( x = minX1; x < maxX1; x++ )   
  970.         {   
  971.         int d = dptr[x], c = cptr[x];   
  972.         int x2 = x – ((d + DISP_SCALE/2) >> DISP_SHIFT);   
  973.    
  974.             if( disp2cost[x2] > c )   
  975.             {   
  976.                 disp2cost[x2] = c;   
  977.                 disp2buf[x2] = d;   
  978.             }   
  979.         }   
  980.     }   
  981.   else   
  982.     {   
  983.     const int* cptr = cost.ptr<int>(y);   
  984.    
  985.     for( x = minX1; x < maxX1; x++ )   
  986.         {   
  987.         int d = dptr[x], c = cptr[x];   
  988.         int x2 = x – ((d + DISP_SCALE/2) >> DISP_SHIFT);   
  989.    
  990.         if( disp2cost[x2] < c )   
  991.             {   
  992.                 disp2cost[x2] = c;   
  993.                 disp2buf[x2] = d;   
  994.             }   
  995.         }   
  996.     }   
  997.    
  998. for( x = minX1; x < maxX1; x++ )   
  999.         {   
  1000.         // we round the computed disparity both towards -inf and +inf and check   
  1001.         // if either of the corresponding disparities in disp2 is consistent.   
  1002.         // This is to give the computed disparity a chance to look valid if it is.   
  1003.         int d = dptr[x];   
  1004.         if( d == INVALID_DISP_SCALED )   
  1005.         continue;   
  1006.         int d0 = d >> DISP_SHIFT;   
  1007.         int d1 = (d + DISP_SCALE-1) >> DISP_SHIFT;   
  1008.         int x0 = x – d0, x1 = x – d1;   
  1009.         if( (0 <= x0 && x0 < cols && disp2buf[x0] > INVALID_DISP_SCALED && std::abs(disp2buf[x0] – d) > disp12MaxDiff) && (0 <= x1 && x1 < cols && disp2buf[x1] > INVALID_DISP_SCALED && std::abs(disp2buf[x1] – d) > disp12MaxDiff) )   
  1010.         dptr[x] = (short)INVALID_DISP_SCALED;   
  1011.         }   
  1012.    }   
  1013. }   
  1014. CvRect cvGetValidDisparityROI( CvRect roi1, CvRect roi2, int minDisparity, int numberOfDisparities, int SADWindowSize )   
  1015. {   
  1016. return (CvRect)cv::getValidDisparityROI( roi1, roi2, minDisparity,   
  1017. numberOfDisparities, SADWindowSize );   
  1018. }   
  1019.    
  1020. void cvValidateDisparity( CvArr* _disp, const CvArr* _cost, int minDisparity, int numberOfDisparities, int disp12MaxDiff )   
  1021. {   
  1022. cv::Mat disp = cv::cvarrToMat(_disp), cost = cv::cvarrToMat(_cost);   
  1023. cv::validateDisparity( disp, cost, minDisparity, numberOfDisparities, disp12MaxDiff   
  1024.   
  1025. );   
  1026. }  
  1027. void myStereoSGBM::GenerateFalseMap(cv::Mat &src, cv::Mat &disp)  
  1028. {  
  1029.     // color map  
  1030.     float max_val = 255.0f;  
  1031.     float map[8][4] = {{0,0,0,114},{0,0,1,185},{1,0,0,114},{1,0,1,174},  
  1032.                        {0,1,0,114},{0,1,1,185},{1,1,0,114},{1,1,1,0}};  
  1033.     float sum = 0;  
  1034.     for (int i=0; i<8; i++)  
  1035.       sum += map[i][3];  
  1036.   
  1037.     float weights[8]; // relative   weights  
  1038.     float cumsum[8];  // cumulative weights  
  1039.     cumsum[0] = 0;  
  1040.     for (int i=0; i<7; i++) {  
  1041.       weights[i]  = sum/map[i][3];  
  1042.       cumsum[i+1] = cumsum[i] + map[i][3]/sum;  
  1043.     }  
  1044.   
  1045.     int height_ = src.rows;  
  1046.     int width_ = src.cols;  
  1047.     // for all pixels do  
  1048.     for (int v=0; v<height_; v++) {  
  1049.       for (int u=0; u<width_; u++) {  
  1050.   
  1051.         // get normalized value  
  1052.         float val = std::min(std::max(src.data[v*width_ + u]/max_val,0.0f),1.0f);  
  1053.   
  1054.         // find bin  
  1055.         int i;  
  1056.         for (i=0; i<7; i++)  
  1057.           if (val<cumsum[i+1])  
  1058.             break;  
  1059.   
  1060.         // compute red/green/blue values  
  1061.         float   w = 1.0-(val-cumsum[i])*weights[i];  
  1062.         uchar r = (uchar)((w*map[i][0]+(1.0-w)*map[i+1][0]) * 255.0);  
  1063.         uchar g = (uchar)((w*map[i][1]+(1.0-w)*map[i+1][1]) * 255.0);  
  1064.         uchar b = (uchar)((w*map[i][2]+(1.0-w)*map[i+1][2]) * 255.0);  
  1065.         //rgb内存连续存放  
  1066.         disp.data[v*width_*3 + 3*u + 0] = b;  
  1067.         disp.data[v*width_*3 + 3*u + 1] = g;  
  1068.         disp.data[v*width_*3 + 3*u + 2] = r;  
  1069.       }  
  1070.     }  
  1071. }  

    原文作者:动态规划
    原文地址: https://blog.csdn.net/KYJL888/article/details/79249569
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞