关于双目立体视觉的三大基本算法及发展现状

发布时间:2024-06-04  

双目立体视觉一直是机器视觉研究领域的发展热点和难点,“热”是因为双目立体视觉有着及其广阔的应用前景,且随着光学、计算机科学等学科的不断发展,双目立体技术将不断进步直到应用到人类生活的方方面面。“难”则是因为受到摄像机、镜头等硬件设备及一些相关算法的限制。


01 简介


双目立体视觉是机器视觉中的一个重要分支,自上世纪60年代中期开创以来,经过几十年的发展,如今在机器人视觉、航空测绘、军事应及医学成像、工业检测上应用极其广泛。双目立体视觉基于视差原理并利用成像设备从不同的位置获取被测物体的左右两幅图像,然后根据三角测量原理计算空间点在二维图像的位置偏差,最后再利用位置偏差进行三维重建来获取被测物体的三维几何信息(本文不对双目立体视觉的数学原理进行详细介绍)。


02


双目立体视觉的三大基本算法的原理及其代码实现(基于opencv)


双目立体视觉中常用的基于区域的局部匹配准则主要有图像序列中对应像素差的绝对值之和SAD(sum of absolute differences)、对应像素差的平方之和SSD(sum of squared differences)及半全局匹配算法SGM(semi—global matching)。


2.1 SAD(sum of absolute differences)的原理


匹配算法SAD的基本思想是对经行对准后的左右视图图像的对应像素块的对应像素差的绝对值进行求和。


其数学公式如下:


094f0876-4328-11ee-a2ef-92fbcf53809c.png


SAD匹配算法的基本流程如下:


①输入两幅已经校正实现行对准的左视图(Left-Image)及右视图(Right-Image)。


②对左视图Left-Image进行扫描选定一个锚点并构建一个类似于卷积核的小窗口。


③用此小窗口覆盖Left-Image,并选择出小窗口覆盖区域的全部像素点。


④同样用此小窗口覆盖Right-Image,并选择出小窗口覆盖区域的全部像素点。


⑤Left-Image覆盖区域的像素减去Right-Image覆盖区域的像素,并求出所有像素点的差的绝对值之和。


⑥移动Right-Image的小窗口并重复④—⑤的操作。(注意此处会设置一个搜索范围,超过此范围则跳出)


⑦找到这个范围内SAD值最小的小窗口,此时便找到了与Left-Image锚点的最佳匹配的像素块。


2.1.1 SAD(sum of absolute differences)的基于opencv的C++代码实现


首先先定义一个SAD 算法的头文件(SAD_Algorithm.h):


#include"iostream"

#include"opencv2/opencv.hpp"

#include"iomanip"

using namespace std;

using namespace cv;

class SAD

{

public:

  SAD() :winSize(7), DSR(30) {}

  SAD(int _winSize, int _DSR) :winSize(_winSize), DSR(_DSR) {}

  Mat computerSAD(Mat &L, Mat &R); //计算SAD



private:

  int winSize; //卷积核的尺寸

  int DSR;     //视差搜索范围

};



Mat SAD::computerSAD(Mat &L, Mat &R)

{

  int Height = L.rows;

  int Width = L.cols;



  Mat Kernel_L(Size(winSize, winSize), CV_8U, Scalar::all(0));

  Mat Kernel_R(Size(winSize, winSize), CV_8U, Scalar::all(0));

  Mat Disparity(Height, Width, CV_8U, Scalar(0)); //视差图



  for (int i = 0; i= 0)

        {

          Kernel_R = R(Rect(x, j, winSize, winSize));

          Mat Dif;

          absdiff(Kernel_L, Kernel_R, Dif);//求差的绝对值之和

          Scalar ADD = sum(Dif);

          float a = ADD[0];

          MM.at(k) = a;

        }

      }

      Point minLoc;

      minMaxLoc(MM, NULL, NULL, &minLoc, NULL);

      int loc = minLoc.x;

      //int loc=DSR-loc;

      Disparity.at(j, i) = loc * 16;

    }

    double rate = double(i) / (Width);

    cout << "已完成" << setprecision(2) << rate * 100 << "%" << endl; //显示处理进度

  }

  return Disparity;

}



调用示例:

#include"SAD_Algorithm.h"

