博主最近在研究双目测距的实现,要实现对高分辨率的图片进行实时匹配,对立体匹配算法的要求就比较苛刻。经过测试,OpenCV自带的BM、SGBM等算法对小图片的匹配效果还行,但是对高分辨率图片就力所不逮了。于是经过一番折腾,找到了这篇论文《Efficient Large-Scale Stereo Matching》及作者开源发布的源码库,但是发现源码库的example及网上相关资料均只能在VS的x86环境下运行,而受限于某些原因,我又只能在x64环境下运行,最后参考这位大佬的代码:链接,实现了ELAS算法在x64环境下的编译及运行。
代码运行环境:Win10+VS2015+OpenCV3.4.1
/*
ElasMatch的形参必须为灰度图像,因为ELAS算法处理的图像格式为*.pgm,其为灰度图像对应的便携式图像格式。而黑白对应*.pbm格式、彩色对应着*.ppm格式。
*/
#include
#include
#include
#include
#include "elas.h"
using namespace std;
using namespace cv;
int ElasMatch(cv::Mat leftImage, cv::Mat rightImage);
int main() {
Mat left = imread("L.jpg",IMREAD_GRAYSCALE);
Mat right = imread("R.jpg",IMREAD_GRAYSCALE);
ElasMatch(left, right);
waitKey(0);
return 0;
}
int ElasMatch(cv::Mat leftImage, cv::Mat rightImage)
{
cv::Mat disp_l, disp_r, disp8u_l, disp8u_r;
double minVal; double maxVal;
//cv::Mat leftImage = cv::imread("../test_images/leftr31.png", 0);
//cv::Mat rightImage = cv::imread("../test_images/rightr31.png", 0);
// generate disparity image using LIBELAS
int bd = 0;
const int32_t dims[3] = { leftImage.cols,leftImage.rows,leftImage.cols };
cv::Mat leftdpf = cv::Mat::zeros(cv::Size(leftImage.cols, leftImage.rows), CV_32F);
cv::Mat rightdpf = cv::Mat::zeros(cv::Size(leftImage.cols, leftImage.rows), CV_32F);
Elas::parameters param;
param.postprocess_only_left = false;
Elas elas(param);
elas.process(leftImage.data, rightImage.data, leftdpf.ptr<float>(0), rightdpf.ptr<float>(0), dims);
cv::Mat(leftdpf(cv::Rect(bd, 0, leftImage.cols, leftImage.rows))).copyTo(disp_l);
cv::Mat(rightdpf(cv::Rect(bd, 0, rightImage.cols, rightImage.rows))).copyTo(disp_r);
//-- Check its extreme values
cv::minMaxLoc(disp_l, &minVal, &maxVal);
cout << "Min disp: Max value" << minVal << maxVal; //numberOfDisparities.= (maxVal - minVal)
//-- Display it as a CV_8UC1 image
disp_l.convertTo(disp8u_l, CV_8U, 255 / (maxVal - minVal));//(numberOfDisparities*16.)
cv::minMaxLoc(disp_r, &minVal, &maxVal);
cout << "Min disp: Max value" << minVal << maxVal; //numberOfDisparities.= (maxVal - minVal)
//-- Display it as a CV_8UC1 image
disp_r.convertTo(disp8u_r, CV_8U, 255 / (maxVal - minVal));//(numberOfDisparities*16.)
cv::normalize(disp8u_l, disp8u_l, 0, 255, CV_MINMAX, CV_8UC1); // obtain normalized image
cv::normalize(disp8u_r, disp8u_r, 0, 255, CV_MINMAX, CV_8UC1); // obtain normalized image
cv::imshow("Left", leftImage);
cv::imshow("Right", rightImage);
cv::imshow("Elas_left", disp8u_l);
cv::imshow("Elas_right", disp8u_r);
cv::imwrite("Elas_left.png", disp8u_l);
cv::imwrite("Elas_right.png", disp8u_r);
cout << endl << "Over" << endl;
//cv::waitKey(0);
return 0;
}
论文原文+库文件+基于VS2015的工程实现等相关源代码见:ELAS算法原文+库文件+VS2015x64实现。