opencv / opencv_contrib

Repository for OpenCV's extra modules
Apache License 2.0
9.44k stars 5.76k forks source link

Error while using StereoBinarySGBM to compute Disparity #925

Open TheShadow29 opened 7 years ago

TheShadow29 commented 7 years ago
System information (version)
mshabunin commented 7 years ago

I tried to run example_stereo_sample aloeL.jpg aloeR.jpg and it works fine, default algorithm is STEREO_BINARY_SGM which uses an instance of cv::stereo::StereoBinarySGBM. Please provide more info.

TheShadow29 commented 7 years ago

@mshabunin I am unsure what exact details I should give. Do let me know what more would be required.

I am using OpenCV and PCL in conjunction with ROS. Upto the point of the error in the code, PCL and ROS is not really being used. Everything else kept the same This works:

cv::Ptr<cv::StereoSGBM> sgbm;
sgbm = cv::StereoSGBM::create(0,16,3)

This doesn't:

cv::Ptr<cv::stereo::StereoBinarySGBM> sgbm;
sgbm = cv::stereo::StereoBinarySGBM::create(0,16,3);

I have included the following:

#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/core/utility.hpp"
#include <opencv2/core/eigen.hpp>
#include "opencv2/stereo.hpp"
#include "opencv2/photo.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/imgproc/detail/distortion_model.hpp"
#include "opencv2/calib3d/calib3d_c.h"
#include "opencv2/ximgproc/disparity_filter.hpp"

My sgbm parameters settings looks like this: For the first one, I comment setBinaryKernel. Everything else remains the same.

void init_sgbm(const cv::Mat& left,int block_size = 5, int numberOfDisparities = 64)
{
    // int block_size = 5;
    num_disp = numberOfDisparities;
    wsize = block_size;
    std::cout << "line 39 \n";
    sgbm->setPreFilterCap(63);
    std::cout << "line 41 \n";
    int sgbmWinSize = block_size > 0 ? block_size : 3;
    // int numberOfDisparities = 64;
    sgbm->setBlockSize(sgbmWinSize);

    int cn = left.channels();

    cv::Size img_size = left.size();
    numberOfDisparities = numberOfDisparities > 0 ? numberOfDisparities : ((img_size.width/8) + 15) & -16;

    sgbm->setP1(8*cn*sgbmWinSize*sgbmWinSize);
    sgbm->setP2(32*cn*sgbmWinSize*sgbmWinSize);
    sgbm->setMinDisparity(0);
    sgbm->setNumDisparities(numberOfDisparities);
    sgbm->setUniquenessRatio(10);
    sgbm->setSpeckleWindowSize(100);
    sgbm->setSpeckleRange(32);
    sgbm->setDisp12MaxDiff(1);

    sgbm -> setBinaryKernelType(1);
}
mshabunin commented 7 years ago

Try to start with parameters from this example.

lablabla commented 5 years ago

I had the same problem.

It seems that when constructing the StereoBinarySGBM the params (specifically, the _numDisparities) are passed to the constructor of the parent Matching object.

When setting with the call sgbm->setNumDisparities, the underlying Matching object's numDisparities is not being updated.

When calling compute, the hamDist.create(left.rows, left.cols * (params.numDisparities + 1), CV_16S); line creates the matrix using StereoBinarySGBM's params.numDisparities, and the assert in hammingDistanceBlockMatching that fails is CV_Assert(cost.cols / (maxDisparity + 1) == leftImage.cols); is using maxDisparity of the underlying Matching

What happens is that Matching's numDisparity is 16, set when constructed, and StereoBinarySGBM's numDisparity can be different depending on numberOfDisparities in your init_sgbm function.

If they differ, it will cause the error.

What I did was to not call the setNumDisparites but to set the final numDisparity in the constructor and it solved the problem. Though the right thing to do will obviously to fix this.