int main(int argc, char* argv[])

{

  Mat Img_L = imread("Teddy_L.png", 0);   //此处调用的图像已放入项目文件夹中

  Mat Img_R = imread("Teddy_R.png", 0);

  Mat Disparity;                            //创建视差图



  SAD mySAD(7, 30);                        //给出SAD的参数



  Disparity = mySAD.computerSAD(Img_L, Img_R);

  imshow("Teddy_L", Img_L);

  imshow("Teddy_R", Img_R);

  imshow("Disparity", Disparity);        //显示视差图



  waitKey();

  system("pause");                        //按任意键退出

  return 0;

}

2.1.2 SAD算法的运行效果

095b2584-4328-11ee-a2ef-92fbcf53809c.png

09768b6c-4328-11ee-a2ef-92fbcf53809c.png

可以看出SAD算法虽然运行较快,但效果较差。

2.2 SSD(sum of squared differences)的原理

SSD(sum of squared differences)算法大致与SAD(sum of absolute differences)相似。

其数学公式如下:

09dc9baa-4328-11ee-a2ef-92fbcf53809c.png

因SSD匹配算法与SAD匹配算法的过程及代码实现相类似,考虑到篇幅长度的原因,故SSD算法的基本过程及代码实现在本文中不在赘述,读者可去自行实现。

2.3 SGBM(semi-global block matching)的原理

SGM(semi-global matching)是一种用于计算双目立体视觉中的disparity的半全局匹配算法。其在opencv中的实现为SGBM(semi-global block matching)。

SGBM的原理:设置一个和disparity map(由每个像素点的disparity所构成)相关的全局能量函数,使这个能量函数最小。

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

其能量函数如下:

09e90700-4328-11ee-a2ef-92fbcf53809c.png

D--disparity map(视差图)

p、q—图像中的某个像素

Np—像素点Pd 相邻像素点(一般认为是8连通)

C(P,Dp)--当前像素点的disparity为Dp时,该像素点的cost

P1、P2—惩罚系数,分别适用于当像素P相邻像素中的disparity值与P的disparity差值为1和大于1时

I[]—当[]内的参数为真时返回1,否则返回0

SGBM算法的基本流程如下:

①预处理:使用sobel算子对源图像进行处理,并将经sobel算子处理后的图像映射为新图像,并得到图像的梯度信息用于后续的计算代价。

②代价计算:使用采样方法对经预处理得到的图像梯度信息计算梯度代价、使用采样方法对源图像计算SAD代价。

③动态规划:默认四条路经,并对路径规划的参数P1,P2进行设置(包括P1、P2、cn(图像通道数量)以及SADWindowsize(SAD窗口大小)的设置)。

④后处理:包括唯一性检测、亚像素插值、左右一致性检测、连通区域的检测。

2.3.1 SGBM(semi-global block matching)的基于opencv的C++代码实现

首先先定义一个SGBM算法的头文件(SGBM_Algorithm.h):

具体参数见代码及其注释(若读者需优化可自行调整),不再赘述


enum { STEREO_BM = 0, STEREO_SGBM = 1, STEREO_HH = 2, STEREO_VAR = 3, STEREO_3WAY = 4 };

#include"iostream"

#include"opencv2/opencv.hpp"

using namespace std;

using namespace cv;



void calDispWithSGBM(Mat Img_L, Mat Img_R, Mat &imgDisparity8U)

