1
votes

I am new to stereo camera(or perhaps, new to opencv). However, i need to do my FYP that requires stereo camera to measure distance of an object selected.

What are the steps taken to get an accurate disparity map? As far as i know, we need to calibrate to get intrinsic & extrinsic parameters , undistort it , then rectify it then only calculate the disparity mapping.

I've done calibration to get intrinsic and extrinsic values. Then i tried to rectify it and i get this RMS value_and_reprojection_error_value.jpg. Question is, at what value is acceptable for disparity mapping?

After that, I start to do disparity mapping by using Block Matching. Here is my code `

int main(void)
{

   VideoCapture camLeft(0);
   VideoCapture camRight(2);

   camLeft.set(CV_CAP_PROP_FRAME_WIDTH, 500);
   camLeft.set(CV_CAP_PROP_FRAME_HEIGHT, 500);
   camRight.set(CV_CAP_PROP_FRAME_WIDTH, 500);
   camRight.set(CV_CAP_PROP_FRAME_HEIGHT, 500);



   if (!camLeft.isOpened() || !camRight.isOpened()) {
      cout << "Error: Stereo Cameras not found or there is some problem       connecting them. Please check your cameras.\n";
      exit(-1);
     }


//Read intrinsice parameters
string intrinsic_filepath = "C:/Users/Jerry/Documents/Visual Studio 2015/Projects/OctStereoCalibration/OctStereoCalibration/intrinsics.yml";
FileStorage fs(intrinsic_filepath, FileStorage::READ);
if (!fs.isOpened())
{
    printf("Failed to open intrinsics.yml");
    return -1;
}
Mat M1, D1, M2, D2;
fs["M1"] >> M1;
fs["D1"] >> D1;
fs["M2"] >> M2;
fs["D2"] >> D2;

//Read Extrinsic Parameters
string extrinsic_filepath = "C:/Users/Jerry/Documents/Visual Studio 2015/Projects/OctStereoCalibration/OctStereoCalibration/extrinsics.yml";
fs.open(extrinsic_filepath, FileStorage::READ);
if (!fs.isOpened())
{
    printf("Failed to open extrinsics");
    return -1;
}

Mat R, T, R1, P1, R2, P2;
fs["R"] >> R;
fs["T"] >> T;

Mat frame1, frame2, gray1, gray2, copyImageLeft, copyImageRight;
int counter = 0;

camLeft >> frame1;
camRight >> frame2;

Size img_size = frame1.size();
Rect roi1, roi2;
Mat Q;

stereoRectify(M1, D1, M2, D2, img_size, R, T, R1, R2, P1, P2, Q, CALIB_ZERO_DISPARITY, -1, img_size, &roi1, &roi2);

Mat map11, map12, map21, map22;
initUndistortRectifyMap(M1, D1, R1, P1, img_size, CV_16SC2, map11, map12);
initUndistortRectifyMap(M2, D2, R2, P2, img_size, CV_16SC2, map21, map22);



while (1) {
    createTrackbars();
    on_trackbar(0, 0);

    bm->setROI1(roi1);
    bm->setROI2(roi2);
    bm->setPreFilterCap(PreFilterCap);
    bm->setPreFilterSize(PrefilterSize);
    bm->setBlockSize(SADWindowSize);
    bm->setMinDisparity(MinDisparity);  //0
    bm->setNumDisparities(numberOfDisparities);
    bm->setTextureThreshold(TextureThreshold);
    bm->setUniquenessRatio(UniquenessRatio);
    bm->setSpeckleWindowSize(SpeckleWindowSize);
    bm->setSpeckleRange(SpeckleRange);
    bm->setDisp12MaxDiff(Disp12MaxDiff);    //1

    camLeft >> frame1;
    camRight >> frame2;
    if ((frame1.rows != frame2.rows) || (frame1.cols != frame2.cols)) {
        cout << "Error: Images from both cameras are not of some size. Please check the size of each camera.\n";
        exit(-1);
    }
    //frame1.copyTo(copyImageLeft);
    //frame2.copyTo(copyImageRight);
    imshow("Cam1", frame1);
    imshow("Cam2", frame2);

    /************************* STEREO ***********************/

    cvtColor(frame1, gray1, CV_RGB2GRAY);
    cvtColor(frame2, gray2, CV_RGB2GRAY);

    int64 t = getTickCount();

    Mat img1r, img2r;
    remap(gray1, img1r, map11, map12, INTER_LINEAR);
    remap(gray2, img2r, map21, map22, INTER_LINEAR);

    Mat disp, disp8;
    Mat XYZ;
    bm->compute(img1r, img2r, disp);
    t = getTickCount() - t;
    printf("Time elapsed: %fms\n", t * 1000 / getTickFrequency());

    disp.convertTo(disp8, CV_8U, 255 / (numberOfDisparities*16.));
    //normalize(disp, disp8, 0, 255, CV_MINMAX, CV_8U);
    imshow("disparity", disp8);

    //reprojectImageTo3D(disp8, XYZ, Q, false, CV_32F);

    char keyBoardInput = (char)waitKey(50);
    if (keyBoardInput == 'q' || keyBoardInput == 'Q') {
        break;
        return(0);
    }
}

} `

My BM parameters are :

int PreFilterCap = 31; int PrefilterSize = 21; int SADWindowSize = 33; int MinDisparity = 0; int numberOfDisparities = 48; int TextureThreshold = 29; int UniquenessRatio = 15; int SpeckleWindowSize = 32; int SpeckleRange = 32; int Disp12MaxDiff = 0; The disparity Map I get is : Disparity map

How to get a better quality of disparity mapping? Thanks

1

1 Answers

0
votes

You can try changing the value of the parameter window size and number of disparities.For different Depth different set of values work.
The second option is to use SGBM instead of sbm and the third method that I am aware of is to use Gaussian pyramids to calculate disparity at low resolution of left and right cameras and then fuse them with some simple logic. The calculation of disparity map at low level has the benefit that as you go down the pyramid level holes will start filling making the final disparity map better.