diff --git a/modules/calib3d/test/test_stereomatching.cpp b/modules/calib3d/test/test_stereomatching.cpp index 3a0d73ce55..90e9ae4edf 100644 --- a/modules/calib3d/test/test_stereomatching.cpp +++ b/modules/calib3d/test/test_stereomatching.cpp @@ -326,9 +326,15 @@ string ERROR_PREFIXES[] = { "borderedAll", "borderedTextureless", "borderedDepthDiscont" }; // size of ERROR_KINDS_COUNT +string ROI_PREFIXES[] = { "roiX", + "roiY", + "roiWidth", + "roiHeight" }; + const string RMS_STR = "RMS"; const string BAD_PXLS_FRACTION_STR = "BadPxlsFraction"; +const string ROI_STR = "ValidDisparityROI"; class QualityEvalParams { @@ -366,16 +372,20 @@ public: protected: // assumed that left image is a reference image virtual int runStereoMatchingAlgorithm( const Mat& leftImg, const Mat& rightImg, - Mat& leftDisp, Mat& rightDisp, int caseIdx ) = 0; // return ignored border width + Rect& calcROI, Mat& leftDisp, Mat& rightDisp, int caseIdx ) = 0; // return ignored border width int readDatasetsParams( FileStorage& fs ); virtual int readRunParams( FileStorage& fs ); void writeErrors( const string& errName, const vector& errors, FileStorage* fs = 0 ); + void writeROI( const Rect& calcROI, FileStorage* fs = 0 ); void readErrors( FileNode& fn, const string& errName, vector& errors ); + void readROI( FileNode& fn, Rect& trueROI ); int compareErrors( const vector& calcErrors, const vector& validErrors, const vector& eps, const string& errName ); + int compareROI( const Rect& calcROI, const Rect& validROI ); int processStereoMatchingResults( FileStorage& fs, int caseIdx, bool isWrite, const Mat& leftImg, const Mat& rightImg, + const Rect& calcROI, const Mat& trueLeftDisp, const Mat& trueRightDisp, const Mat& leftDisp, const Mat& rightDisp, const QualityEvalParams& qualityEvalParams ); @@ -451,6 +461,7 @@ void CV_StereoMatchingTest::run(int) Mat rightImg = imread(datasetFullDirName + RIGHT_IMG_NAME); Mat trueLeftDisp = imread(datasetFullDirName + TRUE_LEFT_DISP_NAME, 0); Mat trueRightDisp = imread(datasetFullDirName + TRUE_RIGHT_DISP_NAME, 0); + Rect calcROI; if( leftImg.empty() || rightImg.empty() || trueLeftDisp.empty() ) { @@ -473,7 +484,7 @@ void CV_StereoMatchingTest::run(int) } Mat leftDisp, rightDisp; - int ignBorder = max(runStereoMatchingAlgorithm(leftImg, rightImg, leftDisp, rightDisp, ci), EVAL_IGNORE_BORDER); + int ignBorder = max(runStereoMatchingAlgorithm(leftImg, rightImg, calcROI, leftDisp, rightDisp, ci), EVAL_IGNORE_BORDER); leftDisp.convertTo( tmp, CV_32FC1 ); leftDisp = tmp; @@ -484,7 +495,7 @@ void CV_StereoMatchingTest::run(int) tmp.release(); int tempCode = processStereoMatchingResults( resFS, ci, isWrite, - leftImg, rightImg, trueLeftDisp, trueRightDisp, leftDisp, rightDisp, QualityEvalParams(ignBorder)); + leftImg, rightImg, calcROI, trueLeftDisp, trueRightDisp, leftDisp, rightDisp, QualityEvalParams(ignBorder)); code = tempCode==cvtest::TS::OK ? code : tempCode; } @@ -538,6 +549,7 @@ void calcErrors( const Mat& leftImg, const Mat& /*rightImg*/, int CV_StereoMatchingTest::processStereoMatchingResults( FileStorage& fs, int caseIdx, bool isWrite, const Mat& leftImg, const Mat& rightImg, + const Rect& calcROI, const Mat& trueLeftDisp, const Mat& trueRightDisp, const Mat& leftDisp, const Mat& rightDisp, const QualityEvalParams& qualityEvalParams ) @@ -574,6 +586,8 @@ int CV_StereoMatchingTest::processStereoMatchingResults( FileStorage& fs, int ca writeErrors( RMS_STR, rmss, &fs ); cvWriteComment( fs.fs, BAD_PXLS_FRACTION_STR.c_str(), 0 ); writeErrors( BAD_PXLS_FRACTION_STR, badPxlsFractions, &fs ); + cvWriteComment( fs.fs, ROI_STR.c_str(), 0 ); + writeROI( calcROI, &fs ); fs << "}"; // datasetName } else // compare @@ -583,16 +597,22 @@ int CV_StereoMatchingTest::processStereoMatchingResults( FileStorage& fs, int ca writeErrors( RMS_STR, rmss ); ts->printf( cvtest::TS::LOG, "%s\n", BAD_PXLS_FRACTION_STR.c_str() ); writeErrors( BAD_PXLS_FRACTION_STR, badPxlsFractions ); + ts->printf( cvtest::TS::LOG, "%s\n", ROI_STR.c_str() ); + writeROI( calcROI ); FileNode fn = fs.getFirstTopLevelNode()[caseNames[caseIdx]]; vector validRmss, validBadPxlsFractions; + Rect validROI; readErrors( fn, RMS_STR, validRmss ); readErrors( fn, BAD_PXLS_FRACTION_STR, validBadPxlsFractions ); + readROI( fn, validROI ); int tempCode = compareErrors( rmss, validRmss, rmsEps, RMS_STR ); code = tempCode==cvtest::TS::OK ? code : tempCode; tempCode = compareErrors( badPxlsFractions, validBadPxlsFractions, fracEps, BAD_PXLS_FRACTION_STR ); code = tempCode==cvtest::TS::OK ? code : tempCode; + tempCode = compareROI( calcROI, validROI ); + code = tempCode==cvtest::TS::OK ? code : tempCode; } return code; } @@ -642,6 +662,24 @@ void CV_StereoMatchingTest::writeErrors( const string& errName, const vectorprintf( cvtest::TS::LOG, "%s = %f\n", string(ERROR_PREFIXES[i]+errName).c_str(), *it ); } +void CV_StereoMatchingTest::writeROI( const Rect& calcROI, FileStorage* fs ) +{ + if( fs ) + { + *fs << ROI_PREFIXES[0] << calcROI.x; + *fs << ROI_PREFIXES[1] << calcROI.y; + *fs << ROI_PREFIXES[2] << calcROI.width; + *fs << ROI_PREFIXES[3] << calcROI.height; + } + else + { + ts->printf( cvtest::TS::LOG, "%s = %d\n", ROI_PREFIXES[0].c_str(), calcROI.x ); + ts->printf( cvtest::TS::LOG, "%s = %d\n", ROI_PREFIXES[1].c_str(), calcROI.y ); + ts->printf( cvtest::TS::LOG, "%s = %d\n", ROI_PREFIXES[2].c_str(), calcROI.width ); + ts->printf( cvtest::TS::LOG, "%s = %d\n", ROI_PREFIXES[3].c_str(), calcROI.height ); + } +} + void CV_StereoMatchingTest::readErrors( FileNode& fn, const string& errName, vector& errors ) { errors.resize( ERROR_KINDS_COUNT ); @@ -650,6 +688,14 @@ void CV_StereoMatchingTest::readErrors( FileNode& fn, const string& errName, vec fn[ERROR_PREFIXES[i]+errName] >> *it; } +void CV_StereoMatchingTest::readROI( FileNode& fn, Rect& validROI ) +{ + fn[ROI_PREFIXES[0]] >> validROI.x; + fn[ROI_PREFIXES[1]] >> validROI.y; + fn[ROI_PREFIXES[2]] >> validROI.width; + fn[ROI_PREFIXES[3]] >> validROI.height; +} + int CV_StereoMatchingTest::compareErrors( const vector& calcErrors, const vector& validErrors, const vector& eps, const string& errName ) { @@ -669,6 +715,26 @@ int CV_StereoMatchingTest::compareErrors( const vector& calcErrors, const return ok ? cvtest::TS::OK : cvtest::TS::FAIL_BAD_ACCURACY; } +int CV_StereoMatchingTest::compareROI( const Rect& calcROI, const Rect& validROI ) +{ + int compare[4][2] = { + { calcROI.x, validROI.x }, + { calcROI.y, validROI.y }, + { calcROI.width, validROI.width }, + { calcROI.height, validROI.height }, + }; + bool ok = true; + for (int i = 0; i < 4; i++) + { + if (compare[i][0] != compare[i][1]) + { + ts->printf( cvtest::TS::LOG, "bad accuracy of %s (valid=%d; calc=%d)\n", ROI_PREFIXES[i].c_str(), compare[i][1], compare[i][0] ); + ok = false; + } + } + return ok ? cvtest::TS::OK : cvtest::TS::FAIL_BAD_ACCURACY; +} + //----------------------------------- StereoBM test ----------------------------------------------------- class CV_StereoBMTest : public CV_StereoMatchingTest @@ -685,6 +751,7 @@ protected: struct RunParams { int ndisp; + int mindisp; int winSize; }; vector caseRunParams; @@ -694,12 +761,13 @@ protected: int code = CV_StereoMatchingTest::readRunParams( fs ); FileNode fn = fs.getFirstTopLevelNode(); assert(fn.isSeq()); - for( int i = 0; i < (int)fn.size(); i+=4 ) + for( int i = 0; i < (int)fn.size(); i+=5 ) { string caseName = fn[i], datasetName = fn[i+1]; RunParams params; - string ndisp = fn[i+2]; params.ndisp = atoi(ndisp.c_str()); - string winSize = fn[i+3]; params.winSize = atoi(winSize.c_str()); + String ndisp = fn[i+2]; params.ndisp = atoi(ndisp.c_str()); + String mindisp = fn[i+3]; params.mindisp = atoi(mindisp.c_str()); + String winSize = fn[i+4]; params.winSize = atoi(winSize.c_str()); caseNames.push_back( caseName ); caseDatasets.push_back( datasetName ); caseRunParams.push_back( params ); @@ -708,7 +776,7 @@ protected: } virtual int runStereoMatchingAlgorithm( const Mat& _leftImg, const Mat& _rightImg, - Mat& leftDisp, Mat& /*rightDisp*/, int caseIdx ) + Rect& calcROI, Mat& leftDisp, Mat& /*rightDisp*/, int caseIdx ) { RunParams params = caseRunParams[caseIdx]; assert( params.ndisp%16 == 0 ); @@ -717,7 +785,21 @@ protected: Mat rightImg; cvtColor( _rightImg, rightImg, CV_BGR2GRAY ); StereoBM bm( StereoBM::BASIC_PRESET, params.ndisp, params.winSize ); + bm.state->minDisparity = params.mindisp; + + Rect cROI(0, 0, _leftImg.cols, _leftImg.rows); + calcROI = getValidDisparityROI(cROI, cROI, params.mindisp, params.ndisp, params.winSize); + bm( leftImg, rightImg, leftDisp, CV_32F ); + + if (params.mindisp != 0) + for (int y = 0; y < leftDisp.rows; y++) + for (int x = 0; x < leftDisp.cols; x++) + { + if (leftDisp.at(y, x) < params.mindisp) + leftDisp.at(y, x) = -0.0625; // treat disparity < mindisp as no disparity + } + return params.winSize/2; } }; @@ -754,7 +836,13 @@ protected: RunParams params; string ndisp = fn[i+2]; params.ndisp = atoi(ndisp.c_str()); string winSize = fn[i+3]; params.winSize = atoi(winSize.c_str()); - string fullDP = fn[i+4]; params.fullDP = atoi(fullDP.c_str()) == 0 ? false : true; + string fullDP = fn[i+4]; + int n = atoi(fullDP.c_str()); + params.fullDP = n == 0 ? false : true; + + if (n > 1) + continue; // OpenCV 3+ compatibility - skip tests for mode > 1 + caseNames.push_back( caseName ); caseDatasets.push_back( datasetName ); caseRunParams.push_back( params ); @@ -763,12 +851,16 @@ protected: } virtual int runStereoMatchingAlgorithm( const Mat& leftImg, const Mat& rightImg, - Mat& leftDisp, Mat& /*rightDisp*/, int caseIdx ) + Rect& calcROI, Mat& leftDisp, Mat& /*rightDisp*/, int caseIdx ) { 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 ); + + Rect cROI(0, 0, leftImg.cols, leftImg.rows); + calcROI = getValidDisparityROI(cROI, cROI, 0, params.ndisp, params.winSize); + sgbm( leftImg, rightImg, leftDisp ); assert( leftDisp.type() == CV_16SC1 ); leftDisp/=16;