1. 程式人生 > >OpenCV3.0立體匹配演算法對比研究(SGBM、BM、GC)

OpenCV3.0立體匹配演算法對比研究(SGBM、BM、GC)

立體匹配演算法對比研究

引言:基於OpenCV3.0,對BM、SGBM和GC演算法進行了對比測試研究。由於SGBM演算法視差效果好速度快的特點,常常被廣泛應用和改進,本文針對SGBM演算法主要引數設定作了對比測試,以供大家參考。

BM:Block Matching ,採用SAD方法計算匹配代價;

                 與原方法不同點:

  1.  預設執行單通道DP演算法,只用了5個方向,而fullDP使能時則使用8個方向(可能需要佔用大量記憶體);
  2.  增加了一些BM演算法中的預處理和後處理程式;

GC:OpenCV3.0中沒有實現,可以在OpenCV以下版本中找到。該方法效果是最好的,但是速度太慢,不能達到實時的匹配效率;

1、SGBM

程式碼:

#include "stdafx.h"
#include "opencv2/opencv.hpp
using namespace std;
using namespace cv;

int _tmain(int argc, _TCHAR* argv[])
{
	Mat left = imread("imgL.jpg", IMREAD_GRAYSCALE);
	Mat right = imread("imgR.jpg", IMREAD_GRAYSCALE);
	Mat disp;

	int mindisparity = 0;
	int ndisparities = 64;  
	int SADWindowSize = 11; 

	//SGBM
	cv::Ptr<cv::StereoSGBM> sgbm = cv::StereoSGBM::create(mindisparity, ndisparities, SADWindowSize);
	int P1 = 8 * left.channels() * SADWindowSize* SADWindowSize;
	int P2 = 32 * left.channels() * SADWindowSize* SADWindowSize;
	sgbm->setP1(P1);
	sgbm->setP2(P2);

	sgbm->setPreFilterCap(15);
	sgbm->setUniquenessRatio(10);
	sgbm->setSpeckleRange(2);
	sgbm->setSpeckleWindowSize(100);
	sgbm->setDisp12MaxDiff(1);
	//sgbm->setMode(cv::StereoSGBM::MODE_HH);

	sgbm->compute(left, right, disp);

	disp.convertTo(disp, CV_32F, 1.0 / 16);                //除以16得到真實視差值
	Mat disp8U = Mat(disp.rows, disp.cols, CV_8UC1);       //顯示
	normalize(disp, disp8U, 0, 255, NORM_MINMAX, CV_8UC1);

	imwrite("results/SGBM.jpg", disp8U);
	return 0;
}

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.jpg tsukuba_right.jpg
SADWindowSize = 5 SADWindowSize = 11 SADWindowSize = 21
P1 = 8 , P2 = 10 P1 = 8 , P2 = 32 P1 = 8 , P2 = 64
MODE_SGBM(5方向) MODE_HH(8方向)

總結:

1. blockSize(SADWindowSize) 越小,也就是匹配代價計算的視窗越小,視差圖噪聲越大;blockSize越大,視差圖越平滑;太大的size容易導致過平滑,並且誤匹配增多,體現在視差圖中空洞增多;
2. 懲罰係數控制視差圖的平滑度,P2>P1,P2越大則視差圖越平滑;
3. 八方向動態規劃較五方向改善效果不明顯,主要在影象邊緣能夠找到正確的匹配;

2、BM

程式碼:

#include "stdafx.h"
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;

int _tmain(int argc, _TCHAR* argv[])
{
	Mat left = imread("imgL.jpg", IMREAD_GRAYSCALE);
	Mat right = imread("imgR.jpg", IMREAD_GRAYSCALE);
	Mat disp;

	int mindisparity = 0;
	int ndisparities = 64;  
	int SADWindowSize = 11; 

	cv::Ptr<cv::StereoBM> bm = cv::StereoBM::create(ndisparities, SADWindowSize);
	// setter
	bm->setBlockSize(SADWindowSize);
	bm->setMinDisparity(mindisparity);
	bm->setNumDisparities(ndisparities);
	bm->setPreFilterSize(15);
	bm->setPreFilterCap(31);
	bm->setTextureThreshold(10);
	bm->setUniquenessRatio(10);
	bm->setDisp12MaxDiff(1);

	copyMakeBorder(left, left, 0, 0, 80, 0, IPL_BORDER_REPLICATE);  //防止黑邊
	copyMakeBorder(right, right, 0, 0, 80, 0, IPL_BORDER_REPLICATE);
	bm->compute(left, right, disp);

	disp.convertTo(disp, CV_32F, 1.0 / 16); //除以16得到真實視差值
	disp = disp.colRange(80, disp.cols);
	Mat disp8U = Mat(disp.rows, disp.cols, CV_8UC1);
	normalize(disp, disp8U, 0, 255, NORM_MINMAX, CV_8UC1);
	imwrite("results/BM.jpg", disp8U);
	return 0;
}
SADWindowSize = 5 SADWindowSize = 21 SADWindowSize = 31 SADWindowSize = 41

3、GC


總結:

SGBM BM GC

視差效果:BM < SGBM < GC;

處理速度:BM > SGBM > GC ;

參考: