Ask Your Question
1 to cpp

asked 2014-02-22 20:50:45 -0600

flynnt gravatar image

Hi there. I'd like to generate a disparity map from a stereo image in C++. The C++ sample is a bit large and hard to strip out what I really want. The Python version was easier to strip down. Here is my stripped down python version:

#!/usr/bin/env python

if __name__ == '__main__':
    print 'loading images...'
    imgL = cv2.pyrDown( cv2.imread('aloeL.jpg') )  # downscale images for faster processing
    imgR = cv2.pyrDown( cv2.imread('aloeR.jpg') )

    # disparity range is tuned for 'aloe' image pair
    window_size = 3
    min_disp = 16
    num_disp = 112-min_disp
    stereo = cv2.StereoSGBM(minDisparity = min_disp,
        numDisparities = num_disp,
        SADWindowSize = window_size,
        uniquenessRatio = 10,
        speckleWindowSize = 100,
        speckleRange = 32,
        disp12MaxDiff = 1,
        P1 = 8*3*window_size**2,
        P2 = 32*3*window_size**2,
        fullDP = False

    print 'computing disparity...'
    disp = stereo.compute(imgL, imgR).astype(np.float32) / 16.0

    cv2.imshow('left', imgL)
    cv2.imshow('disparity', (disp-min_disp)/num_disp)

By comparing to the cpp sample, I converted the above python script to cpp. I think I did it right, but am having trouble getting data within range to view the result. I need a second set of eyes on this code. What did I screw up? Here's my cpp code:

void bringWithinRange(void *inptr, void *outptr, int width, int height, int min, int num)
    int *iptr = (int *)inptr;
    float *fptr = (float *)outptr;

    for(int i=0; i<width*height; i++)
        float value = (float)iptr[i];
        float newvalue = ((value/16.0f) - min) / num;
        fptr[i] = newvalue;

int main(int argc, char *argv[]) 
    int window_size = 3;
    int min_disp = 16;
    int num_disp = 112-min_disp;

    StereoSGBM sgbm = StereoSGBM(
         min_disp, // min_disp
         num_disp, // num_disp
         window_size, // SADWindowSize
         8*3*window_size*window_size, // P1
         32*3*window_size*window_size, // P2
         1, // disp12MaxDiff
         10, // uniquenessRatio
         100, // speckleWindowSize
         32, // speckleRange
         false // fullDP

    Mat left = imread("aloeL.jpg", -1);
    Mat right = imread("aloeR.jpg", -1);
    Mat disparity, disparity8, disparity32;

    sgbm(left, right, disparity);
    disparity.convertTo(disparity32, CV_32F);
    bringWithinRange(disparity.ptr(), disparity32.ptr(), disparity.cols, disparity.rows, min_disp, num_disp);

    namedWindow("Disparity", 0);
    imshow("disparity", disparity32);

    return 0;
edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted

answered 2014-02-23 18:57:41 -0600

I think that what you are trying to accomplish by:

disparity.convertTo(disparity32, CV_32F);
bringWithinRange(disparity.ptr(), disparity32.ptr(), disparity.cols, disparity.rows, min_disp, num_disp);
namedWindow("Disparity", 0);
imshow("disparity", disparity32);

Can be accomplished simply by this:

disparity.convertTo(disparity8, CV_8U, 255/(num_disp*16.));
namedWindow("Disparity", 0);
imshow("disparity", disparity8);
edit flag offensive delete link more


well, that's closer. What I get now is a mostly dark gray image with a few white spots. Those white spots seem to be where the plant is closest to the viewer.

flynnt gravatar imageflynnt ( 2014-03-08 13:54:02 -0600 )edit

Keep in mind that if the objects in your scene are relatively far away from the camera they will have a very low disparity value, which corresponds to a very dark value in gray scale. The white spots are probably mismatches. If what you want to do is visualize the disparity map, maybe it will be a good idea to perform a histogram equalization on the disparity image (disparity8) to make it better suited for human eyes.

Martin Peris gravatar imageMartin Peris ( 2014-03-09 20:58:09 -0600 )edit

Also, keep in mind that the accuracy (or should I say inaccuracy...) of your disparity image will depend greatly on the quality of your stereo camera calibration, the texture of the objects on your scene, illumination and the parameters that you use for the StereoSGBM algorithm. Don't expect too much

Martin Peris gravatar imageMartin Peris ( 2014-03-09 21:00:56 -0600 )edit

That's why I chose to start from an existing example that is provided in the examples directory by OpenCV. It uses a known, existing image (also provided in the OpenCV example source) that when you run the python script on it, displays a very clear and accurate looking image. I'm trying to figure out the c++ equivalent of that python script. I'll eventually want this running as a part of a larger c++ program. I know I'll have to learn how to tweak things so this will work for images I take myself, but for now, I'd be happy if I could get the same result in c++ that i can get via python with the same image and parameters.

flynnt gravatar imageflynnt ( 2014-03-15 12:24:39 -0600 )edit

answered 2016-05-23 03:10:59 -0600

bymulker gravatar image


I dont know if it is late but i can send the settings for sgbm :

sStereo->alg = StereoCameraRig::STEREO_SGBM;
  sStereo->SADWindowSize = 3;
  sStereo->numberOfDisparities = 192;
  sStereo->preFilterCap = 4;
  sStereo->minDisparity = -64;
  sStereo->uniquenessRatio = 1;
  sStereo->speckleWindowSize = 150;
  sStereo->speckleRange = 1;
  sStereo->disp12MaxDiff = 1;
  sStereo->fullDP = false;
  sStereo->P1 = 600;
  sStereo->P2 = 2400;
  sStereo->textureThreshold = 500;


  stRig.getDisparityMap(viewL, viewR, dispMap, false);

  normalize(dispMap, disp8, 0, 255, CV_MINMAX, CV_8U);

  showImage(disp8, true);

In any case i got my tiny shiny disparity map :) but cannot reproject3d as i cannot see any extrinsics files shipped with OpenCV!! (the instrinscs file is 'intrinsics.yml' file if i'm not wrong) Can someone point out where or a better sample maybe?

edit flag offensive delete link more

Question Tools


Asked: 2014-02-22 20:50:45 -0600

Seen: 1,442 times

Last updated: Feb 23 '14