2012-06-25 22 views
5

He intentado rectificar y crear el mapeo de disparidad para un par de imágenes usando OpenCV stereoRectifyUncalibrated, pero no estoy obteniendo muy buenos resultados. Mi código es:Problemas con 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); 
} 

secuencia drawKeyPoint es la manera puedo comprobar visualmente la consistencia de los puntos que tengo para ambas imágenes. Dibujando cada uno de sus puntos clave en secuencia, puedo estar seguro de que el punto clave i en la imagen A es el punto clave i en la imagen B.

También he intentado jugar con el parámetro ndisp, pero no ayudó mucho.

que probamos para el siguiente par de imágenes:

LeftImage

RightImage

tiene el siguiente par corregido:

RectifiedLeft

RectifiedRight

y, finalmente, el siguiente mapa de disparidad

DisparityMap

Lo cual, como se puede ver, es bastante malo. También probé el mismo par de imágenes con el siguiente ejemplo stereorectifyUncalibrated: http://programmingexamples.net/wiki/OpenCV/WishList/StereoRectifyUncalibrated y SBM_Sample.cpp del código tutorial de opencv muestrea para construir el mapa de disparidad, y obtuve un resultado muy similar.

estoy usando OpenCV 2.4

Gracias de antemano!

+0

Estoy enfrentando problemas muy similares. ¿Encontraste una solución? –

Respuesta

0

Yo sugeriría hacer una calibración estéreo usando el tablero de ajedrez, o tomar varias fotos con un tablero de ajedrez y usar stereocalibrate.cpp en su computadora. Lo digo porque está usando stereorectifyuncalibrated, mientras que el algoritmo no necesita conocer los parámetros intrínsecos de las cámaras, depende en gran medida de la geometría epipolar. Por lo tanto, si las lentes de la cámara tienen una distorsión significativa, sería mejor corregirla antes de calcular la matriz fundamental y llamar a esta función. Por ejemplo, los coeficientes de distorsión se pueden estimar para cada cabezal de cámara estéreo por separado usando calibrateCamera(). Luego, las imágenes se pueden corregir usando undistort(), o solo las coordenadas de los puntos pueden corregirse con undistortPoints().

2

Además de los posibles problemas de calibración, las imágenes carecen claramente de cierta textura para que el emparejamiento estéreo coincida con el trabajo. Este algoritmo verá muchas ambigüedades y disparidades demasiado grandes en partes planas (no ajustadas).

Sin embargo, tenga en cuenta que los puntos clave parecen coincidir bien, por lo que incluso si el resultado de la rectificación parece extraño, probablemente sea correcto.

Puede probar su código con imágenes estándar del Middlebury stereo page para verificaciones de cordura.