2016-03-09 67 views
4

我正在嘗試使用StereoBM來獲取兩幅圖像的視差圖。我嘗試了一些示例代碼和圖像。他們工作正常。但是,當我嘗試自己的圖像時,地圖非常糟糕,非常嘈雜。差使用opencv的視差圖StereoBM

enter image description here

enter image description here

enter image description here

我StereoBM參數

sbm.state->SADWindowSize = 25; 
sbm.state->numberOfDisparities = 128; 
sbm.state->preFilterSize = 5; 
sbm.state->preFilterCap = 61; 
sbm.state->minDisparity = -39; 
sbm.state->textureThreshold = 507; 
sbm.state->uniquenessRatio = 0; 
sbm.state->speckleWindowSize = 0; 
sbm.state->speckleRange = 8; 
sbm.state->disp12MaxDiff = 1; 

我的問題是

  1. 有關我的圖像的任何問題?
  2. 如果沒有攝像頭校準,是否可以獲得很好的視差圖?我是否需要在立體聲之前糾正圖像

謝謝。

這裏是我糾正圖像

Mat img_1 = imread("image1.jpg", CV_LOAD_IMAGE_GRAYSCALE); 
Mat img_2 = imread("image2.jpg", CV_LOAD_IMAGE_GRAYSCALE); 

int minHessian = 430; 
SurfFeatureDetector detector(minHessian); 
std::vector<KeyPoint> keypoints_1, keypoints_2; 
detector.detect(img_1, keypoints_1); 
detector.detect(img_2, keypoints_2); 

//-- Step 2: Calculate descriptors (feature vectors) 
SurfDescriptorExtractor extractor; 
Mat descriptors_1, descriptors_2; 
extractor.compute(img_1, keypoints_1, descriptors_1); 
extractor.compute(img_2, keypoints_2, descriptors_2); 

//-- Step 3: Matching descriptor vectors with a brute force matcher 
BFMatcher matcher(NORM_L1, true); //BFMatcher matcher(NORM_L2); 

std::vector<DMatch> matches; 
matcher.match(descriptors_1, descriptors_2, matches); 

double max_dist = 0; double min_dist = 100; 
//-- Quick calculation of max and min distances between keypoints 
for(int i = 0; i < matches.size(); i++) 
{ double dist = matches[i].distance; 
    if(dist < min_dist) min_dist = dist; 
    if(dist > max_dist) max_dist = dist; 
} 

std::vector<DMatch> good_matches; 
vector<Point2f>imgpts1,imgpts2; 
for(int i = 0; i < matches.size(); i++) 
{ 
    if(matches[i].distance <= max(4.5*min_dist, 0.02)){ 
     good_matches.push_back(matches[i]); 
     imgpts1.push_back(keypoints_1[matches[i].queryIdx].pt); 
     imgpts2.push_back(keypoints_2[matches[i].trainIdx].pt); 
    } 

} 

std::vector<uchar> status; 
cv::Mat F = cv::findFundamentalMat(imgpts1, imgpts2, cv::FM_8POINT, 3., 0.99, status); //FM_RANSAC 

Mat H1,H2; 
cv::stereoRectifyUncalibrated(imgpts1, imgpts1, F, img_1.size(), H1, H2); 

cv::Mat rectified1(img_1.size(), img_1.type()); 
cv::warpPerspective(img_1, rectified1, H1, img_1.size()); 

cv::Mat rectified2(img_2.size(), img_2.type()); 
cv::warpPerspective(img_2, rectified2, H2, img_2.size()); 

StereoBM sbm; 
sbm.state->SADWindowSize = 25; 
sbm.state->numberOfDisparities = 128; 
sbm.state->preFilterSize = 5; 
sbm.state->preFilterCap = 61; 
sbm.state->minDisparity = -39; 
sbm.state->textureThreshold = 507; 
sbm.state->uniquenessRatio = 0; 
sbm.state->speckleWindowSize = 0; 
sbm.state->speckleRange = 8; 
sbm.state->disp12MaxDiff = 1; 

Mat disp,disp8; 
sbm(rectified1, rectified2, disp); 

整流圖像和視差圖碼在這裏

enter image description here

enter image description here

enter image description here

enter image description here

+0

是的,他們需要被糾正,你可以在[文檔]閱讀(http://docs.opencv.org/2.4/modules/calib3d/ doc/camera_calibration_and_3d_reconstruction.html#stereobm-operator) – Berriel

+0

@Berriel可以在沒有任何相機信息的情況下糾正圖像?對不起,我是新手。我讀了stereo_match.cpp。它需要相機的內在參數。 – fnhdx

回答

4
  1. 您的圖片沒有特別的問題。但是,如果計算時間不重要,我建議你使用更大的分辨率。另外,如果可能的話,您最好還是使用未壓縮的圖像格式。

  2. 您校準立體相機以糾正立體照片。喲確實需要糾正照片,但也可以在沒有校準照相機的情況下進行糾正。如果您只有幾張圖片需要處理,您可以通過移動或旋轉圖像以使匹配點位於同一行上,在Photoshop或類似的工具中進行。如果你有更多的圖片需要處理,你可以像你在代碼中嘗試的那樣做。

我沒有仔細檢查你的代碼,但我想你應該檢查匹配點是否在同一行。

在您的示例圖片中,實際上是這種情況,使用StereoSGMB而不是StereoBM,我得到了一些更好但仍非常嘈雜的結果。

enter image description here

這是一個有點參數調整,以獲得StereoSGMB了良好的效果。還要注意,由於塊具有紋理表面,因此後面塊的結果比前面的塊要好得多。

這是我使用的參數:

Ptr<StereoSGBM> sgbm = StereoSGBM::create(0, //int minDisparity 
             96,  //int numDisparities 
             5,  //int SADWindowSize 
             600, //int P1 = 0 
             2400, //int P2 = 0 
             20,  //int disp12MaxDiff = 0 
             16,  //int preFilterCap = 0 
             1,  //int uniquenessRatio = 0 
             100, //int speckleWindowSize = 0 
             20,  //int speckleRange = 0 
             true); //bool fullDP = false 

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

感謝您的回答。我認爲紋理表面是關鍵。我通過使用紋理對象得到了更好的效果。 – fnhdx