2012-06-25 39 views
5

我一直在嘗試糾正和建立使用OpenCV stereoRectifyUncalibrated一對圖像的差異映射,但我沒有得到很好的結果。我的代碼是:opencv stereoRectifyUncalibrated問題

template<class T> 
T convertNumber(string& number) 
{ 
    istringstream ss(number); 
    T t; 
    ss >> t; 
    return t; 
} 

void readPoints(vector<Point2f>& points, string filename) 
{ 
    fstream filest(filename.c_str(), ios::in); 
    string line; 

    assert(filest != NULL); 

    getline(filest, line); 
    do{ 
     int posEsp = line.find_first_of(' '); 
     string posX = line.substr(0, posEsp); 
     string posY = line.substr(posEsp+1, line.size() - posEsp); 

     float X = convertNumber<float>(posX); 
     float Y = convertNumber<float>(posY); 

     Point2f pnt = Point2f(X, Y); 
     points.push_back(pnt); 
     getline(filest, line); 
    }while(!filest.eof()); 

    filest.close(); 
} 

void drawKeypointSequence(Mat lFrame, Mat rFrame, vector<KeyPoint>& lKeyp, vector<KeyPoint>& rKeyp) 
{ 
    namedWindow("prevFrame", WINDOW_AUTOSIZE); 
    namedWindow("currFrame", WINDOW_AUTOSIZE); 
    moveWindow("prevFrame", 0, 300); 
    moveWindow("currFrame", 650, 300); 
    Mat rFrameAux; 
    rFrame.copyTo(rFrameAux); 
    Mat lFrameAux; 
    lFrame.copyTo(lFrameAux); 

    int size = rKeyp.size(); 
    for(int i=0; i<size; i++) 
    { 
     vector<KeyPoint> drawRightKeyp; 
     vector<KeyPoint> drawleftKeyp; 

     drawRightKeyp.push_back(rKeyp[i]); 
     drawleftKeyp.push_back(lKeyp[i]); 

     cout << rKeyp[i].pt << " <<<>>> " << lKeyp[i].pt << endl; 

     drawKeypoints(rFrameAux, drawRightKeyp, rFrameAux, Scalar::all(255), DrawMatchesFlags::DRAW_OVER_OUTIMG); 
     drawKeypoints(lFrameAux, drawleftKeyp, lFrameAux, Scalar::all(255), DrawMatchesFlags::DRAW_OVER_OUTIMG); 

     imshow("currFrame", rFrameAux); 
     imshow("prevFrame", lFrameAux); 
     waitKey(0); 
    } 
    imwrite("RightKeypFrame.jpg", rFrameAux); 
    imwrite("LeftKeypFrame.jpg", lFrameAux); 
} 
int main(int argc, char* argv[]) 
{ 
    StereoBM stereo(StereoBM::BASIC_PRESET, 16*5, 21); 
    double ndisp = 16*4; 
    assert(argc == 5); 
    string rightImgFilename(argv[1]);  // Right image (current frame) 
    string leftImgFilename(argv[2]);  // Left image (previous frame) 
    string rightPointsFilename(argv[3]); // Right image points file 
    string leftPointsFilename(argv[4]);  // Left image points file 

    Mat rightFrame = imread(rightImgFilename.c_str(), 0); 
    Mat leftFrame = imread(leftImgFilename.c_str(), 0); 

    vector<Point2f> rightPoints; 
    vector<Point2f> leftPoints; 

    vector<KeyPoint> rightKeyp; 
    vector<KeyPoint> leftKeyp; 

    readPoints(rightPoints, rightPointsFilename); 
    readPoints(leftPoints, leftPointsFilename); 
    assert(rightPoints.size() == leftPoints.size()); 

    KeyPoint::convert(rightPoints, rightKeyp); 
    KeyPoint::convert(leftPoints, leftKeyp); 

    // Desenha os keypoints sequencialmente, de forma a testar a consistência do matching 
    drawKeypointSequence(leftFrame, rightFrame, leftKeyp, rightKeyp); 

    Mat fundMatrix = findFundamentalMat(leftPoints, rightPoints, CV_FM_8POINT); 
    Mat homRight; 
    Mat homLeft; 
    Mat disp16 = Mat(rightFrame.rows, leftFrame.cols, CV_16S); 
    Mat disp8 = Mat(rightFrame.rows, leftFrame.cols, CV_8UC1); 
    stereoRectifyUncalibrated(leftPoints, rightPoints, fundMatrix, rightFrame.size(), homLeft, homRight); 

    warpPerspective(rightFrame, rightFrame, homRight, rightFrame.size()); 
    warpPerspective(leftFrame, leftFrame, homLeft, leftFrame.size()); 


    namedWindow("currFrame", WINDOW_AUTOSIZE); 
    namedWindow("prevFrame", WINDOW_AUTOSIZE); 
    moveWindow("currFrame", 650, 300); 
    moveWindow("prevFrame", 0, 300); 
    imshow("currFrame", rightFrame); 
    imshow("prevFrame", leftFrame); 

    imwrite("RectfRight.jpg", rightFrame); 
    imwrite("RectfLeft.jpg", leftFrame); 

    waitKey(0); 

    stereo(rightFrame, leftFrame, disp16, CV_16S); 

    disp16.convertTo(disp8, CV_8UC1, 255/ndisp); 
    FileStorage file("disp_map.xml", FileStorage::WRITE); 
    file << "disparity" << disp8; 
    file.release(); 
    imshow("disparity", disp8); 
    imwrite("disparity.jpg", disp8); 
    moveWindow("disparity", 0, 0); 

    waitKey(0); 
} 

drawKeyPoint序列是我可視化檢查兩個圖像所具有的點的一致性的方式。通過依次繪製每個關鍵點,我可以確定,關於圖像A的關鍵點i是關於圖像B的關鍵點。

我也試着玩過ndisp參數,但沒有多大幫助。

我嘗試了以下對圖像:

LeftImage

RightImage

得到以下糾正對:

RectifiedLeft

RectifiedRight

最後,下面視差圖

DisparityMap

哪像你所看到的,是相當糟糕。我還嘗試了以下stereoRectifyUncalibrated示例的同一對圖像:http://programmingexamples.net/wiki/OpenCV/WishList/StereoRectifyUncalibrated和來自opencv教程代碼示例的SBM_Sample.cpp構建視差圖,並得到了非常相似的結果。

我使用的是opencv 2.4

在此先感謝!

+0

我面臨着非常類似的問題。你找到解決方案嗎? –

回答

0

我會建議使用棋盤進行立體校準,或者用棋盤拍攝多張照片,並在您的計算機上使用stereocalibrate.cpp。我在說,因爲您使用的是stereorectifyuncalibrated,雖然算法不需要知道相機的內部參數,但它很大程度上取決於極線幾何。因此,如果相機鏡頭有明顯的失真,最好在計算基本矩陣並調用此函數之前對其進行糾正。例如,可以通過使用calibrateCamera()分別爲立體相機的每個頭部估計失真係數。然後,可以使用undistort()來校正圖像,或者只需使用undistortPoints()就可以校正點座標。

2

除了可能存在的校準問題,您的圖像顯然缺乏一些用於立體塊匹配工作的紋理。 該算法會在扁平(非tetxured)部件上看到許多歧義和太大的差異。

但是請注意,關鍵點似乎匹配得很好,所以即使整流輸出看起來很奇怪,它也許是正確的。

您可以根據Middlebury stereo page的標準圖像測試您的代碼以進行完整性檢查。