OpenCV3.0立體匹配演算法對比研究(SGBM、BM、GC)
阿新 • • 發佈:2019-01-27
立體匹配演算法對比研究
引言:基於OpenCV3.0,對BM、SGBM和GC演算法進行了對比測試研究。由於SGBM演算法視差效果好速度快的特點,常常被廣泛應用和改進,本文針對SGBM演算法主要引數設定作了對比測試,以供大家參考。
BM:Block Matching ,採用SAD方法計算匹配代價;
與原方法不同點:
- 預設執行單通道DP演算法,只用了5個方向,而fullDP使能時則使用8個方向(可能需要佔用大量記憶體);
- 增加了一些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 ;
參考: