From 7661625c3918b6ed1891b1be66cfc5440aae8af1 Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Fri, 22 Mar 2013 01:05:30 +0400 Subject: [PATCH 1/5] converter stereo correspondence algorithms to the new style --- modules/calib3d/include/opencv2/calib3d.hpp | 136 ++++++++++-------- modules/calib3d/src/compat_stereo.cpp | 90 ------------ modules/calib3d/src/stereobm.cpp | 109 ++++++++++---- modules/calib3d/src/stereosgbm.cpp | 133 +++++++++++------ modules/calib3d/test/test_stereomatching.cpp | 17 ++- modules/gpu/perf/perf_calib3d.cpp | 4 +- samples/cpp/stereo_match.cpp | 50 +++---- .../calib3d/stereoBM/SBM_Sample.cpp | 6 +- 8 files changed, 292 insertions(+), 253 deletions(-) diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d.hpp index 989912cda8..de44148d03 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d.hpp @@ -12,6 +12,7 @@ // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -372,6 +373,8 @@ CVAPI(void) cvReprojectImageTo3D( const CvArr* disparityImage, #ifdef __cplusplus } +template<> CV_EXPORTS void cv::Ptr::delete_obj(); + ////////////////////////////////////////////////////////////////////////////////////////// class CV_EXPORTS CvLevMarq { @@ -673,84 +676,95 @@ CV_EXPORTS_W void correctMatches( InputArray F, InputArray points1, InputArray p class CV_EXPORTS_W StereoMatcher : public Algorithm { public: + enum { DISP_SHIFT=4, DISP_SCALE=(1 << DISP_SHIFT) }; + CV_WRAP virtual void compute( InputArray left, InputArray right, OutputArray disparity ) = 0; -}; -enum { STEREO_DISP_SCALE=16, STEREO_PREFILTER_NORMALIZED_RESPONSE = 0, STEREO_PREFILTER_XSOBEL = 1 }; + CV_WRAP virtual int getMinDisparity() const = 0; + CV_WRAP virtual void setMinDisparity(int minDisparity) = 0; -CV_EXPORTS Ptr createStereoBM(int numDisparities=0, int SADWindowSize=21); + CV_WRAP virtual int getNumDisparities() const = 0; + CV_WRAP virtual void setNumDisparities(int numDisparities) = 0; -CV_EXPORTS Ptr createStereoSGBM(int minDisparity, int numDisparities, int SADWindowSize, - int P1=0, int P2=0, int disp12MaxDiff=0, - int preFilterCap=0, int uniquenessRatio=0, - int speckleWindowSize=0, int speckleRange=0, - bool fullDP=false); + CV_WRAP virtual int getBlockSize() const = 0; + CV_WRAP virtual void setBlockSize(int blockSize) = 0; -template<> CV_EXPORTS void Ptr::delete_obj(); + CV_WRAP virtual int getSpeckleWindowSize() const = 0; + CV_WRAP virtual void setSpeckleWindowSize(int speckleWindowSize) = 0; + + CV_WRAP virtual int getSpeckleRange() const = 0; + CV_WRAP virtual void setSpeckleRange(int speckleRange) = 0; + + CV_WRAP virtual int getDisp12MaxDiff() const = 0; + CV_WRAP virtual void setDisp12MaxDiff(int disp12MaxDiff) = 0; +}; -// to be moved to "compat" module -class CV_EXPORTS_W StereoBM + +class CV_EXPORTS_W StereoBM : public StereoMatcher { public: - enum { PREFILTER_NORMALIZED_RESPONSE = 0, PREFILTER_XSOBEL = 1, - BASIC_PRESET=0, FISH_EYE_PRESET=1, NARROW_PRESET=2 }; - - //! the default constructor - CV_WRAP StereoBM(); - //! the full constructor taking the camera-specific preset, number of disparities and the SAD window size - CV_WRAP StereoBM(int preset, int ndisparities=0, int SADWindowSize=21); - //! the method that reinitializes the state. The previous content is destroyed - void init(int preset, int ndisparities=0, int SADWindowSize=21); - //! the stereo correspondence operator. Finds the disparity for the specified rectified stereo pair - CV_WRAP_AS(compute) void operator()( InputArray left, InputArray right, - OutputArray disparity, int disptype=CV_16S ); - - //! pointer to the underlying CvStereoBMState - Ptr state; + enum { PREFILTER_NORMALIZED_RESPONSE = 0, PREFILTER_XSOBEL = 1 }; + + CV_WRAP virtual int getPreFilterType() const = 0; + CV_WRAP virtual void setPreFilterType(int preFilterType) = 0; + + CV_WRAP virtual int getPreFilterSize() const = 0; + CV_WRAP virtual void setPreFilterSize(int preFilterSize) = 0; + + CV_WRAP virtual int getPreFilterCap() const = 0; + CV_WRAP virtual void setPreFilterCap(int preFilterCap) = 0; + + CV_WRAP virtual int getTextureThreshold() const = 0; + CV_WRAP virtual void setTextureThreshold(int textureThreshold) = 0; + + CV_WRAP virtual int getUniquenessRatio() const = 0; + CV_WRAP virtual void setUniquenessRatio(int uniquenessRatio) = 0; + + CV_WRAP virtual int getSmallerBlockSize() const = 0; + CV_WRAP virtual void setSmallerBlockSize(int blockSize) = 0; + + CV_WRAP virtual Rect getROI1() const = 0; + CV_WRAP virtual void setROI1(Rect roi1) = 0; + + CV_WRAP virtual Rect getROI2() const = 0; + CV_WRAP virtual void setROI2(Rect roi2) = 0; }; +CV_EXPORTS Ptr createStereoBM(int numDisparities=0, int blockSize=21); -// to be moved to "compat" module -class CV_EXPORTS_W StereoSGBM + +class CV_EXPORTS_W StereoSGBM : public StereoMatcher { public: - enum { DISP_SHIFT=4, DISP_SCALE = (1< sm; + enum { MODE_SGBM=0, MODE_HH=1 }; + + CV_WRAP virtual int getPreFilterCap() const = 0; + CV_WRAP virtual void setPreFilterCap(int preFilterCap) = 0; + + CV_WRAP virtual int getUniquenessRatio() const = 0; + CV_WRAP virtual void setUniquenessRatio(int uniquenessRatio) = 0; + + CV_WRAP virtual int getP1() const = 0; + CV_WRAP virtual void setP1(int P1) = 0; + + CV_WRAP virtual int getP2() const = 0; + CV_WRAP virtual void setP2(int P2) = 0; + + CV_WRAP virtual int getMode() const = 0; + CV_WRAP virtual void setMode(int mode) = 0; }; + +CV_EXPORTS Ptr createStereoSGBM(int minDisparity, int numDisparities, int blockSize, + int P1=0, int P2=0, int disp12MaxDiff=0, + int preFilterCap=0, int uniquenessRatio=0, + int speckleWindowSize=0, int speckleRange=0, + int mode=StereoSGBM::MODE_SGBM); + //! filters off speckles (small regions of incorrectly computed disparity) -CV_EXPORTS_W void filterSpeckles( InputOutputArray img, double newVal, int maxSpeckleSize, double maxDiff, +CV_EXPORTS_W void filterSpeckles( InputOutputArray img, double newVal, + int maxSpeckleSize, double maxDiff, InputOutputArray buf=noArray() ); //! computes valid disparity ROI from the valid ROIs of the rectified images (that are returned by cv::stereoRectify()) diff --git a/modules/calib3d/src/compat_stereo.cpp b/modules/calib3d/src/compat_stereo.cpp index 7b9ed33e41..f1d9834245 100644 --- a/modules/calib3d/src/compat_stereo.cpp +++ b/modules/calib3d/src/compat_stereo.cpp @@ -124,93 +124,3 @@ void cvValidateDisparity( CvArr* _disp, const CvArr* _cost, int minDisparity, cv::Mat disp = cv::cvarrToMat(_disp), cost = cv::cvarrToMat(_cost); cv::validateDisparity( disp, cost, minDisparity, numberOfDisparities, disp12MaxDiff ); } - -namespace cv -{ - -StereoBM::StereoBM() -{ init(BASIC_PRESET); } - -StereoBM::StereoBM(int _preset, int _ndisparities, int _SADWindowSize) -{ init(_preset, _ndisparities, _SADWindowSize); } - -void StereoBM::init(int _preset, int _ndisparities, int _SADWindowSize) -{ - state = cvCreateStereoBMState(_preset, _ndisparities); - state->SADWindowSize = _SADWindowSize; -} - -void StereoBM::operator()( InputArray _left, InputArray _right, - OutputArray _disparity, int disptype ) -{ - Mat left = _left.getMat(), right = _right.getMat(); - CV_Assert( disptype == CV_16S || disptype == CV_32F ); - _disparity.create(left.size(), disptype); - Mat disp = _disparity.getMat(); - - CvMat left_c = left, right_c = right, disp_c = disp; - cvFindStereoCorrespondenceBM(&left_c, &right_c, &disp_c, state); -} - - -StereoSGBM::StereoSGBM() -{ - minDisparity = numberOfDisparities = 0; - SADWindowSize = 0; - P1 = P2 = 0; - disp12MaxDiff = 0; - preFilterCap = 0; - uniquenessRatio = 0; - speckleWindowSize = 0; - speckleRange = 0; - fullDP = false; - - sm = createStereoSGBM(0, 0, 0); -} - -StereoSGBM::StereoSGBM( int _minDisparity, int _numDisparities, int _SADWindowSize, - int _P1, int _P2, int _disp12MaxDiff, int _preFilterCap, - int _uniquenessRatio, int _speckleWindowSize, int _speckleRange, - bool _fullDP ) -{ - minDisparity = _minDisparity; - numberOfDisparities = _numDisparities; - SADWindowSize = _SADWindowSize; - P1 = _P1; - P2 = _P2; - disp12MaxDiff = _disp12MaxDiff; - preFilterCap = _preFilterCap; - uniquenessRatio = _uniquenessRatio; - speckleWindowSize = _speckleWindowSize; - speckleRange = _speckleRange; - fullDP = _fullDP; - - sm = createStereoSGBM(0, 0, 0); -} - -StereoSGBM::~StereoSGBM() -{ -} - -void StereoSGBM::operator ()( InputArray _left, InputArray _right, - OutputArray _disp ) -{ - sm->set("minDisparity", minDisparity); - sm->set("numDisparities", numberOfDisparities); - sm->set("SADWindowSize", SADWindowSize); - sm->set("P1", P1); - sm->set("P2", P2); - sm->set("disp12MaxDiff", disp12MaxDiff); - sm->set("preFilterCap", preFilterCap); - sm->set("uniquenessRatio", uniquenessRatio); - sm->set("speckleWindowSize", speckleWindowSize); - sm->set("speckleRange", speckleRange); - sm->set("fullDP", fullDP); - - sm->compute(_left, _right, _disp); -} - -} - - - diff --git a/modules/calib3d/src/stereobm.cpp b/modules/calib3d/src/stereobm.cpp index 158881bd94..a005c66d24 100644 --- a/modules/calib3d/src/stereobm.cpp +++ b/modules/calib3d/src/stereobm.cpp @@ -56,7 +56,7 @@ struct StereoBMParams { StereoBMParams(int _numDisparities=64, int _SADWindowSize=21) { - preFilterType = STEREO_PREFILTER_XSOBEL; + preFilterType = StereoBM::PREFILTER_XSOBEL; preFilterSize = 9; preFilterCap = 31; SADWindowSize = _SADWindowSize; @@ -676,7 +676,7 @@ struct PrefilterInvoker : public ParallelLoopBody { for( int i = range.start; i < range.end; i++ ) { - if( state->preFilterType == STEREO_PREFILTER_NORMALIZED_RESPONSE ) + if( state->preFilterType == StereoBM::PREFILTER_NORMALIZED_RESPONSE ) prefilterNorm( *imgs0[i], *imgs[i], state->preFilterSize, state->preFilterCap, buf[i] ); else prefilterXSobel( *imgs0[i], *imgs[i], state->preFilterCap ); @@ -771,8 +771,7 @@ protected: Rect validDisparityRect; }; - -class StereoBMImpl : public StereoMatcher +class StereoBMImpl : public StereoBM { public: StereoBMImpl() @@ -802,8 +801,8 @@ public: disparr.create(left0.size(), dtype); Mat disp0 = disparr.getMat(); - if( params.preFilterType != STEREO_PREFILTER_NORMALIZED_RESPONSE && - params.preFilterType != STEREO_PREFILTER_XSOBEL ) + if( params.preFilterType != PREFILTER_NORMALIZED_RESPONSE && + params.preFilterType != PREFILTER_XSOBEL ) CV_Error( CV_StsOutOfRange, "preFilterType must be = CV_STEREO_BM_NORMALIZED_RESPONSE" ); if( params.preFilterSize < 5 || params.preFilterSize > 255 || params.preFilterSize % 2 == 0 ) @@ -901,33 +900,95 @@ public: disp.convertTo(disp0, disp0.type(), 1./(1 << DISPARITY_SHIFT), 0); } - AlgorithmInfo* info() const; + AlgorithmInfo* info() const { return 0; } + + int getMinDisparity() const { return params.minDisparity; } + void setMinDisparity(int minDisparity) { params.minDisparity = minDisparity; } + + int getNumDisparities() const { return params.numDisparities; } + void setNumDisparities(int numDisparities) { params.numDisparities = numDisparities; } + + int getBlockSize() const { return params.SADWindowSize; } + void setBlockSize(int blockSize) { params.SADWindowSize = blockSize; } + + int getSpeckleWindowSize() const { return params.speckleWindowSize; } + void setSpeckleWindowSize(int speckleWindowSize) { params.speckleWindowSize = speckleWindowSize; } + + int getSpeckleRange() const { return params.speckleRange; } + void setSpeckleRange(int speckleRange) { params.speckleRange = speckleRange; } + + int getDisp12MaxDiff() const { return params.disp12MaxDiff; } + void setDisp12MaxDiff(int disp12MaxDiff) { params.disp12MaxDiff = disp12MaxDiff; } + + int getPreFilterType() const { return params.preFilterType; } + void setPreFilterType(int preFilterType) { params.preFilterType = preFilterType; } + + int getPreFilterSize() const { return params.preFilterSize; } + void setPreFilterSize(int preFilterSize) { params.preFilterSize = preFilterSize; } + + int getPreFilterCap() const { return params.preFilterCap; } + void setPreFilterCap(int preFilterCap) { params.preFilterCap = preFilterCap; } + + int getTextureThreshold() const { return params.textureThreshold; } + void setTextureThreshold(int textureThreshold) { params.textureThreshold = textureThreshold; } + + int getUniquenessRatio() const { return params.uniquenessRatio; } + void setUniquenessRatio(int uniquenessRatio) { params.uniquenessRatio = uniquenessRatio; } + + int getSmallerBlockSize() const { return 0; } + void setSmallerBlockSize(int) {} + + Rect getROI1() const { return params.roi1; } + void setROI1(Rect roi1) { params.roi1 = roi1; } + + Rect getROI2() const { return params.roi2; } + void setROI2(Rect roi2) { params.roi2 = roi2; } + + void write(FileStorage& fs) const + { + fs << "name" << name_ + << "minDisparity" << params.minDisparity + << "numDisparities" << params.numDisparities + << "blockSize" << params.SADWindowSize + << "speckleWindowSize" << params.speckleWindowSize + << "speckleRange" << params.speckleRange + << "disp12MaxDiff" << params.disp12MaxDiff + << "preFilterType" << params.preFilterType + << "preFilterSize" << params.preFilterSize + << "preFilterCap" << params.preFilterCap + << "textureThreshold" << params.textureThreshold + << "uniquenessRatio" << params.uniquenessRatio; + } + + void read(const FileNode& fn) + { + CV_Assert( (std::string)fn["name"] == std::string(name_) ); + params.minDisparity = (int)fn["minDisparity"]; + params.numDisparities = (int)fn["numDisparities"]; + params.SADWindowSize = (int)fn["blockSize"]; + params.speckleWindowSize = (int)fn["speckleWindowSize"]; + params.speckleRange = (int)fn["speckleRange"]; + params.disp12MaxDiff = (int)fn["disp12MaxDiff"]; + params.preFilterType = (int)fn["preFilterType"]; + params.preFilterSize = (int)fn["preFilterSize"]; + params.preFilterCap = (int)fn["preFilterCap"]; + params.textureThreshold = (int)fn["textureThreshold"]; + params.uniquenessRatio = (int)fn["uniquenessRatio"]; + params.roi1 = params.roi2 = Rect(); + } StereoBMParams params; Mat preFilteredImg0, preFilteredImg1, cost, dispbuf; Mat slidingSumBuf; + + static const char* name_; }; -#define add_param(n) \ - obj.info()->addParam(obj, #n, obj.params.n) - -CV_INIT_ALGORITHM(StereoBMImpl, "StereoMatcher.BM", - add_param(preFilterType); - add_param(preFilterSize); - add_param(preFilterCap); - add_param(SADWindowSize); - add_param(minDisparity); - add_param(numDisparities); - add_param(textureThreshold); - add_param(uniquenessRatio); - add_param(speckleRange); - add_param(speckleWindowSize); - add_param(disp12MaxDiff); - add_param(dispType)); +const char* StereoBMImpl::name_ = "StereoMatcher.BM"; } -cv::Ptr cv::createStereoBM(int _numDisparities, int _SADWindowSize) +cv::Ptr cv::createStereoBM(int _numDisparities, int _SADWindowSize) { return new StereoBMImpl(_numDisparities, _SADWindowSize); } diff --git a/modules/calib3d/src/stereosgbm.cpp b/modules/calib3d/src/stereosgbm.cpp index 026201fc03..d46c4110c6 100644 --- a/modules/calib3d/src/stereosgbm.cpp +++ b/modules/calib3d/src/stereosgbm.cpp @@ -75,13 +75,13 @@ struct StereoSGBMParams uniquenessRatio = 0; speckleWindowSize = 0; speckleRange = 0; - fullDP = false; + mode = StereoSGBM::MODE_SGBM; } StereoSGBMParams( int _minDisparity, int _numDisparities, int _SADWindowSize, int _P1, int _P2, int _disp12MaxDiff, int _preFilterCap, int _uniquenessRatio, int _speckleWindowSize, int _speckleRange, - bool _fullDP ) + int _mode ) { minDisparity = _minDisparity; numDisparities = _numDisparities; @@ -93,7 +93,7 @@ struct StereoSGBMParams uniquenessRatio = _uniquenessRatio; speckleWindowSize = _speckleWindowSize; speckleRange = _speckleRange; - fullDP = _fullDP; + mode = _mode; } int minDisparity; @@ -106,7 +106,7 @@ struct StereoSGBMParams int speckleWindowSize; int speckleRange; int disp12MaxDiff; - bool fullDP; + int mode; }; /* @@ -328,8 +328,8 @@ static void computeDisparitySGBM( const Mat& img1, const Mat& img2, #endif const int ALIGN = 16; - const int DISP_SHIFT = StereoSGBM::DISP_SHIFT; - const int DISP_SCALE = StereoSGBM::DISP_SCALE; + const int DISP_SHIFT = StereoMatcher::DISP_SHIFT; + const int DISP_SCALE = (1 << DISP_SHIFT); const CostType MAX_COST = SHRT_MAX; int minD = params.minDisparity, maxD = minD + params.numDisparities; @@ -344,7 +344,8 @@ static void computeDisparitySGBM( const Mat& img1, const Mat& img2, int D = maxD - minD, width1 = maxX1 - minX1; int INVALID_DISP = minD - 1, INVALID_DISP_SCALED = INVALID_DISP*DISP_SCALE; int SW2 = SADWindowSize.width/2, SH2 = SADWindowSize.height/2; - int npasses = params.fullDP ? 2 : 1; + bool fullDP = params.mode == StereoSGBM::MODE_HH; + int npasses = fullDP ? 2 : 1; const int TAB_OFS = 256*4, TAB_SIZE = 256 + TAB_OFS*2; PixType clipTab[TAB_SIZE]; @@ -373,7 +374,7 @@ static void computeDisparitySGBM( const Mat& img1, const Mat& img2, // we keep pixel difference cost (C) and the summary cost over NR directions (S). // we also keep all the partial costs for the previous line L_r(x,d) and also min_k L_r(x, k) size_t costBufSize = width1*D; - size_t CSBufSize = costBufSize*(params.fullDP ? height : 1); + size_t CSBufSize = costBufSize*(fullDP ? height : 1); size_t minLrSize = (width1 + LrBorder*2)*NR2, LrSize = minLrSize*D2; int hsumBufNRows = SH2*2 + 2; size_t totalBufSize = (LrSize + minLrSize)*NLR*sizeof(CostType) + // minLr[] and Lr[] @@ -434,8 +435,8 @@ static void computeDisparitySGBM( const Mat& img1, const Mat& img2, { int x, d; DispType* disp1ptr = disp1.ptr(y); - CostType* C = Cbuf + (!params.fullDP ? 0 : y*costBufSize); - CostType* S = Sbuf + (!params.fullDP ? 0 : y*costBufSize); + CostType* C = Cbuf + (!fullDP ? 0 : y*costBufSize); + CostType* S = Sbuf + (!fullDP ? 0 : y*costBufSize); if( pass == 1 ) // compute C on the first pass, and reuse it on the second pass, if any. { @@ -460,7 +461,7 @@ static void computeDisparitySGBM( const Mat& img1, const Mat& img2, if( y > 0 ) { const CostType* hsumSub = hsumBuf + (std::max(y - SH2 - 1, 0) % hsumBufNRows)*costBufSize; - const CostType* Cprev = !params.fullDP || y == 0 ? C : C - costBufSize; + const CostType* Cprev = !fullDP || y == 0 ? C : C - costBufSize; for( x = D; x < width1*D; x += D ) { @@ -828,8 +829,7 @@ static void computeDisparitySGBM( const Mat& img1, const Mat& img2, } } - -class StereoSGBMImpl : public StereoMatcher +class StereoSGBMImpl : public StereoSGBM { public: StereoSGBMImpl() @@ -840,12 +840,12 @@ public: StereoSGBMImpl( int _minDisparity, int _numDisparities, int _SADWindowSize, int _P1, int _P2, int _disp12MaxDiff, int _preFilterCap, int _uniquenessRatio, int _speckleWindowSize, int _speckleRange, - bool _fullDP ) + int _mode ) { params = StereoSGBMParams( _minDisparity, _numDisparities, _SADWindowSize, _P1, _P2, _disp12MaxDiff, _preFilterCap, _uniquenessRatio, _speckleWindowSize, _speckleRange, - _fullDP ); + _mode ); } void compute( InputArray leftarr, InputArray rightarr, OutputArray disparr ) @@ -861,47 +861,98 @@ public: medianBlur(disp, disp, 3); if( params.speckleWindowSize > 0 ) - filterSpeckles(disp, (params.minDisparity - 1)*STEREO_DISP_SCALE, params.speckleWindowSize, - STEREO_DISP_SCALE*params.speckleRange, buffer); + filterSpeckles(disp, (params.minDisparity - 1)*StereoMatcher::DISP_SCALE, params.speckleWindowSize, + StereoMatcher::DISP_SCALE*params.speckleRange, buffer); } - AlgorithmInfo* info() const; + AlgorithmInfo* info() const { return 0; } + + int getMinDisparity() const { return params.minDisparity; } + void setMinDisparity(int minDisparity) { params.minDisparity = minDisparity; } + + int getNumDisparities() const { return params.numDisparities; } + void setNumDisparities(int numDisparities) { params.numDisparities = numDisparities; } + + int getBlockSize() const { return params.SADWindowSize; } + void setBlockSize(int blockSize) { params.SADWindowSize = blockSize; } + + int getSpeckleWindowSize() const { return params.speckleWindowSize; } + void setSpeckleWindowSize(int speckleWindowSize) { params.speckleWindowSize = speckleWindowSize; } + + int getSpeckleRange() const { return params.speckleRange; } + void setSpeckleRange(int speckleRange) { params.speckleRange = speckleRange; } + + int getDisp12MaxDiff() const { return params.disp12MaxDiff; } + void setDisp12MaxDiff(int disp12MaxDiff) { params.disp12MaxDiff = disp12MaxDiff; } + + int getPreFilterCap() const { return params.preFilterCap; } + void setPreFilterCap(int preFilterCap) { params.preFilterCap = preFilterCap; } + + int getUniquenessRatio() const { return params.uniquenessRatio; } + void setUniquenessRatio(int uniquenessRatio) { params.uniquenessRatio = uniquenessRatio; } + + int getP1() const { return params.P1; } + void setP1(int P1) { params.P1 = P1; } + + int getP2() const { return params.P2; } + void setP2(int P2) { params.P2 = P2; } + + int getMode() const { return params.mode; } + void setMode(int mode) { params.mode = mode; } + + void write(FileStorage& fs) const + { + fs << "name" << name_ + << "minDisparity" << params.minDisparity + << "numDisparities" << params.numDisparities + << "blockSize" << params.SADWindowSize + << "speckleWindowSize" << params.speckleWindowSize + << "speckleRange" << params.speckleRange + << "disp12MaxDiff" << params.disp12MaxDiff + << "preFilterCap" << params.preFilterCap + << "uniquenessRatio" << params.uniquenessRatio + << "P1" << params.P1 + << "P2" << params.P2 + << "mode" << params.mode; + } + + void read(const FileNode& fn) + { + CV_Assert( (std::string)fn["name"] == std::string(name_) ); + params.minDisparity = (int)fn["minDisparity"]; + params.numDisparities = (int)fn["numDisparities"]; + params.SADWindowSize = (int)fn["blockSize"]; + params.speckleWindowSize = (int)fn["speckleWindowSize"]; + params.speckleRange = (int)fn["speckleRange"]; + params.disp12MaxDiff = (int)fn["disp12MaxDiff"]; + params.preFilterCap = (int)fn["preFilterCap"]; + params.uniquenessRatio = (int)fn["uniquenessRatio"]; + params.P1 = (int)fn["P1"]; + params.P2 = (int)fn["P2"]; + params.mode = (int)fn["mode"]; + } StereoSGBMParams params; Mat buffer; + static const char* name_; }; +const char* StereoSGBMImpl::name_ = "StereoMatcher.SGBM"; + -Ptr createStereoSGBM(int minDisparity, int numDisparities, int SADWindowSize, - int P1, int P2, int disp12MaxDiff, - int preFilterCap, int uniquenessRatio, - int speckleWindowSize, int speckleRange, - bool fullDP) +Ptr createStereoSGBM(int minDisparity, int numDisparities, int SADWindowSize, + int P1, int P2, int disp12MaxDiff, + int preFilterCap, int uniquenessRatio, + int speckleWindowSize, int speckleRange, + int mode) { return new StereoSGBMImpl(minDisparity, numDisparities, SADWindowSize, P1, P2, disp12MaxDiff, preFilterCap, uniquenessRatio, speckleWindowSize, speckleRange, - fullDP); + mode); } - -#define add_param(n) \ - obj.info()->addParam(obj, #n, obj.params.n) - -CV_INIT_ALGORITHM(StereoSGBMImpl, "StereoMatcher.SGBM", - add_param(minDisparity); - add_param(numDisparities); - add_param(SADWindowSize); - add_param(preFilterCap); - add_param(uniquenessRatio); - add_param(P1); - add_param(P2); - add_param(speckleWindowSize); - add_param(speckleRange); - add_param(disp12MaxDiff); - add_param(fullDP)); - Rect getValidDisparityROI( Rect roi1, Rect roi2, int minDisparity, int numberOfDisparities, diff --git a/modules/calib3d/test/test_stereomatching.cpp b/modules/calib3d/test/test_stereomatching.cpp index 4b35dad990..372e9f5436 100644 --- a/modules/calib3d/test/test_stereomatching.cpp +++ b/modules/calib3d/test/test_stereomatching.cpp @@ -700,8 +700,10 @@ protected: Mat leftImg; cvtColor( _leftImg, leftImg, CV_BGR2GRAY ); Mat rightImg; cvtColor( _rightImg, rightImg, CV_BGR2GRAY ); - StereoBM bm( StereoBM::BASIC_PRESET, params.ndisp, params.winSize ); - bm( leftImg, rightImg, leftDisp, CV_32F ); + Ptr bm = createStereoBM( params.ndisp, params.winSize ); + Mat tempDisp; + bm->compute( leftImg, rightImg, tempDisp ); + tempDisp.convertTo(leftDisp, CV_32F, 1./StereoMatcher::DISP_SCALE); return params.winSize/2; } }; @@ -751,10 +753,13 @@ protected: { RunParams params = caseRunParams[caseIdx]; assert( params.ndisp%16 == 0 ); - StereoSGBM sgbm( 0, params.ndisp, params.winSize, 10*params.winSize*params.winSize, 40*params.winSize*params.winSize, - 1, 63, 10, 100, 32, params.fullDP ); - sgbm( leftImg, rightImg, leftDisp ); - assert( leftDisp.type() == CV_16SC1 ); + Ptr sgbm = createStereoSGBM( 0, params.ndisp, params.winSize, + 10*params.winSize*params.winSize, + 40*params.winSize*params.winSize, + 1, 63, 10, 100, 32, params.fullDP ? + StereoSGBM::MODE_HH : StereoSGBM::MODE_SGBM ); + sgbm->compute( leftImg, rightImg, leftDisp ); + CV_Assert( leftDisp.type() == CV_16SC1 ); leftDisp/=16; return 0; } diff --git a/modules/gpu/perf/perf_calib3d.cpp b/modules/gpu/perf/perf_calib3d.cpp index b174d9a12e..1387e04c68 100644 --- a/modules/gpu/perf/perf_calib3d.cpp +++ b/modules/gpu/perf/perf_calib3d.cpp @@ -37,11 +37,11 @@ PERF_TEST_P(ImagePair, Calib3D_StereoBM, } else { - cv::StereoBM bm(preset, ndisp); + cv::Ptr bm = cv::createStereoBM(ndisp); cv::Mat dst; - TEST_CYCLE() bm(imgLeft, imgRight, dst); + TEST_CYCLE() bm->compute(imgLeft, imgRight, dst); CPU_SANITY_CHECK(dst); } diff --git a/samples/cpp/stereo_match.cpp b/samples/cpp/stereo_match.cpp index 743185e451..2d4bb5fec6 100644 --- a/samples/cpp/stereo_match.cpp +++ b/samples/cpp/stereo_match.cpp @@ -67,8 +67,8 @@ int main(int argc, char** argv) bool no_display = false; float scale = 1.f; - Ptr bm = createStereoBM(16,9); - Ptr sgbm = createStereoSGBM(0,16,3); + Ptr bm = createStereoBM(16,9); + Ptr sgbm = createStereoSGBM(0,16,3); StereoVar var; for( int i = 1; i < argc; i++ ) @@ -221,33 +221,33 @@ int main(int argc, char** argv) numberOfDisparities = numberOfDisparities > 0 ? numberOfDisparities : ((img_size.width/8) + 15) & -16; - //bm->set("roi1", roi1); - //bm->set("roi2", roi2); - bm->set("preFilterCap", 31); - bm->set("SADWindowSize", SADWindowSize > 0 ? SADWindowSize : 9); - bm->set("minDisparity", 0); - bm->set("numDisparities", numberOfDisparities); - bm->set("textureThreshold", 10); - bm->set("uniquenessRatio", 15); - bm->set("speckleWindowSize", 100); - bm->set("speckleRange", 32); - bm->set("disp12MaxDiff", 1); - - sgbm->set("preFilterCap", 63); + bm->setROI1(roi1); + bm->setROI2(roi2); + bm->setPreFilterCap(31); + bm->setBlockSize(SADWindowSize > 0 ? SADWindowSize : 9); + bm->setMinDisparity(0); + bm->setNumDisparities(numberOfDisparities); + bm->setTextureThreshold(10); + bm->setUniquenessRatio(15); + bm->setSpeckleWindowSize(100); + bm->setSpeckleRange(32); + bm->setDisp12MaxDiff(1); + + sgbm->setPreFilterCap(63); int sgbmWinSize = SADWindowSize > 0 ? SADWindowSize : 3; - sgbm->set("SADWindowSize", sgbmWinSize); + sgbm->setBlockSize(sgbmWinSize); int cn = img1.channels(); - sgbm->set("P1", 8*cn*sgbmWinSize*sgbmWinSize); - sgbm->set("P2", 32*cn*sgbmWinSize*sgbmWinSize); - sgbm->set("minDisparity", 0); - sgbm->set("numDisparities", numberOfDisparities); - sgbm->set("uniquenessRatio", 10); - sgbm->set("speckleWindowSize", 100); - sgbm->set("speckleRange", 32); - sgbm->set("disp12MaxDiff", 1); - sgbm->set("fullDP", alg == STEREO_HH); + 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->setMode(alg == STEREO_HH ? StereoSGBM::MODE_HH : StereoSGBM::MODE_SGBM); var.levels = 3; // ignored with USE_AUTO_PARAMS var.pyrScale = 0.5; // ignored with USE_AUTO_PARAMS diff --git a/samples/cpp/tutorial_code/calib3d/stereoBM/SBM_Sample.cpp b/samples/cpp/tutorial_code/calib3d/stereoBM/SBM_Sample.cpp index 13d5aa8708..18244c59fb 100644 --- a/samples/cpp/tutorial_code/calib3d/stereoBM/SBM_Sample.cpp +++ b/samples/cpp/tutorial_code/calib3d/stereoBM/SBM_Sample.cpp @@ -39,12 +39,10 @@ int main( int argc, char** argv ) int ndisparities = 16*5; /**< Range of disparity */ int SADWindowSize = 21; /**< Size of the block window. Must be odd */ - StereoBM sbm( StereoBM::BASIC_PRESET, - ndisparities, - SADWindowSize ); + Ptr sbm = createStereoBM( ndisparities, SADWindowSize ); //-- 3. Calculate the disparity image - sbm( imgLeft, imgRight, imgDisparity16S, CV_16S ); + sbm->compute( imgLeft, imgRight, imgDisparity16S ); //-- Check its extreme values double minVal; double maxVal; From 7b5923e98b90a8cabaa16b27e36ce0db25d72159 Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Sun, 24 Mar 2013 23:09:17 +0400 Subject: [PATCH 2/5] fixed docs and compile error on Linux --- ...mera_calibration_and_3d_reconstruction.rst | 178 +++++------------- modules/calib3d/include/opencv2/calib3d.hpp | 6 +- 2 files changed, 51 insertions(+), 133 deletions(-) diff --git a/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst b/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst index 199e9b5eb1..c09c5ace0b 100644 --- a/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst +++ b/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst @@ -81,7 +81,7 @@ is extended as: :math:`s_1`, :math:`s_2`, :math:`s_3`, and -:math:`s_4`, are the thin prism distortion coefficients. +:math:`s_4`, are the thin prism distortion coefficients. Higher-order coefficients are not considered in OpenCV. In the functions below the coefficients are passed or returned as .. math:: @@ -156,9 +156,9 @@ Finds the camera intrinsic and extrinsic parameters from several views of a cali * **CV_CALIB_FIX_K1,...,CV_CALIB_FIX_K6** The corresponding radial distortion coefficient is not changed during the optimization. If ``CV_CALIB_USE_INTRINSIC_GUESS`` is set, the coefficient from the supplied ``distCoeffs`` matrix is used. Otherwise, it is set to 0. * **CV_CALIB_RATIONAL_MODEL** Coefficients k4, k5, and k6 are enabled. To provide the backward compatibility, this extra flag should be explicitly specified to make the calibration function use the rational model and return 8 coefficients. If the flag is not set, the function computes and returns only 5 distortion coefficients. - + * **CALIB_THIN_PRISM_MODEL** Coefficients s1, s2, s3 and s4 are enabled. To provide the backward compatibility, this extra flag should be explicitly specified to make the calibration function use the thin prism model and return 12 coefficients. If the flag is not set, the function computes and returns only 5 distortion coefficients. - + * **CALIB_FIX_S1_S2_S3_S4** The thin prism distortion coefficients are not changed during the optimization. If ``CV_CALIB_USE_INTRINSIC_GUESS`` is set, the coefficient from the supplied ``distCoeffs`` matrix is used. Otherwise, it is set to 0. @@ -1166,155 +1166,93 @@ used in the global 3D geometry optimization procedures like :ocv:func:`solvePnP` . +StereoMatcher +------------- +.. ocv:class:: StereoMatcher : public Algorithm -StereoBM --------- -.. ocv:class:: StereoBM - -Class for computing stereo correspondence using the block matching algorithm. :: +The base class for stereo correspondence algorithms. :: - // Block matching stereo correspondence algorithm class StereoBM - { - enum { NORMALIZED_RESPONSE = CV_STEREO_BM_NORMALIZED_RESPONSE, - BASIC_PRESET=CV_STEREO_BM_BASIC, - FISH_EYE_PRESET=CV_STEREO_BM_FISH_EYE, - NARROW_PRESET=CV_STEREO_BM_NARROW }; - - StereoBM(); - // the preset is one of ..._PRESET above. - // ndisparities is the size of disparity range, - // in which the optimal disparity at each pixel is searched for. - // SADWindowSize is the size of averaging window used to match pixel blocks - // (larger values mean better robustness to noise, but yield blurry disparity maps) - StereoBM(int preset, int ndisparities=0, int SADWindowSize=21); - // separate initialization function - void init(int preset, int ndisparities=0, int SADWindowSize=21); - // computes the disparity for the two rectified 8-bit single-channel images. - // the disparity will be 16-bit signed (fixed-point) or 32-bit floating-point image of the same size as left. - void operator()( InputArray left, InputArray right, OutputArray disparity, int disptype=CV_16S ); - - Ptr state; - }; - -The class is a C++ wrapper for the associated functions. In particular, :ocv:funcx:`StereoBM::operator()` is the wrapper for -:ocv:cfunc:`cvFindStereoCorrespondenceBM`. - - -StereoBM::StereoBM ------------------- -The constructors. - -.. ocv:function:: StereoBM::StereoBM() -.. ocv:function:: StereoBM::StereoBM(int preset, int ndisparities=0, int SADWindowSize=21) +StereoMatcher::compute +----------------------- +Computes disparity map for the specified stereo pair -.. ocv:pyfunction:: cv2.StereoBM([preset[, ndisparities[, SADWindowSize]]]) -> +.. ocv:function:: void StereoMatcher::compute( InputArray left, InputArray right, OutputArray disparity ) -.. ocv:cfunction:: CvStereoBMState* cvCreateStereoBMState( int preset=CV_STEREO_BM_BASIC, int numberOfDisparities=0 ) +.. ocv:pyfunction:: cv2.StereoBM.compute(left, right[, disparity[, disptype]]) -> disparity -.. ocv:pyoldfunction:: cv.CreateStereoBMState(preset=CV_STEREO_BM_BASIC, numberOfDisparities=0)-> CvStereoBMState + :param left: Left 8-bit single-channel image. - :param preset: specifies the whole set of algorithm parameters, one of: + :param right: Right image of the same size and the same type as the left one. - * BASIC_PRESET - parameters suitable for general cameras - * FISH_EYE_PRESET - parameters suitable for wide-angle cameras - * NARROW_PRESET - parameters suitable for narrow-angle cameras + :param disparity: Output disparity map. It has the same size as the input images. Some algorithms, like StereoBM or StereoSGBM compute 16-bit fixed-point disparity map (where each disparity value has 4 fractional bits), whereas other algorithms output 32-bit floating-point disparity map. - After constructing the class, you can override any parameters set by the preset. - :param ndisparities: the disparity search range. For each pixel algorithm will find the best disparity from 0 (default minimum disparity) to ``ndisparities``. The search range can then be shifted by changing the minimum disparity. +StereoBM +-------- +.. ocv:class:: StereoBM : public StereoMatcher - :param SADWindowSize: the linear size of the blocks compared by the algorithm. The size should be odd (as the block is centered at the current pixel). Larger block size implies smoother, though less accurate disparity map. Smaller block size gives more detailed disparity map, but there is higher chance for algorithm to find a wrong correspondence. +Class for computing stereo correspondence using the block matching algorithm, introduced and contributed to OpenCV by K. Konolige. -The constructors initialize ``StereoBM`` state. You can then call ``StereoBM::operator()`` to compute disparity for a specific stereo pair. -.. note:: In the C API you need to deallocate ``CvStereoBM`` state when it is not needed anymore using ``cvReleaseStereoBMState(&stereobm)``. +createStereoBM +------------------ +Creates StereoBM object -StereoBM::operator() ------------------------ -Computes disparity using the BM algorithm for a rectified stereo pair. +.. ocv:function:: Ptr createStereoBM(int numDisparities=0, int blockSize=21) -.. ocv:function:: void StereoBM::operator()( InputArray left, InputArray right, OutputArray disparity, int disptype=CV_16S ) +.. ocv:pyfunction:: cv2.createStereoBM([numDisparities[, blockSize]]) -> -.. ocv:pyfunction:: cv2.StereoBM.compute(left, right[, disparity[, disptype]]) -> disparity +.. ocv:cfunction:: CvStereoBMState* cvCreateStereoBMState( int preset=CV_STEREO_BM_BASIC, int numDisparities=0 ) -.. ocv:cfunction:: void cvFindStereoCorrespondenceBM( const CvArr* left, const CvArr* right, CvArr* disparity, CvStereoBMState* state ) +.. ocv:pyoldfunction:: cv.CreateStereoBMState(preset=CV_STEREO_BM_BASIC, numDisparities=0)-> CvStereoBMState -.. ocv:pyoldfunction:: cv.FindStereoCorrespondenceBM(left, right, disparity, state)-> None + :param preset: specifies the whole set of algorithm parameters, one of: - :param left: Left 8-bit single-channel image. + * BASIC_PRESET - parameters suitable for general cameras + * FISH_EYE_PRESET - parameters suitable for wide-angle cameras + * NARROW_PRESET - parameters suitable for narrow-angle cameras - :param right: Right image of the same size and the same type as the left one. + After constructing the class, you can override any parameters set by the preset. - :param disparity: Output disparity map. It has the same size as the input images. When ``disptype==CV_16S``, the map is a 16-bit signed single-channel image, containing disparity values scaled by 16. To get the true disparity values from such fixed-point representation, you will need to divide each ``disp`` element by 16. If ``disptype==CV_32F``, the disparity map will already contain the real disparity values on output. + :param numDisparities: the disparity search range. For each pixel algorithm will find the best disparity from 0 (default minimum disparity) to ``numDisparities``. The search range can then be shifted by changing the minimum disparity. - :param disptype: Type of the output disparity map, ``CV_16S`` (default) or ``CV_32F``. + :param blockSize: the linear size of the blocks compared by the algorithm. The size should be odd (as the block is centered at the current pixel). Larger block size implies smoother, though less accurate disparity map. Smaller block size gives more detailed disparity map, but there is higher chance for algorithm to find a wrong correspondence. - :param state: The pre-initialized ``CvStereoBMState`` structure in the case of the old API. +The function create ``StereoBM`` object. You can then call ``StereoBM::compute()`` to compute disparity for a specific stereo pair. -The method executes the BM algorithm on a rectified stereo pair. See the ``stereo_match.cpp`` OpenCV sample on how to prepare images and call the method. Note that the method is not constant, thus you should not use the same ``StereoBM`` instance from within different threads simultaneously. The function is parallelized with the TBB library. +.. note:: In the C API you need to deallocate ``CvStereoBM`` state when it is not needed anymore using ``cvReleaseStereoBMState(&stereobm)``. StereoSGBM ---------- -.. ocv:class:: StereoSGBM - -Class for computing stereo correspondence using the semi-global block matching algorithm. :: - - class StereoSGBM - { - StereoSGBM(); - StereoSGBM(int minDisparity, int numDisparities, int SADWindowSize, - int P1=0, int P2=0, int disp12MaxDiff=0, - int preFilterCap=0, int uniquenessRatio=0, - int speckleWindowSize=0, int speckleRange=0, - bool fullDP=false); - virtual ~StereoSGBM(); - - virtual void operator()(InputArray left, InputArray right, OutputArray disp); - - int minDisparity; - int numberOfDisparities; - int SADWindowSize; - int preFilterCap; - int uniquenessRatio; - int P1, P2; - int speckleWindowSize; - int speckleRange; - int disp12MaxDiff; - bool fullDP; - - ... - }; +.. ocv:class:: StereoSGBM : public StereoMatcher The class implements the modified H. Hirschmuller algorithm [HH08]_ that differs from the original one as follows: - * By default, the algorithm is single-pass, which means that you consider only 5 directions instead of 8. Set ``fullDP=true`` to run the full variant of the algorithm but beware that it may consume a lot of memory. + * By default, the algorithm is single-pass, which means that you consider only 5 directions instead of 8. Set ``mode=StereoSGBM::MODE_HH`` in ``createStereoSGBM`` to run the full variant of the algorithm but beware that it may consume a lot of memory. - * The algorithm matches blocks, not individual pixels. Though, setting ``SADWindowSize=1`` reduces the blocks to single pixels. + * The algorithm matches blocks, not individual pixels. Though, setting ``blockSize=1`` reduces the blocks to single pixels. * Mutual information cost function is not implemented. Instead, a simpler Birchfield-Tomasi sub-pixel metric from [BT98]_ is used. Though, the color images are supported as well. - * Some pre- and post- processing steps from K. Konolige algorithm :ocv:funcx:`StereoBM::operator()` are included, for example: pre-filtering (``CV_STEREO_BM_XSOBEL`` type) and post-filtering (uniqueness check, quadratic interpolation and speckle filtering). - + * Some pre- and post- processing steps from K. Konolige algorithm ``StereoBM`` are included, for example: pre-filtering (``StereoBM::PREFILTER_XSOBEL`` type) and post-filtering (uniqueness check, quadratic interpolation and speckle filtering). -StereoSGBM::StereoSGBM +createStereoSGBM -------------------------- -.. ocv:function:: StereoSGBM::StereoSGBM() +Creates StereoSGBM object -.. ocv:function:: StereoSGBM::StereoSGBM( int minDisparity, int numDisparities, int SADWindowSize, int P1=0, int P2=0, int disp12MaxDiff=0, int preFilterCap=0, int uniquenessRatio=0, int speckleWindowSize=0, int speckleRange=0, bool fullDP=false) +.. ocv:function:: Ptr createStereoSGBM( int minDisparity, int numDisparities, int blockSize, int P1=0, int P2=0, int disp12MaxDiff=0, int preFilterCap=0, int uniquenessRatio=0, int speckleWindowSize=0, int speckleRange=0, int mode=StereoSGBM::MODE_SGBM) -.. ocv:pyfunction:: cv2.StereoSGBM([minDisparity, numDisparities, SADWindowSize[, P1[, P2[, disp12MaxDiff[, preFilterCap[, uniquenessRatio[, speckleWindowSize[, speckleRange[, fullDP]]]]]]]]]) -> - - Initializes ``StereoSGBM`` and sets parameters to custom values.?? +.. ocv:pyfunction:: cv2.StereoSGBM([minDisparity, numDisparities, blockSize[, P1[, P2[, disp12MaxDiff[, preFilterCap[, uniquenessRatio[, speckleWindowSize[, speckleRange[, mode]]]]]]]]]) -> :param minDisparity: Minimum possible disparity value. Normally, it is zero but sometimes rectification algorithms can shift images, so this parameter needs to be adjusted accordingly. :param numDisparities: Maximum disparity minus minimum disparity. The value is always greater than zero. In the current implementation, this parameter must be divisible by 16. - :param SADWindowSize: Matched block size. It must be an odd number ``>=1`` . Normally, it should be somewhere in the ``3..11`` range. + :param blockSize: Matched block size. It must be an odd number ``>=1`` . Normally, it should be somewhere in the ``3..11`` range. :param P1: The first parameter controlling the disparity smoothness. See below. @@ -1330,31 +1268,11 @@ StereoSGBM::StereoSGBM :param speckleRange: Maximum disparity variation within each connected component. If you do speckle filtering, set the parameter to a positive value, it will be implicitly multiplied by 16. Normally, 1 or 2 is good enough. - :param fullDP: Set it to ``true`` to run the full-scale two-pass dynamic programming algorithm. It will consume O(W*H*numDisparities) bytes, which is large for 640x480 stereo and huge for HD-size pictures. By default, it is set to ``false`` . - -The first constructor initializes ``StereoSGBM`` with all the default parameters. So, you only have to set ``StereoSGBM::numberOfDisparities`` at minimum. The second constructor enables you to set each parameter to a custom value. + :param mode: Set it to ``StereoSGBM::MODE_HH`` to run the full-scale two-pass dynamic programming algorithm. It will consume O(W*H*numDisparities) bytes, which is large for 640x480 stereo and huge for HD-size pictures. By default, it is set to ``false`` . +The first constructor initializes ``StereoSGBM`` with all the default parameters. So, you only have to set ``StereoSGBM::numDisparities`` at minimum. The second constructor enables you to set each parameter to a custom value. -StereoSGBM::operator () ------------------------ - -.. ocv:function:: void StereoSGBM::operator()(InputArray left, InputArray right, OutputArray disp) - -.. ocv:pyfunction:: cv2.StereoSGBM.compute(left, right[, disp]) -> disp - - Computes disparity using the SGBM algorithm for a rectified stereo pair. - - :param left: Left 8-bit single-channel or 3-channel image. - - :param right: Right image of the same size and the same type as the left one. - - :param disp: Output disparity map. It is a 16-bit signed single-channel image of the same size as the input image. It contains disparity values scaled by 16. So, to get the floating-point disparity map, you need to divide each ``disp`` element by 16. - -The method executes the SGBM algorithm on a rectified stereo pair. See ``stereo_match.cpp`` OpenCV sample on how to prepare images and call the method. - -.. note:: The method is not constant, so you should not use the same ``StereoSGBM`` instance from different threads simultaneously. - stereoCalibrate ------------------- @@ -1413,9 +1331,9 @@ Calibrates the stereo camera. * **CV_CALIB_FIX_K1,...,CV_CALIB_FIX_K6** Do not change the corresponding radial distortion coefficient during the optimization. If ``CV_CALIB_USE_INTRINSIC_GUESS`` is set, the coefficient from the supplied ``distCoeffs`` matrix is used. Otherwise, it is set to 0. * **CV_CALIB_RATIONAL_MODEL** Enable coefficients k4, k5, and k6. To provide the backward compatibility, this extra flag should be explicitly specified to make the calibration function use the rational model and return 8 coefficients. If the flag is not set, the function computes and returns only 5 distortion coefficients. - + * **CALIB_THIN_PRISM_MODEL** Coefficients s1, s2, s3 and s4 are enabled. To provide the backward compatibility, this extra flag should be explicitly specified to make the calibration function use the thin prism model and return 12 coefficients. If the flag is not set, the function computes and returns only 5 distortion coefficients. - + * **CALIB_FIX_S1_S2_S3_S4** The thin prism distortion coefficients are not changed during the optimization. If ``CV_CALIB_USE_INTRINSIC_GUESS`` is set, the coefficient from the supplied ``distCoeffs`` matrix is used. Otherwise, it is set to 0. The function estimates transformation between two cameras making a stereo pair. If you have a stereo camera where the relative position and orientation of two cameras is fixed, and if you computed poses of an object relative to the first camera and to the second camera, (R1, T1) and (R2, T2), respectively (this can be done with diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d.hpp index de44148d03..45c55a59f6 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d.hpp @@ -373,8 +373,6 @@ CVAPI(void) cvReprojectImageTo3D( const CvArr* disparityImage, #ifdef __cplusplus } -template<> CV_EXPORTS void cv::Ptr::delete_obj(); - ////////////////////////////////////////////////////////////////////////////////////////// class CV_EXPORTS CvLevMarq { @@ -673,6 +671,8 @@ CV_EXPORTS_W void correctMatches( InputArray F, InputArray points1, InputArray p OutputArray newPoints1, OutputArray newPoints2 ); +template<> CV_EXPORTS void Ptr::delete_obj(); + class CV_EXPORTS_W StereoMatcher : public Algorithm { public: @@ -700,7 +700,7 @@ public: CV_WRAP virtual void setDisp12MaxDiff(int disp12MaxDiff) = 0; }; - + class CV_EXPORTS_W StereoBM : public StereoMatcher { public: From 44157c421f0c7a625edf0ff573ace0801746a6bc Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Mon, 25 Mar 2013 00:42:46 +0400 Subject: [PATCH 3/5] fixed python test failures (modified stereo correspondence test to use cv2.* stuff), fixed docs --- ...mera_calibration_and_3d_reconstruction.rst | 4 +- modules/calib3d/include/opencv2/calib3d.hpp | 4 +- modules/python/src2/cv2.cpp | 4 ++ modules/python/test/test.py | 57 ++++++------------- 4 files changed, 24 insertions(+), 45 deletions(-) diff --git a/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst b/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst index c09c5ace0b..3b531c49e6 100644 --- a/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst +++ b/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst @@ -1083,7 +1083,7 @@ Reprojects a disparity image to 3D space. :param Q: :math:`4 \times 4` perspective transformation matrix that can be obtained with :ocv:func:`stereoRectify`. - :param handleMissingValues: Indicates, whether the function should handle missing values (i.e. points where the disparity was not computed). If ``handleMissingValues=true``, then pixels with the minimal disparity that corresponds to the outliers (see :ocv:funcx:`StereoBM::operator()` ) are transformed to 3D points with a very large Z value (currently set to 10000). + :param handleMissingValues: Indicates, whether the function should handle missing values (i.e. points where the disparity was not computed). If ``handleMissingValues=true``, then pixels with the minimal disparity that corresponds to the outliers (see :ocv:funcx:`StereoMatcher::compute` ) are transformed to 3D points with a very large Z value (currently set to 10000). :param ddepth: The optional output array depth. If it is ``-1``, the output image will have ``CV_32F`` depth. ``ddepth`` can also be set to ``CV_16S``, ``CV_32S`` or ``CV_32F``. @@ -1170,7 +1170,7 @@ StereoMatcher ------------- .. ocv:class:: StereoMatcher : public Algorithm -The base class for stereo correspondence algorithms. :: +The base class for stereo correspondence algorithms. StereoMatcher::compute ----------------------- diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d.hpp index 45c55a59f6..79fb8892a9 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d.hpp @@ -731,7 +731,7 @@ public: CV_WRAP virtual void setROI2(Rect roi2) = 0; }; -CV_EXPORTS Ptr createStereoBM(int numDisparities=0, int blockSize=21); +CV_EXPORTS_W Ptr createStereoBM(int numDisparities=0, int blockSize=21); class CV_EXPORTS_W StereoSGBM : public StereoMatcher @@ -756,7 +756,7 @@ public: }; -CV_EXPORTS Ptr createStereoSGBM(int minDisparity, int numDisparities, int blockSize, +CV_EXPORTS_W Ptr createStereoSGBM(int minDisparity, int numDisparities, int blockSize, int P1=0, int P2=0, int disp12MaxDiff=0, int preFilterCap=0, int uniquenessRatio=0, int speckleWindowSize=0, int speckleRange=0, diff --git a/modules/python/src2/cv2.cpp b/modules/python/src2/cv2.cpp index 40538d1c9c..78cd96e4cd 100644 --- a/modules/python/src2/cv2.cpp +++ b/modules/python/src2/cv2.cpp @@ -129,6 +129,10 @@ typedef Ptr Ptr_DescriptorExtractor; typedef Ptr Ptr_Feature2D; typedef Ptr Ptr_DescriptorMatcher; +typedef Ptr Ptr_StereoMatcher; +typedef Ptr Ptr_StereoBM; +typedef Ptr Ptr_StereoSGBM; + typedef Ptr Ptr_ChannelFeatureBuilder; typedef SimpleBlobDetector::Params SimpleBlobDetector_Params; diff --git a/modules/python/test/test.py b/modules/python/test/test.py index 7c511e4ef7..25c4c2c820 100755 --- a/modules/python/test/test.py +++ b/modules/python/test/test.py @@ -14,6 +14,8 @@ import getopt import operator import functools +import numpy as np +import cv2 import cv2.cv as cv from test2 import * @@ -78,6 +80,12 @@ class OpenCVTests(unittest.TestCase): cv.SetData(imagefiledata, filedata, len(filedata)) self.image_cache[filename] = cv.DecodeImageM(imagefiledata, iscolor) return self.image_cache[filename] + + def get_sample2(self, filename, iscolor = cv.CV_LOAD_IMAGE_COLOR): + if not filename in self.image_cache: + filedata = urllib.urlopen("https://raw.github.com/Itseez/opencv/master/" + filename).read() + self.image_cache[filename] = cv2.imdecode(np.fromstring(filedata, dtype=np.uint8), iscolor) + return self.image_cache[filename] def setUp(self): self.image_cache = {} @@ -987,47 +995,14 @@ class AreaTests(OpenCVTests): self.assertRaises(cv.error, lambda: l[tup2]) def test_stereo(self): - bm = cv.CreateStereoBMState() - def illegal_delete(): - bm = cv.CreateStereoBMState() - del bm.preFilterType - def illegal_assign(): - bm = cv.CreateStereoBMState() - bm.preFilterType = "foo" - - self.assertRaises(TypeError, illegal_delete) - self.assertRaises(TypeError, illegal_assign) - - left = self.get_sample("samples/c/lena.jpg", 0) - right = self.get_sample("samples/c/lena.jpg", 0) - disparity = cv.CreateMat(512, 512, cv.CV_16SC1) - cv.FindStereoCorrespondenceBM(left, right, disparity, bm) - - gc = cv.CreateStereoGCState(16, 2) - left_disparity = cv.CreateMat(512, 512, cv.CV_16SC1) - right_disparity = cv.CreateMat(512, 512, cv.CV_16SC1) - - def test_stereo(self): - bm = cv.CreateStereoBMState() - def illegal_delete(): - bm = cv.CreateStereoBMState() - del bm.preFilterType - def illegal_assign(): - bm = cv.CreateStereoBMState() - bm.preFilterType = "foo" - - self.assertRaises(TypeError, illegal_delete) - self.assertRaises(TypeError, illegal_assign) - - left = self.get_sample("samples/c/lena.jpg", 0) - right = self.get_sample("samples/c/lena.jpg", 0) - disparity = cv.CreateMat(512, 512, cv.CV_16SC1) - cv.FindStereoCorrespondenceBM(left, right, disparity, bm) - - gc = cv.CreateStereoGCState(16, 2) - left_disparity = cv.CreateMat(512, 512, cv.CV_16SC1) - right_disparity = cv.CreateMat(512, 512, cv.CV_16SC1) - cv.FindStereoCorrespondenceGC(left, right, left_disparity, right_disparity, gc) + left = self.get_sample2("samples/cpp/tsukuba_l.png", 0) + right = self.get_sample2("samples/cpp/tsukuba_r.png", 0) + bm = cv2.createStereoBM(32, 11) + disparity = bm.compute(left, right) + self.assertEqual(left.shape, disparity.shape) + sgbm = cv2.createStereoSGBM(0, 32, 5) + disparity2 = sgbm.compute(left, right) + self.assertEqual(left.shape, disparity2.shape) def test_kalman(self): k = cv.CreateKalman(2, 1, 0) From f8b61e4ecac367f9cbc77ce0557f65c01c7fdc6c Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Mon, 25 Mar 2013 12:04:11 +0400 Subject: [PATCH 4/5] fixed hopefully last warnings in the doc builder --- .../camera_calibration_and_3d_reconstruction.rst | 15 --------------- modules/python/test/test.py | 2 +- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst b/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst index 3b531c49e6..1c2e537f86 100644 --- a/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst +++ b/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst @@ -1202,27 +1202,12 @@ Creates StereoBM object .. ocv:pyfunction:: cv2.createStereoBM([numDisparities[, blockSize]]) -> -.. ocv:cfunction:: CvStereoBMState* cvCreateStereoBMState( int preset=CV_STEREO_BM_BASIC, int numDisparities=0 ) - -.. ocv:pyoldfunction:: cv.CreateStereoBMState(preset=CV_STEREO_BM_BASIC, numDisparities=0)-> CvStereoBMState - - :param preset: specifies the whole set of algorithm parameters, one of: - - * BASIC_PRESET - parameters suitable for general cameras - * FISH_EYE_PRESET - parameters suitable for wide-angle cameras - * NARROW_PRESET - parameters suitable for narrow-angle cameras - - After constructing the class, you can override any parameters set by the preset. - :param numDisparities: the disparity search range. For each pixel algorithm will find the best disparity from 0 (default minimum disparity) to ``numDisparities``. The search range can then be shifted by changing the minimum disparity. :param blockSize: the linear size of the blocks compared by the algorithm. The size should be odd (as the block is centered at the current pixel). Larger block size implies smoother, though less accurate disparity map. Smaller block size gives more detailed disparity map, but there is higher chance for algorithm to find a wrong correspondence. The function create ``StereoBM`` object. You can then call ``StereoBM::compute()`` to compute disparity for a specific stereo pair. -.. note:: In the C API you need to deallocate ``CvStereoBM`` state when it is not needed anymore using ``cvReleaseStereoBMState(&stereobm)``. - - StereoSGBM ---------- diff --git a/modules/python/test/test.py b/modules/python/test/test.py index 25c4c2c820..33e605ec06 100755 --- a/modules/python/test/test.py +++ b/modules/python/test/test.py @@ -80,7 +80,7 @@ class OpenCVTests(unittest.TestCase): cv.SetData(imagefiledata, filedata, len(filedata)) self.image_cache[filename] = cv.DecodeImageM(imagefiledata, iscolor) return self.image_cache[filename] - + def get_sample2(self, filename, iscolor = cv.CV_LOAD_IMAGE_COLOR): if not filename in self.image_cache: filedata = urllib.urlopen("https://raw.github.com/Itseez/opencv/master/" + filename).read() From 322d781192d68364dbb97b9a4904d1a40a50efe7 Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Tue, 26 Mar 2013 12:55:21 +0400 Subject: [PATCH 5/5] avoid explicit std::string use --- modules/calib3d/src/stereobm.cpp | 3 ++- modules/calib3d/src/stereosgbm.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/calib3d/src/stereobm.cpp b/modules/calib3d/src/stereobm.cpp index a005c66d24..7b583dbe3c 100644 --- a/modules/calib3d/src/stereobm.cpp +++ b/modules/calib3d/src/stereobm.cpp @@ -962,7 +962,8 @@ public: void read(const FileNode& fn) { - CV_Assert( (std::string)fn["name"] == std::string(name_) ); + FileNode n = fn["name"]; + CV_Assert( n.isString() && strcmp(n.node->data.str.ptr, name_) == 0 ); params.minDisparity = (int)fn["minDisparity"]; params.numDisparities = (int)fn["numDisparities"]; params.SADWindowSize = (int)fn["blockSize"]; diff --git a/modules/calib3d/src/stereosgbm.cpp b/modules/calib3d/src/stereosgbm.cpp index d46c4110c6..160d92637c 100644 --- a/modules/calib3d/src/stereosgbm.cpp +++ b/modules/calib3d/src/stereosgbm.cpp @@ -918,7 +918,8 @@ public: void read(const FileNode& fn) { - CV_Assert( (std::string)fn["name"] == std::string(name_) ); + FileNode n = fn["name"]; + CV_Assert( n.isString() && strcmp(n.node->data.str.ptr, name_) == 0 ); params.minDisparity = (int)fn["minDisparity"]; params.numDisparities = (int)fn["numDisparities"]; params.SADWindowSize = (int)fn["blockSize"];