{

  Size imgSize = Img_L.size();

  int numberOfDisparities = ((imgSize.width / 8) + 15) & -16;

  Ptr sgbm = StereoSGBM::create(0, 16, 3);



  int cn = Img_L.channels();                        //左图像的通道数

  int SADWindowSize = 9;

  int sgbmWinSize = SADWindowSize > 0 ? SADWindowSize : 3;



  sgbm->setMinDisparity(0);                         //minDisparity最小视差默认为0;



  sgbm->setNumDisparities(numberOfDisparities);     //numDisparity视差搜索范围,其值必须为16的整数倍;



  sgbm->setP1(8 * cn*sgbmWinSize*sgbmWinSize);

  sgbm->setP2(32 * cn*sgbmWinSize*sgbmWinSize);     //一般建议惩罚系数P1、P2取此两值,P1、P2控制视差图的光滑度

                                                    //P2越大,视差图越平滑



  sgbm->setDisp12MaxDiff(1);                        //左右一致性检测最大容许误差阈值



  sgbm->setPreFilterCap(31);                        //预处理滤波器的截断值,预处理的输出值仅保留

                                                    //[-preFilterCap, preFilterCap]范围内的值,参数范围:1 - 31



  sgbm->setUniquenessRatio(10);                     //视差唯一性百分比:视差窗口范围内最低代价是次低代价的(1 + uniquenessRatio/100)倍时

                                                    //最低代价对应的视差值才是该像素点的视差,否则该像素点的视差为 0 ,不能为负值,一般去5——15



  sgbm->setSpeckleWindowSize(100);                  //视差连通区域像素点个数的大小:对于每一个视差点,当其连通区域的像素点个数小于

                                                    //speckleWindowSize时,认为该视差值无效,是噪点。



  sgbm->setSpeckleRange(32);                        //视差连通条件:在计算一个视差点的连通区域时,当下一个像素点视差变化绝对值大于

                                                    //speckleRange就认为下一个视差像素点和当前视差像素点是不连通的。



  sgbm->setMode(0);                                 //模式选择



  sgbm->setBlockSize(sgbmWinSize);                  //设置SAD代价计算窗口,一般在3*3到21*21之间

                                                    //blockSize(SADWindowSize) 越小,也就是匹配代价计算的窗口越小,视差图噪声越大;

                                                    //blockSize越大,视差图越平滑;

                                                    //太大的size容易导致过平滑,并且误匹配增多,体现在视差图中空洞增多



//三种模式选择(HH、SGBM、3WAY)

  int algorithm = STEREO_SGBM;



  if (algorithm == STEREO_HH)

    sgbm->setMode(StereoSGBM::MODE_HH);

  else if (algorithm == STEREO_SGBM)

    sgbm->setMode(StereoSGBM::MODE_SGBM);

  else if (algorithm == STEREO_3WAY)

    sgbm->setMode(StereoSGBM::MODE_SGBM_3WAY);



  Mat imgDisparity16S = Mat(Img_L.rows, Img_L.cols, CV_16S);



  sgbm->compute(Img_L, Img_R, imgDisparity16S);



  //--Display it as a CV_8UC1 image:16位有符号转为8位无符号

  imgDisparity16S.convertTo(imgDisparity8U, CV_8U, 255 / (numberOfDisparities*16.));

}



调用示例:

#include"SGBM_Algorithm.h"

int main()

{

  Mat Img_L = imread("Teddy_L.png", 0);

  Mat Img_R = imread("Teddy_R.png", 0);

  Mat Disparity8U = Mat(Img_L.rows, Img_R.cols, CV_8UC1);//创建一个Disparity图像



  calDispWithSGBM(Img_L, Img_R, Disparity8U);

  imshow("Teddy_L", Img_L);

  imshow("Teddy_R", Img_R);

  imshow("Disparity", Disparity8U);



  waitKey();

  system("pause");  //按任意键退出

  return 0;

}


2.3.2 SGBM算法的运行效果

09fd807c-4328-11ee-a2ef-92fbcf53809c.png

0a0b3168-4328-11ee-a2ef-92fbcf53809c.png

还顺便调整了SADWindowsize的大小来给读者探讨并展示当设置不同SADWindowsize大小时对Disparity效果图的影响,其结果如下(皆为MODE_SGBM模式下):

0a5cff48-4328-11ee-a2ef-92fbcf53809c.png

0a7ea080-4328-11ee-a2ef-92fbcf53809c.png

0ab6d05e-4328-11ee-a2ef-92fbcf53809c.png

由上述在不同SADWindowsize大小设置(其他参数保持不变)的效果图对比下我们可得知如下结论:

SADWindowsize过小时,视差图的噪声较多;随着SADWindowsize的增大,视图越平滑,但当SADWindowsize过大时,视差图中的空洞现象会增加;故在选择SADWindowsize的大小时,应选取合适的大小(建议选择SADWindowsize=9)。

03 双目立体视觉的发展现状

目前在国外,双目立体视觉技术已广泛运用于生产生活实际中,但在我国,双目立体视觉技术仍处在起步阶段,仍需要在座的各位发奋图强、力争创新。

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>