赞
踩
如前所述,本系列首先通过视差图的实现,从直观的角度对双目立体视觉首先进行个大概的了解。
1,SAD
参考代码:双目立体视觉SAD匹配算法
- class SAD{
- private:
- int winSize;//卷积核尺寸
- int DSR;//视差搜索范围
- public:
- SAD() :winSize(7), DSR(30){}
- SAD(int _winSize, int _DSR) :winSize(_winSize), DSR(_DSR){}
- Mat computerSAD(Mat&L, Mat&R);//计算SAD
- };
- 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));
- //CV_8U:0~255的值,大多数图像/视频的格式,该段设置全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 < Width - winSize; ++i){
- for (int j = 0; j < Height - winSize; ++j){
- Kernel_L = L(Rect(i, j, winSize, winSize));//L为做图像,Kernel为这个范围内的左图
- Mat MM(1, DSR, CV_32F, Scalar(0));//定义匹配范围
-
- for (int k = 0; k < DSR; ++k){
- int x = i - k;
- if (x >= 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<float>(k) = a;
- }
- Point minLoc;
- minMaxLoc(MM, NULL, NULL, &minLoc, NULL);
-
- int loc = minLoc.x;
- Disparity.at<char>(j, i) = loc * 16;
- }
- double rate = double(i) / (Width);
- cout << "已完成" << setprecision(2) << rate * 100 << "%" << endl;
- }
- }
- return Disparity;
- }
-
- int main(){
- Mat left = imread("1.png");
- Mat right = imread("2.png");
- //-------图像显示-----------
- namedWindow("leftimag");
- imshow("leftimag", left);
-
- namedWindow("rightimag");
- imshow("rightimag", right);
- //--------由SAD求取视差图-----
- Mat Disparity;
-
- SAD mySAD(7, 30);
- Disparity = mySAD.computerSAD(left, right);
- //-------结果显示------
- namedWindow("Disparity");
- imshow("Disparity",Disparity);
- //-------收尾------
- waitKey(0);
- return 0;
- }
程序解读:
可以看到SAD算法的效果确实很一般,而且在实际运行过程中,结果图的边界会出现黑色块的现象。
主程序中先定义了卷积核尺寸为7,视差搜索范围为30,参见构造函数Mat SAD():winSize(),DSR(){}
computerSAD计算出视差图。
其程序实现如下:
首先定义左右两幅图像的kernel,大小为winSize尺寸,并定义视差图Mat矩阵
----------------------------------------------------------------------------------------------------------------
第二步就是在图像内实现块的遍历匹配
块的大小为winSize,范围为(0:width-winSize,0:height-winSize);
遍历方法如下
- for (int k = 0; k < DSR; ++k){
- int x = i - k;
- if (x >= 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<float>(k) = a;
- }
排序后便可输出视差图。
SGBM算法是一种全局匹配算法,立体匹配的效果明显好于局部匹配算法,在OpenCV中是把SGBM作为一个类对该算法进行实现的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。