Ask Your Question

StereoBM CPU and StereoBM GPU versions on OpenCV give very different output.

asked 2018-02-26 07:14:47 -0600 gravatar image

updated 2019-10-23 21:12:32 -0600

supra56 gravatar image

I find a huge difference between the outputs of the CPU and GPU versions of StereoBM. I have compiled a GPU version of OpenCV 3.2 on my machine. I am attaching the outputs of both CPU and GPU, along with the GPU code.

StereoBM GPU StereoBM GPU

StereoBM CPU StereoBM CPU

Here is the code:

#include "opencv2/opencv.hpp"
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/cudaarithm.hpp"
#include <iostream>
#include <stdio.h>
#include <limits.h>

using namespace cv;

int main()
cv::Mat img1, img2;

img1 = imread( "~/left.png", cv::IMREAD_GRAYSCALE);
img2 = imread( "~/right.png", cv::IMREAD_GRAYSCALE);

cuda::GpuMat d_left, d_right;
Ptr<cuda::StereoBM> bm;
bm = cuda::createStereoBM(64, 11); //numDisparities=64, windowSize=11
Mat disp(img1.size(), CV_8U);

cuda::GpuMat d_disp(img1.size(), CV_8U);
cuda::GpuMat d_disp_color(img1.size(), CV_8U);

bm->compute(d_right, d_left, d_disp);
cuda::drawColorDisp(d_disp, d_disp_color, 64);;
imwrite("~/disparity.png", disp);;
imwrite("~/disparity_color.png", disp);

return 0;

The Output of StereoBM CPU is obtained with the same parameters as StereoBM GPU. In addition to that, StereoBM CPU has following parameters:

> preFilterSize = 9,
> preFilterCap = 31,
> wsize = 11,
> numDisparities = 64,
> minDisparity = 0,
> uniquenessRatio = 0,
> textureThreshold = 0,
> speckleWindowSize = 400,
> speckleRange = 4,
> disp12MaxDiff = 0.
edit retag flag offensive close merge delete



can you try with 16 bit images for disparity (doc is here)?

LBerger gravatar imageLBerger ( 2018-02-26 07:29:09 -0600 )edit

Look at the source code and you'll see that many of those parameters are ignored. There is no L/R check on the CUDA version for instance and it also won't give you subpixel disparity.

Der Luftmensch gravatar imageDer Luftmensch ( 2019-10-24 06:40:41 -0600 )edit

1 answer

Sort by ยป oldest newest most voted

answered 2019-10-22 20:41:30 -0600

MaxD gravatar image

updated 2019-10-28 22:14:14 -0600

cpu stereoBM takes the result of Sobel operator applied to the input images, while cuda::stereoBM uses the original images.

Block matching is sensitive to illumination changes. It might be the reason why cuda::stereoBM returns poor disparity map. Edge information is robust to these changes, so stereoBM outputs a better disparity map.


It appears I was wrong when I said that cuda::stereoBM did not use Sobel operator. Actually, it does apply the operator if preset_ (use setPreFilterType) is set to 1, but it is turned off by the default. This is the case in the code above. BTW, preFilterCap_, used in Sobel, has the same default value in cpu and cuda stereoBM

As was mentioned by Der Luffmensch, cuda::stereoBM does not work with negative and subpixel disparities.

One more difference is that invalid and filtered out disparities are set to zero, but not to a value out of the disparity range as done in cpu stereoBM.

edit flag offensive delete link more

Question Tools

1 follower


Asked: 2018-02-26 07:14:47 -0600

Seen: 1,446 times

Last updated: Oct 28 '19