2012-06-25 5 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 так я визуально проверить согласованность точек у меня есть для обоих изображений. Выбирая каждую из своих ключевых точек последовательно, я могу быть уверен, что ключевая точка i на изображении A является ключевой точкой i на изображении B.

Я также попытался сыграть с параметром ndisp, но это не помогло.

Я попробовал его для следующей пары изображений:

LeftImage

RightImage

получил следующее выпрямляется пара:

RectifiedLeft

RectifiedRight

и, наконец, следующая карта неравенство

DisparityMap

Который, как вы можете видеть, это очень плохо. Я также попробовал одну и ту же пару изображений со следующим примером: стереофонический эффект: http://programmingexamples.net/wiki/OpenCV/WishList/StereoRectifyUncalibrated и SBM_Sample.cpp из образцов кода учебного кода opencv для создания карты несоответствий и получил очень похожий результат.

Я использую OpenCV 2.4

Спасибо заранее!

+0

У меня очень похожие проблемы. Вы нашли решение? –

ответ

0

Я предлагаю выполнить стереокалькуляцию с помощью шахматной доски или сделать несколько снимков с помощью шахматной доски и использовать stereocalibrate.cpp на вашем компьютере. Я говорю это, потому что вы используете stereorectifyuncalibrated. Хотя алгоритму не нужно знать внутренние параметры камер, он в значительной степени зависит от эпиполярной геометрии. Поэтому, если объективы камеры имеют значительное искажение, лучше было бы исправить ее до вычисления основной матрицы и вызова этой функции. Например, коэффициенты искажения могут быть оценены для каждой головки стереокамеры отдельно, используя calibrateCamera(). Затем изображения можно исправить с помощью undistort(), или только координаты точки могут быть скорректированы с помощью undistortPoints().

2

Помимо возможных проблем с калибровкой, на ваших изображениях явно не хватает текстуры для совместимости стереоблоков. Этот алгоритм увидит много двусмысленностей и слишком большие различия на плоских (нетексированных) частях.

Обратите внимание, что ключевые точки, похоже, хорошо совпадают, поэтому даже если выход выпрямления кажется странным, это, вероятно, правильно.

Вы можете проверить свой код на стандартных изображениях с Middlebury stereo page для проверки работоспособности.