精华内容
下载资源
问答
  • sgbm参数设置
    2021-03-19 19:01:06

    1.minDisparity 最小可能的视差值。通常为,但有时校正算法会偏移图像,因此需要相应地调整此参数。

    2.numDisparities 最大视差减去最小视差。该值始终大于零。在当前的实现中,此参数必须可被16整除。

    3.P1 控制视差平滑度的第一个参数。此参数用于倾斜表面(非正视平行)的情况。

    4.P2 第二个参数控制视差平滑度。此参数用于“解决”深度不连续性问题。值越大,视差越平滑。P1是对相邻像素之间视差变化加或减1的惩罚。P2是相邻像素之间视差变化大于1的代价。该算法要求P2> P1。一些相当不错的P1和P2值(分别为8 * number_of_image_channels * SADWindowSize * SADWindowSize和32 * number_of_image_channels * SADWindowSize * SADWindowSize)。

    5.disp12MaxDiff 左右视差检查中允许的最大差异(以整数像素为单位)。将其设置为非正值可禁用检查。
    preFilterCap 预过滤图像像素的截断值。该算法首先在每个像素处计算x导数,然后按[-preFilterCap,preFilterCap]间隔裁剪其值。结果值传递到Birchfield-Tomasi像素成本函数。
    唯一性比率 最佳(最小)计算成本函数值应“赢得”次优值以认为找到的匹配正确的百分比裕度。通常,在5到15范围内的值就足够了。

    6.speckleWindowSize 平滑视差区域的最大大小,以考虑其噪声斑点并使其无效。将其设置为0以禁用斑点过滤。否则,将其设置在50-200范围内。
    斑点范围 每个连接组件内的最大视差变化。如果执行斑点过滤,请将参数设置为正值,它将隐式乘以16。通常,1或2就足够了。
    7.块大小 匹配的块大小。它必须是> = 1的奇数。通常,它应该在3…11范围内。
    这是我设置的参数,仅供参考。
    在这里插入图片描述

    更多相关内容
  • sgbm参数设置

    千次阅读 多人点赞 2019-01-08 16:26:45
    转自 https://blog.csdn.net/zhubaohua_bupt/article/details/51866567 https://blog.csdn.net/cxgincsu/article/details/74451940 ... SGBM相关学习链接: 1,原始文献:H...

    转自
    https://blog.csdn.net/zhubaohua_bupt/article/details/51866567
    https://blog.csdn.net/cxgincsu/article/details/74451940
    https://blog.csdn.net/u010369450/article/details/78839345


    SGBM相关学习链接:

    1,原始文献:Heiko Hirschmuller. Stereo processing by semiglobal matching and mutual information.Pattern Analysis and Machine Intelligence, IEEE Transactions on, 30(2):328–341, 2008.

    2,cv::StereoSGBM Class Reference

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


    SGBM的基本原理

    SGBM的基本步骤涉及:预处理、代价计算、动态规划以及后处理


    StereoSGBM的原型

    
     
    1. static Ptr<StereoSGBM> cv::StereoSGBM::create
    2. (
    3. int minDisparity = 0,
    4. int numDisparities = 16,
    5. int blockSize = 3,
    6. int P1 = 0,
    7. int P2 = 0,
    8. int disp12MaxDiff = 0,
    9. int preFilterCap = 0,
    10. int uniquenessRatio = 0,
    11. int speckleWindowSize = 0,
    12. int speckleRange = 0,
    13. int mode = StereoSGBM::MODE_SGBM 
    14. )

    第一个参数minDisparity,一般情况下为0,但有可能矫正算法会移动图像,因此,参数需要进行调整

    第二个参数numDisparities,最大视差减最小视差,现在的算法中,参数必须为16所整除

    第三个参数blockSize,块匹配的大小,应该为奇数,在3~11的范围

    第四、五个参数P1,P2:控制视差图的光滑度

    SGBM部分程序

    代码:

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

    minDisparity:最小视差,默认为0。此参数决定左图中的像素点在右图匹配搜索的起点,int 类型;

    numDisparities:视差搜索范围长度,其值必须为16的整数倍。最大视差 maxDisparity = minDisparity + numDisparities -1;

    blockSize:SAD代价计算窗口大小,默认为5。窗口大小为奇数,一般在3*3 到21*21之间;

    P1、P2:能量函数参数,P1是相邻像素点视差增/减 1 时的惩罚系数;P2是相邻像素点视差变化值大于1时的惩罚系数。P2必须大于P1。需要指出,在动态规划时,P1和P2都是常数。

    一般建议:P1 = 8*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;



    tsukuba_left.jpgtsukuba_right.jpg
    SADWindowSize = 5SADWindowSize = 11SADWindowSize = 21

    P1 = 8 , P2 = 10P1 = 8 , P2 = 32P1 = 8 , P2 = 64
    MODE_SGBM(5方向)MODE_HH(8方向)


    总结:

    1. blockSize(SADWindowSize) 越小,也就是匹配代价计算的窗口越小,视差图噪声越大;blockSize越大,视差图越平滑;太大的size容易导致过平滑,并且误匹配增多,体现在视差图中空洞增多;
    2. 惩罚系数控制视差图的平滑度,P2>P1,P2越大则视差图越平滑;
    3. 八方向动态规划较五方向改善效果不明显,主要在图像边缘能够找到正确的匹配;


      

    第二部分:opencvSGBM算法的参数含义及数值选取

    一 预处理参数

    1:preFilterCap:水平sobel预处理后,映射滤波器大小。默认为15

    int ftzero =max(params.preFilterCap, 15) | 1;

    opencv测试例程test_stereomatching.cpp中取63。

    二 代价参数

    2:SADWindowSize:计算代价步骤中SAD窗口的大小。由源码得,此窗口默认大小为5。

    SADWindowSize.width= SADWindowSize.height = params.SADWindowSize > 0 ?params.SADWindowSize : 5;

    注:窗口大小应为奇数,一般应在3x3到21x21之间。

    3:minDisparity:最小视差,默认为0。此参数决定左图中的像素点在右图匹配搜索的起点。int 类型

    4:numberOfDisparities:视差搜索范围,其值必须为16的整数倍(CV_Assert( D % 16 == 0 );)。最大搜索边界= numberOfDisparities+ minDisparity。int 类型

    三 动态规划参数

    动态规划有两个参数,分别是P1、P2,它们控制视差变化平滑性的参数。P1、P2的值越大,视差越平滑。P1是相邻像素点视差增/减 1 时的惩罚系数;P2是相邻像素点视差变化值大于1时的惩罚系数。P2必须大于P1。需要指出,在动态规划时,P1和P2都是常数。

    5:opencv测试例程test_stereomatching.cpp中,P1 = 8*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;

    6:opencv测试例程test_stereomatching.cpp中,P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;

    四:后处理参数

    7:uniquenessRatio:唯一性检测参数。对于左图匹配像素点来说,先定义在numberOfDisparities搜索区间内的最低代价为mincost,次低代价为secdmincost。如果满足

    即说明最低代价和次第代价相差太小,也就是匹配的区分度不够,就认为当前匹配像素点是误匹配的。

    opencv测试例程test_stereomatching.cpp中,uniquenessRatio=10。int 类型

    8:disp12MaxDiff:左右一致性检测最大容许误差阈值。int 类型

    opencv测试例程test_stereomatching.cpp中,disp12MaxDiff =1。

    9:speckleWindowSize:视差连通区域像素点个数的大小。对于每一个视差点,当其连通区域的像素点个数小于speckleWindowSize时,认为该视差值无效,是噪点。

    opencv测试例程test_stereomatching.cpp中,speckleWindowSize=100。

    10:speckleRange:视差连通条件,在计算一个视差点的连通区域时,当下一个像素点视差变化绝对值大于speckleRange就认为下一个视差像素点和当前视差像素点是不连通的。

    opencv测试例程test_stereomatching.cpp中,speckleWindowSize=10。

    展开全文
  • BM SGBM 设置参数解释

    千次阅读 2017-09-28 21:10:35
    (5) cvFindStereoCorrespondenceBM 函数的disparity参数的数据格式新增了 CV_32F 的支持,这种格式的数据给出实际视差,而 2.0 版只支持 CV_16S,需要除以 16.0 才能得到实际的视差数值。     2....

    立体匹配主要是通过找出每对图像间的对应关系,根据三角测量原理,得到视差图;在获得了视差信息后,根据投影模型很容易地可以得到原始图像的深度信息和三维信息。立体匹配技术被普遍认为是立体视觉中最困难也是最关键的问题,主要是以下因素的影响:

     

    (1) 光学失真和噪声(亮度、色调、饱和度等失衡)


    (2) 平滑表面的镜面反射


    (3) 投影缩减(Foreshortening)

    (4) 透视失真(Perspective distortions)

    (5) 低纹理(Low texture)

    (6) 重复纹理(Repetitive/ambiguous patterns)

    (7) 透明物体

    (8) 重叠和非连续



    目前立体匹配算法是计算机视觉中的一个难点和热点,算法很多,但是一般的步骤是:

     

     

    A、匹配代价计算

    匹配代价计算是整个立体匹配算法的基础,实际是对不同视差下进行灰度相似性测量。常见的方法有灰度差的平方SD(squared intensity differences),灰度差的绝对值AD(absolute intensity differences)等。另外,在求原始匹配代价时可以设定一个上限值,来减弱叠加过程中的误匹配的影响。以AD法求匹配代价为例,可用下式进行计算,其中T为设定的阈值。

    B、 匹配代价叠加

    一般来说,全局算法基于原始匹配代价进行后续算法计算。而区域算法则需要通过窗口叠加来增强匹配代价的可靠性,根据原始匹配代价不同,可分为:

    C、 视差获取

    对于区域算法来说,在完成匹配代价的叠加以后,视差的获取就很容易了,只需在一定范围内选取叠加匹配代价最优的点(SAD和SSD取最小值,NCC取最大值)作为对应匹配点,如胜者为王算法WTA(Winner-take-all)。而全局算法则直接对原始匹配代价进行处理,一般会先给出一个能量评价函数,然后通过不同的优化算法来求得能量的最小值,同时每个点的视差值也就计算出来了。

     

     

    D、视差细化(亚像素级)

    大多数立体匹配算法计算出来的视差都是一些离散的特定整数值,可满足一般应用的精度要求。但在一些精度要求比较高的场合,如精确的三维重构中,就需要在初始视差获取后采用一些措施对视差进行细化,如匹配代价的曲线拟合、图像滤波、图像分割等。

     

    有关立体匹配的介绍和常见匹配算法的比较,推荐大家看看Stefano Mattoccia 的讲义 Stereo Vision: algorithms and applications,190页的ppt,讲解得非常形象详尽。

     

     

     

     

     

    1. opencv2.1和opencv2.0在做stereo vision方面有什么区别了?

    2.1版增强了Stereo Vision方面的功能:

    (1) 新增了 SGBM 立体匹配算法(源自Heiko Hirschmuller的《Stereo Processing by Semi-global Matching and Mutual Information》),可以获得比 BM 算法物体轮廓更清晰的视差图(但低纹理区域容易出现横/斜纹路,在 GCstate->fullDP 选项使能时可消减这种异常纹路,但对应区域视差变为0,且运行速度会有所下降),速度比 BM 稍慢, 352*288的帧处理速度大约是 5 帧/秒;

    (2) 视差效果:BM < SGBM < GC;处理速度:BM > SGBM > GC ;

    (3) BM 算法比2.0版性能有所提升,其状态参数新增了对左右视图感兴趣区域 ROI 的支持(roi1 和 roi2,由stereoRectify函数产生);

    (4) BM 算法和 GC 算法的核心代码改动不大,主要是面向多线程运算方面的(由 OpenMP 转向 Intel TBB);

    (5) cvFindStereoCorrespondenceBM 函数的disparity参数的数据格式新增了 CV_32F 的支持,这种格式的数据给出实际视差,而 2.0 版只支持 CV_16S,需要除以 16.0 才能得到实际的视差数值。

     

     

    2. 用于立体匹配的图像可以是彩色的吗?

    在OpenCV2.1中,BM和GC算法只能对8位灰度图像计算视差,SGBM算法则可以处理24位(8bits*3)彩色图像。所以在读入图像时,应该根据采用的算法来处理图像:

    1. int color_mode = alg == STEREO_SGBM ? 1 : 0;  
    2. //   
    3. // 载入图像   
    4. cvGrabFrame( lfCam );  
    5. cvGrabFrame( riCam );  
    6. frame1 = cvRetrieveFrame( lfCam );  
    7. frame2 = cvRetrieveFrame( riCam );  
    8. if(frame1.empty()) break;  
    9. resize(frame1, img1, img_size, 0, 0);  
    10. resize(frame2, img2, img_size, 0, 0);  
    11. // 选择彩色或灰度格式作为双目匹配的处理图像   
    12. if (!color_mode && cn>1)  
    13. {  
    14. cvtColor(img1, img1gray, CV_BGR2GRAY);  
    15. cvtColor(img2, img2gray, CV_BGR2GRAY);  
    16. img1p = img1gray;  
    17. img2p = img2gray;  
    18. }  
    19. else  
    20. {  
    21. img1p = img1;  
    22. img2p = img2;  
    23. }  
    int color_mode = alg == STEREO_SGBM ? 1 : 0;
    //
    // 载入图像
    cvGrabFrame( lfCam );
    cvGrabFrame( riCam );
    frame1 = cvRetrieveFrame( lfCam );
    frame2 = cvRetrieveFrame( riCam );
    if(frame1.empty()) break;
    resize(frame1, img1, img_size, 0, 0);
    resize(frame2, img2, img_size, 0, 0);
    // 选择彩色或灰度格式作为双目匹配的处理图像
    if (!color_mode && cn>1)
    {
    cvtColor(img1, img1gray, CV_BGR2GRAY);
    cvtColor(img2, img2gray, CV_BGR2GRAY);
    img1p = img1gray;
    img2p = img2gray;
    }
    else
    {
    img1p = img1;
    img2p = img2;
    }

    3. 怎样获取与原图像有效像素区域相同的视差图?

    OpenCV2.0及以前的版本中,所获取的视差图总是在左侧和右侧有明显的黑色区域,这些区域没有有效的视差数据。视差图有效像素区域 与视差窗口(ndisp,一般取正值且能被16整除)和最小视差值(mindisp,一般取0或负值)相关,视差窗口越大,视差图左侧的黑色区域越大,最小视差值越小,视差图右侧的黑色区域越大。其原因是为了保证参考图像(一般是左视图)的像素点能在目标图像(右视图)中按照设定的视差匹配窗口匹配对应点, OpenCV 只从参考图像的第 (ndisp - 1 + mindisp) 列开始向右计算视差,第 0 列到第 (ndisp - 1 + mindisp) 列的区域视差统一设置为 (mindisp - 1) *16;视差计算到第 width + mindisp 列时停止,余下的右侧区域视差值也统一设置为 (mindisp - 1) *16

    1. 00177 static const int DISPARITY_SHIFT = 4;  
    2. …  
    3. 00411     int ndisp = state->numberOfDisparities;  
    4. 00412     int mindisp = state->minDisparity;  
    5. 00413     int lofs = MAX(ndisp - 1 + mindisp, 0);  
    6. 00414     int rofs = -MIN(ndisp - 1 + mindisp, 0);  
    7. 00415     int width = left->cols, height = left->rows;  
    8. 00416     int width1 = width - rofs - ndisp + 1;  
    9. …  
    10. 00420     short FILTERED = (short)((mindisp - 1) << DISPARITY_SHIFT);  
    11. …  
    12. 00466     // initialize the left and right borders of the disparity map   
    13. 00467     for( y = 0; y < height; y++ )  
    14. 00468     {  
    15. 00469         for( x = 0; x < lofs; x++ )  
    16. 00470             dptr[y*dstep + x] = FILTERED;  
    17. 00471         for( x = lofs + width1; x < width; x++ )  
    18. 00472             dptr[y*dstep + x] = FILTERED;  
    19. 00473     }  
    20. 00474     dptr += lofs;  
    21. 00475  
    22. 00476     for( x = 0; x < width1; x++, dptr++ )  
    23.   
    24. …  
    00177 static const int DISPARITY_SHIFT = 4;
    …
    00411     int ndisp = state->numberOfDisparities;
    00412     int mindisp = state->minDisparity;
    00413     int lofs = MAX(ndisp - 1 + mindisp, 0);
    00414     int rofs = -MIN(ndisp - 1 + mindisp, 0);
    00415     int width = left->cols, height = left->rows;
    00416     int width1 = width - rofs - ndisp + 1;
    …
    00420     short FILTERED = (short)((mindisp - 1) << DISPARITY_SHIFT);
    …
    00466     // initialize the left and right borders of the disparity map
    00467     for( y = 0; y < height; y++ )
    00468     {
    00469         for( x = 0; x < lofs; x++ )
    00470             dptr[y*dstep + x] = FILTERED;
    00471         for( x = lofs + width1; x < width; x++ )
    00472             dptr[y*dstep + x] = FILTERED;
    00473     }
    00474     dptr += lofs;
    00475
    00476     for( x = 0; x < width1; x++, dptr++ )
    
    …
    

    这样的设置很明显是不符合实际应用的需求的,它相当于把摄像头的视场范围缩窄了。因此, OpenCV2.1 做了明显的改进,不再要求左右视图和视差图的大小(size)一致, 允许对视差图进行左右边界延拓,这样,虽然计算视差时还是按上面的代码思路来处理左右边界,但是视差图的边界得到延拓后,有效视差的范围就能够与对应视图完全对应。具体的实现代码范例如下:

    1. //   
    2. // 对左右视图的左边进行边界延拓,以获取与原始视图相同大小的有效视差区域   
    3. copyMakeBorder(img1r, img1b, 0, 0, m_nMaxDisp, 0, IPL_BORDER_REPLICATE);  
    4. copyMakeBorder(img2r, img2b, 0, 0, m_nMaxDisp, 0, IPL_BORDER_REPLICATE);  
    5.   
    6. //   
    7. // 计算视差   
    8. if( alg == STEREO_BM )  
    9. {  
    10.     bm(img1b, img2b, dispb);  
    11.     // 截取与原始画面对应的视差区域(舍去加宽的部分)   
    12.     displf = dispb.colRange(m_nMaxDisp, img1b.cols);      
    13. }  
    14. else if(alg == STEREO_SGBM)  
    15. {  
    16.     sgbm(img1b, img2b, dispb);  
    17.     displf = dispb.colRange(m_nMaxDisp, img1b.cols);  
    18. }  
    //
    // 对左右视图的左边进行边界延拓,以获取与原始视图相同大小的有效视差区域
    copyMakeBorder(img1r, img1b, 0, 0, m_nMaxDisp, 0, IPL_BORDER_REPLICATE);
    copyMakeBorder(img2r, img2b, 0, 0, m_nMaxDisp, 0, IPL_BORDER_REPLICATE);
    
    //
    // 计算视差
    if( alg == STEREO_BM )
    {
    	bm(img1b, img2b, dispb);
    	// 截取与原始画面对应的视差区域(舍去加宽的部分)
    	displf = dispb.colRange(m_nMaxDisp, img1b.cols);	
    }
    else if(alg == STEREO_SGBM)
    {
    	sgbm(img1b, img2b, dispb);
    	displf = dispb.colRange(m_nMaxDisp, img1b.cols);
    }

    4. cvFindStereoCorrespondenceBM的输出结果好像不是以像素点为单位的视差?

    @scyscyao:在OpenCV2.0中,BM函数得出的结果是以16位符号数的形式的存储的,出于精度需要,所有的视差在输出时都扩大了16倍(2^4)。其具体代码表示如下:

    dptr[y*dstep] = (short)(((ndisp - mind - 1 + mindisp)*256 + (d != 0 ? (p-n)*128/d : 0) + 15) >> 4);

    可以看到,原始视差在左移8位(256)并且加上一个修正值之后又右移了4位,最终的结果就是左移4位。

    因此,在实际求距离时,cvReprojectTo3D出来的X/W,Y/W,Z/W都要乘以16 (也就是W除以16),才能得到正确的三维坐标信息。”

     

    OpenCV2.1中,BM算法可以用 CV_16S 或者 CV_32F 的方式输出视差数据,使用32位float格式可以得到真实的视差值,而CV_16S 格式得到的视差矩阵则需要 除以16 才能得到正确的视差。另外,OpenCV2.1另外两种立体匹配算法 SGBM 和 GC 只支持 CV_16S 格式的 disparity 矩阵

     

     

     

    5. 如何设置BM、SGBM和GC算法的状态参数?

     

    (1)StereoBMState

    // 预处理滤波参数

    • preFilterType:预处理滤波器的类型,主要是用于降低亮度失真(photometric distortions)、消除噪声和增强纹理等, 有两种可选类型:CV_STEREO_BM_NORMALIZED_RESPONSE(归一化响应) 或者 CV_STEREO_BM_XSOBEL(水平方向Sobel算子,默认类型), 该参数为 int 型;
    • preFilterSize:预处理滤波器窗口大小,容许范围是[5,255],一般应该在 5x5..21x21 之间,参数必须为奇数值, int 型
    • preFilterCap:预处理滤波器的截断值,预处理的输出值仅保留[-preFilterCap, preFilterCap]范围内的值,参数范围:1 - 31(文档中是31,但代码中是 63), int

    // SAD 参数

    • SADWindowSize:SAD窗口大小,容许范围是[5,255],一般应该在 5x5 至 21x21 之间,参数必须是奇数,int 型
    • minDisparity:最小视差默认值为 0, 可以是负值,int 型
    • numberOfDisparities:视差窗口,即最大视差值与最小视差值之差, 窗口大小必须是 16 的整数倍,int 型

    // 后处理参数

    • textureThreshold:低纹理区域的判断阈值。如果当前SAD窗口内所有邻居像素点的x导数绝对值之和小于指定阈值,则该窗口对应的像素点的视差值为 0(That is, if the sum of absolute values of x-derivatives computed over SADWindowSize by SADWindowSize pixel neighborhood is smaller than the parameter, no disparity is computed at the pixel),该参数不能为负值,int 型
    • uniquenessRatio:视差唯一性百分比, 视差窗口范围内最低代价是次低代价的(1 + uniquenessRatio/100)倍时,最低代价对应的视差值才是该像素点的视差,否则该像素点的视差为 0 (the minimum margin in percents between the best (minimum) cost function value and the second best value to accept the computed disparity, that is, accept the computed disparity d^ only if SAD(d) >= SAD(d^) x (1 + uniquenessRatio/100.) for any d != d*+/-1 within the search range ),该参数不能为负值,一般5-15左右的值比较合适,int 型
    • speckleWindowSize:检查视差连通区域变化度的窗口大小, 值为 0 时取消 speckle 检查,int 型
    • speckleRange:视差变化阈值,当窗口内视差变化大于阈值时,该窗口内的视差清零,int 型

    // OpenCV2.1 新增的状态参数

    • roi1, roi2:左右视图的有效像素区域,一般由双目校正阶段的 cvStereoRectify 函数传递,也可以自行设定。一旦在状态参数中设定了 roi1 和 roi2,OpenCV 会通过cvGetValidDisparityROI 函数计算出视差图的有效区域,在有效区域外的视差值将被清零。
    • disp12MaxDiff:左视差图(直接计算得出)和右视差图(通过cvValidateDisparity计算得出)之间的最大容许差异。超过该阈值的视差值将被清零。该参数默认为 -1,即不执行左右视差检查。int 型。注意在程序调试阶段最好保持该值为 -1,以便查看不同视差窗口生成的视差效果。具体请参见《使用OpenGL动态显示双目视觉三维重构效果示例》一文中的讨论。

    在上述参数中,对视差生成效果影响较大的主要参数是 SADWindowSize、numberOfDisparities 和 uniquenessRatio 三个,一般只需对这三个参数进行调整,其余参数按默认设置即可

    在OpenCV2.1中,BM算法有C和C++ 两种实现模块。

     

    (2)StereoSGBMState

    SGBM算法的状态参数大部分与BM算法的一致,下面只解释不同的部分:

    • SADWindowSize:SAD窗口大小,容许范围是[1,11],一般应该在 3x3 至 11x11 之间,参数必须是奇数,int 型
    • P1, P2:控制视差变化平滑性的参数。P1、P2的值越大,视差越平滑。P1是相邻像素点视差增/减 1 时的惩罚系数;P2是相邻像素点视差变化值大于1时的惩罚系数。P2必须大于P1。OpenCV2.1提供的例程 stereo_match.cpp 给出了 P1 和 P2 比较合适的数值
    • fullDP:布尔值,当设置为 TRUE 时,运行双通道动态编程算法(full-scale 2-pass dynamic programming algorithm),会占用O(W*H*numDisparities)个字节,对于高分辨率图像将占用较大的内存空间。一般设置为 FALSE

    注意OpenCV2.1的SGBM算法是用C++ 语言编写的,没有C实现模块。与H. Hirschmuller提出的原算法相比,主要有如下变化:

    1. 算法默认运行单通道DP算法,只用了5个方向,而fullDP使能时则使用8个方向(可能需要占用大量内存)。
    2. 算法在计算匹配代价函数时,采用块匹配方法而非像素匹配(不过SADWindowSize=1时就等于像素匹配了)。
    3. 匹配代价的计算采用BT算法("Depth Discontinuities by Pixel-to-Pixel Stereo" by S. Birchfield and C. Tomasi),并没有实现基于互熵信息的匹配代价计算。
    4. 增加了一些BM算法中的预处理和后处理程序。

     

    (3)StereoGCState

    GC算法的状态参数只有两个:numberOfDisparities 和 maxIters ,并且只能通过 cvCreateStereoGCState 在创建算法状态结构体时一次性确定,不能在循环中更新状态信息。GC算法并不是一种实时算法,但可以得到物体轮廓清晰准确的视差图,适用于静态环境物体的深度重构。

    注意GC算法只能在C语言模式下运行,并且不能对视差图进行预先的边界延拓,左右视图和左右视差矩阵的大小必须一致。

     

     

    6. 如何实现视差图的伪彩色显示?

    首先要将16位符号整形的视差矩阵转换为8位无符号整形矩阵,然后按照一定的变换关系进行伪彩色处理。我的实现代码如下:

    1. // 转换为 CV_8U 格式,彩色显示   
    2. dispLfcv = displf, dispRicv = dispri, disp8cv = disp8;  
    3. if (alg == STEREO_GC)  
    4. {  
    5.     cvNormalize( &dispLfcv, &disp8cv, 0, 256, CV_MINMAX );  
    6. }   
    7. else  
    8. {  
    9.     displf.convertTo(disp8, CV_8U, 255/(m_nMaxDisp*16.));  
    10. }  
    11. F_Gray2Color(&disp8cv, vdispRGB);  
    // 转换为 CV_8U 格式,彩色显示
    dispLfcv = displf, dispRicv = dispri, disp8cv = disp8;
    if (alg == STEREO_GC)
    {
    	cvNormalize( &dispLfcv, &disp8cv, 0, 256, CV_MINMAX );
    } 
    else
    {
    	displf.convertTo(disp8, CV_8U, 255/(m_nMaxDisp*16.));
    }
    F_Gray2Color(&disp8cv, vdispRGB);
    

    灰度图转伪彩色图的代码,主要功能是使灰度图中 亮度越高的像素点,在伪彩色图中对应的点越趋向于 红色;亮度越低,则对应的伪彩色越趋向于 蓝色;总体上按照灰度值高低,由红渐变至蓝,中间色为绿色。其对应关系如下图所示:

    1. void F_Gray2Color(CvMat* gray_mat, CvMat* color_mat)  
    2. {  
    3.     if(color_mat)  
    4.         cvZero(color_mat);  
    5.           
    6.     int stype = CV_MAT_TYPE(gray_mat->type), dtype = CV_MAT_TYPE(color_mat->type);  
    7.     int rows = gray_mat->rows, cols = gray_mat->cols;  
    8.   
    9.     // 判断输入的灰度图和输出的伪彩色图是否大小相同、格式是否符合要求   
    10.     if (CV_ARE_SIZES_EQ(gray_mat, color_mat) && stype == CV_8UC1 && dtype == CV_8UC3)  
    11.     {  
    12.         CvMat* red = cvCreateMat(gray_mat->rows, gray_mat->cols, CV_8U);  
    13.         CvMat* green = cvCreateMat(gray_mat->rows, gray_mat->cols, CV_8U);  
    14.         CvMat* blue = cvCreateMat(gray_mat->rows, gray_mat->cols, CV_8U);  
    15.         CvMat* mask = cvCreateMat(gray_mat->rows, gray_mat->cols, CV_8U);  
    16.   
    17.         // 计算各彩色通道的像素值   
    18.         cvSubRS(gray_mat, cvScalar(255), blue); // blue(I) = 255 - gray(I)   
    19.         cvCopy(gray_mat, red);          // red(I) = gray(I)   
    20.         cvCopy(gray_mat, green);            // green(I) = gray(I),if gray(I) < 128   
    21.         cvCmpS(green, 128, mask, CV_CMP_GE );   // green(I) = 255 - gray(I), if gray(I) >= 128   
    22.         cvSubRS(green, cvScalar(255), green, mask);  
    23.         cvConvertScale(green, green, 2.0, 0.0);  
    24.   
    25.         // 合成伪彩色图   
    26.         cvMerge(blue, green, red, NULL, color_mat);  
    27.   
    28.         cvReleaseMat( &red );  
    29.         cvReleaseMat( &green );  
    30.         cvReleaseMat( &blue );  
    31.         cvReleaseMat( &mask );  
    32.     }  
    33. }  
    void F_Gray2Color(CvMat* gray_mat, CvMat* color_mat)
    {
    	if(color_mat)
    		cvZero(color_mat);
    		
    	int stype = CV_MAT_TYPE(gray_mat->type), dtype = CV_MAT_TYPE(color_mat->type);
    	int rows = gray_mat->rows, cols = gray_mat->cols;
    
    	// 判断输入的灰度图和输出的伪彩色图是否大小相同、格式是否符合要求
    	if (CV_ARE_SIZES_EQ(gray_mat, color_mat) && stype == CV_8UC1 && dtype == CV_8UC3)
    	{
    		CvMat* red = cvCreateMat(gray_mat->rows, gray_mat->cols, CV_8U);
    		CvMat* green = cvCreateMat(gray_mat->rows, gray_mat->cols, CV_8U);
    		CvMat* blue = cvCreateMat(gray_mat->rows, gray_mat->cols, CV_8U);
    		CvMat* mask = cvCreateMat(gray_mat->rows, gray_mat->cols, CV_8U);
    
    		// 计算各彩色通道的像素值
    		cvSubRS(gray_mat, cvScalar(255), blue);	// blue(I) = 255 - gray(I)
    		cvCopy(gray_mat, red);			// red(I) = gray(I)
    		cvCopy(gray_mat, green);			// green(I) = gray(I),if gray(I) < 128
    		cvCmpS(green, 128, mask, CV_CMP_GE );	// green(I) = 255 - gray(I), if gray(I) >= 128
    		cvSubRS(green, cvScalar(255), green, mask);
    		cvConvertScale(green, green, 2.0, 0.0);
    
    		// 合成伪彩色图
    		cvMerge(blue, green, red, NULL, color_mat);
    
    		cvReleaseMat( &red );
    		cvReleaseMat( &green );
    		cvReleaseMat( &blue );
    		cvReleaseMat( &mask );
    	}
    }
    

    7. 如何将视差数据保存为 txt 数据文件以便在 Matlab 中读取分析?

    由于OpenCV本身只支持 xml、yml 的数据文件读写功能,并且其xml文件与构建网页数据所用的xml文件格式不一致,在Matlab中无法读取。我们可以通过以下方式将视差数据保存为txt文件,再导入到Matlab中。

    1. void saveDisp(const char* filename, const Mat& mat)       
    2. {  
    3.     FILE* fp = fopen(filename, "wt");  
    4.     fprintf(fp, "%02d/n", mat.rows);  
    5.     fprintf(fp, "%02d/n", mat.cols);  
    6.     for(int y = 0; y < mat.rows; y++)  
    7.     {  
    8.         for(int x = 0; x < mat.cols; x++)  
    9.         {  
    10.             short disp = mat.at<short>(y, x); // 这里视差矩阵是CV_16S 格式的,故用 short 类型读取   
    11.             fprintf(fp, "%d/n", disp); // 若视差矩阵是 CV_32F 格式,则用 float 类型读取   
    12.         }  
    13.     }  
    14.     fclose(fp);  
    15. }  
    void saveDisp(const char* filename, const Mat& mat)		
    {
    	FILE* fp = fopen(filename, "wt");
    	fprintf(fp, "%02d/n", mat.rows);
    	fprintf(fp, "%02d/n", mat.cols);
    	for(int y = 0; y < mat.rows; y++)
    	{
    		for(int x = 0; x < mat.cols; x++)
    		{
    			short disp = mat.at<short>(y, x); // 这里视差矩阵是CV_16S 格式的,故用 short 类型读取
    			fprintf(fp, "%d/n", disp); // 若视差矩阵是 CV_32F 格式,则用 float 类型读取
    		}
    	}
    	fclose(fp);
    }
    

    相应的Matlab代码为:

    1. function img = txt2img(filename)  
    2. data = importdata(filename);  
    3. r = data(1);    % 行数  
    4. c = data(2);    % 列数  
    5. disp = data(3:end); % 视差  
    6. vmin = min(disp);  
    7. vmax = max(disp);  
    8. disp = reshape(disp, [c,r])'; % 将列向量形式的 disp 重构为 矩阵形式  
    9. %  OpenCV 是行扫描存储图像,Matlab 是列扫描存储图像  
    10. %  故对 disp 的重新排列是首先变成 c 行 r 列的矩阵,然后再转置回 r 行 c 列  
    11. img = uint8( 255 * ( disp - vmin ) / ( vmax - vmin ) );  
    12. mesh(disp);  
    13. set(gca,'YDir','reverse');  % 通过 mesh 方式绘图时,需倒置 Y 轴方向  
    14. axis tight; % 使坐标轴显示范围与数据范围相贴合,去除空白显示区  
    function img = txt2img(filename)
    data = importdata(filename);
    r = data(1);    % 行数
    c = data(2);    % 列数
    disp = data(3:end); % 视差
    vmin = min(disp);
    vmax = max(disp);
    disp = reshape(disp, [c,r])'; % 将列向量形式的 disp 重构为 矩阵形式
    %  OpenCV 是行扫描存储图像,Matlab 是列扫描存储图像
    %  故对 disp 的重新排列是首先变成 c 行 r 列的矩阵,然后再转置回 r 行 c 列
    img = uint8( 255 * ( disp - vmin ) / ( vmax - vmin ) );
    mesh(disp);
    set(gca,'YDir','reverse');  % 通过 mesh 方式绘图时,需倒置 Y 轴方向
    axis tight; % 使坐标轴显示范围与数据范围相贴合,去除空白显示区
    显示效果如下








    展开全文
  • 对于SGBM算法原理不多介绍啦,这里只是结合KITTI标准数据集以及opencv环境下,介绍SGBM参数的含义以及设置。 (感谢开放的学术环境,这里也只是对王泽远硕士的论文进行学习和总结,若有侵权部分,请联系作者删除。)...

    对于SGBM算法原理不多介绍啦,这里只是结合KITTI标准数据集以及opencv环境下,介绍SGBM参数的含义以及设置。
    (感谢开放的学术环境,这里也只是对王泽远硕士的论文进行学习和总结,若有侵权部分,请联系作者删除。)
    opencv中对于SGBM算法需要设置很多参数,这些参数都会或多或少的影响到最终匹配结果。概括来说,把这些参数分为三类:

    1.预处理滤波参数

    这部分参数对输入图像进行预处理,来消减光照不均匀、噪声等因素的影响。
    preFilterType:预处理滤波器类型。有两种可选类型:CV_STEREO_BM_NORMALIZED_RESPONSE(归一化响应) 或者 CV_STEREO_BM_XSOBEL(水平方向Sobel算子,默认类型), 该参数为 int 型;
    preFilterSize:预处理滤波器窗口大小。
    preFilterCap:预处理滤波器的截断值。预处理的输出值仅保留[-preFilterCap, preFilterCap]范围内的值,参数范围:1 - 31。

    2.SGBM状态参数

    SADWindowSize:SAD窗口大小,容许范围是[1,11],一般应该在 3x3 至 11x11 之间,参数必须是奇数,int 型;
    minDispariy:最小视差;
    numberofDisparities:最大视差值与最小视差值之差;
    PI,P2:控制视差变化平滑性的参数:根据半全局立体匹配优化函数的定义,选取较大的P1、P2值会较平滑的视差结果。P1是用来惩罚相邻像素点视差增减变化;P2是用来约束视差连续性的惩罚系数;
    fullDP:决定是否使用双通道动态编程算法提高运算效率的布尔值参数。

    3.处理参数

    textureTheshold:低纹理区域的判断阈值。
    uniquenessRatio:视差唯一性百分比。
    speckleWindowSize:检查视差连通区域变化度的窗口大小。
    speckeRange:视差变化阈值,当窗口内视差变化大于阈值时,该窗口内的视差清零

    对与KITTI数据集,采用下表参数设置可以得到个较好的效果。

    设置KITTI数据集
    图像分辨率1241*376
    preFilterType63
    SADWindowSize11
    P1SADWindowSizeSADWindowSize4
    P2SADWindowSizeSADWindowSize32
    minDispariy0
    numberofDisparities64
    uniquenessRatio10
    speckleWindowSize100
    spckleRange32
    FullDP1

    效果图如下:
    SGBM结果

    展开全文
  • SGBM障碍物提取

    2019-03-13 21:31:31
    主要用于对机器人行进路线的障碍物提取......
  • 双目测距 SGBM算法 Python版

    千次阅读 热门讨论 2021-09-16 15:26:18
    首先进行双目定标,获取双目摄像头内部的参数后,进行测距。本次的双目视觉测距,基于SGBM算法。 注意:双目定标的效果会影响测距的精准度,建议大家在做双目定标时,做好一些(尽量让误差小) 如果不太了解双目...
  • 参数设置如BM方法,速度比较快,320*240的灰度图匹配时间为78ms,视差效果如下图。 第三种为GC方法: view plaincopy to clipboardprint? CvStereoGCState* state = cvCreateStereoGCState( 16, 2 ); left_disp_ ...
  • 第一部分BM、GC和SGBM算法的性能比较转自:http://blog.csdn.net/chenyusiyuan/article/details/5967291,其中原博主推荐的Stefano Mattoccia大神的讲义Stereo Vision:algorithms and applications,我看了以后...
  • 上一篇看了较为简单的BM算法,后面又看了下opencv里的SGBM算法。之所以叫SGBM是因为opencv并没有使用MI作为匹配代价,而是仍然使用了块匹配的方法,相关cost的度量为Birchfield-Tomasi metric。而且opencv提供了多种...
  • SAD, SGBM算法代码

    千次阅读 2022-01-26 09:53:37
    用opencv实现SAD和SGBM
  • 近日,南京大学周志华, 创新工场冯霁等人提出了一种新型的软梯度提升机(sGBM),并基于此构建了新型的软梯度提升决策树(sGBDT),作为XGBoost的替代性模型。相比于传统的「硬」GBM,sGBM 在准确度、训练时间和增量学习...
  • SGBM原理和opencv编程

    2021-07-19 09:26:38
    具体的算法原理请移步opencvSGBM半全局立体匹配算法的研究(1) 代码及结果 #include <iostream> #include <opencv2/highgui.hpp> #include <opencv2/core.hpp> #include <opencv2/imgcodecs.hpp...
  • 立体匹配算法SGBM

    千次阅读 2020-01-05 17:31:00
    SGBM算法,作为一种全局匹配算法,立体匹配的效果明显好于局部匹配算法,但是同时复杂度上也要远远大于局部匹配算法。 原文链接:https://blog.csdn.net/renshengrumenglibing/article/details/8525328SGBM的基本...
  • opencv SGBM 练习总结

    千次阅读 2021-11-14 16:49:13
    cap = cv2.VideoCapture(2) # 这个摄像头 设置宽高,帧率会自动跟着变 cap.set(cv2.CAP_PROP_FRAME_WIDTH,2560) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 960) fcc = cv2.VideoWriter_fourcc('M','J','P','G') #cap.set...
  • 转载请说明出处:...本文先描述一下opencvSGBM算法流程,接着给出调用opencvSGBM需要设置参数的含义、数值选取以及运行效果,最后贴出opencvSGBM源码。第一部分:SGBM算法研究总结...
  • 该方法速度最快,一副320*240的灰度图匹配时间为31ms SBGM SGBM算法 Stereo Processing by Semiglobal Matching and Mutual Information 作为一种全局匹配算法,立体匹配的效果明显好于局部匹配算法,但是同时...
  • 设置BM、SGBM和GC算法的状态参数

    万次阅读 2014-07-12 00:04:30
    5. 如何设置BM、SGBM和GC算法的状态参数? (1)StereoBMState // 预处理滤波参数 preFilterType:预处理滤波器的类型,主要是用于降低亮度失真(photometric distortions)、消除噪声和增强纹理等, ...
  • 我还顺便调整了SADWindowsize的大小来给读者探讨并展示当设置不同SADWindowsize大小时对Disparity效果图的影响,其结果如下(皆为MODE_SGBM模式下): 由上述在不同SADWindowsize大小设置(其他参数保持不变)的效果...
  • SGBM参数设置:(在下面的程序中已经标明) MinDisparity设置为0,因为两个摄像头是前向平行放置,相同的物体在左图中一定比在右图中偏右。如果为了追求更大的双目重合区域而将两个摄像头向内偏转的话,这个参数是...
  • 立体匹配(x)SGBM半全局立体匹配算法 一、SGBM算法实现过程 1、预处理 预处理目的是得到图像的梯度信息 Step1:SGBM采用水平Sobel算子,对图像做处理,公式为: Sobel(x,y)=2[P(x+1,y)-P(x-1,y)]+ P(x+1,y-1)-P(x...
  • 双目立体匹配算法SGBM

    万次阅读 多人点赞 2018-08-07 23:01:20
    semi-global matching(SGM)是一种用于计算双目视觉中视差(disparity)的半全局匹配算法,在OpenCV中的实现为semi-global block matching(SGBM)。 第一部分:SGBM算法原理: 一、预处理 Step1:SGBM采用水平...
  • 引言在观察OpenCV中某个函数在不同参数的情况下,所得到的效果的时候,我之前是改一次参数运行一次,这样做起来操作麻烦,效率低下。为了更便捷的观察参数变化时带来的处理效果改变 可以使用滑动条来改变参数具体...
  • OpenCV密集配准BM.cpp

    2020-01-02 16:55:50
    SGBM参数设置:(在下面的程序中已经标明) MinDisparity设置为0,因为两个摄像头是前向平行放置,相同的物体在左图中一定比在右图中偏右。如果为了追求更大的双目重合区域而将两个摄像头向内偏转的话,这个参数是...
  • 这篇写什么呢,就写一下最近在进行深度测试时,因为需要调节很多参数,所以研究 ##创建参数调节的窗口。创建调节变量的函数是cv2.createTrackbar cv2.namedWindow('Disparity',0) cv2.createTrackbar('blockSize', '...
  • opencv stereoMatch BM SGBM

    千次阅读 2017-01-13 15:05:07
     printf("\nUsage: stereo_match   [--algorithm=bm|sgbm|hh|var] [--blocksize=]\n"   "[--max-disparity=] [--scale=scale_factor>] [-i ] [-e ]\n"   "[--no-display] [-o ] [-p ]\n");  } ...
  • SGBM的各个参数意义,请参考https://blog.csdn.net/wwp2016/article/details/86080722 整个程序分为3部分SGBMStart,SGBMUpdate,main #include <opencv2/opencv.hpp> #include "opencv2/highgui/highgui.hpp...
  • //控制视差平滑度第一参数 sgbm->setP2(32*pngChannels*winSize*winSize);//控制视差平滑度第二参数 sgbm->setMinDisparity(0);//最小视差 sgbm->setNumDisparities(nmDisparities);//视差搜索范围 sgbm->...
  • 最后,完成对学习器 h_m 和系数 β_m 的参数更新之后,就可以将其用作条件来更新 GBM 的预测结果: 图 1:GBM 和 sGBM 示意图 然后进入下一轮训练流程。算法 1 总结了这个训练过程,图 1 左图也给出了其示意图。 ...

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 339
精华内容 135
关键字:

sgbm参数设置