diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index ab46838160..1d94e748d5 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -386,7 +386,9 @@ enum GrabCutModes { automatically initialized with GC_BGD .*/ GC_INIT_WITH_MASK = 1, /** The value means that the algorithm should just resume. */ - GC_EVAL = 2 + GC_EVAL = 2, + /** The value means that the algorithm should just run the grabCut algorithm (a single iteration) with the fixed model */ + GC_EVAL_FREEZE_MODEL = 3 }; //! distanceTransform algorithm flags diff --git a/modules/imgproc/src/grabcut.cpp b/modules/imgproc/src/grabcut.cpp index 615b52ea7c..6edce405cb 100644 --- a/modules/imgproc/src/grabcut.cpp +++ b/modules/imgproc/src/grabcut.cpp @@ -557,7 +557,10 @@ void cv::grabCut( InputArray _img, InputOutputArray _mask, Rect rect, if( iterCount <= 0) return; - if( mode == GC_EVAL ) + if( mode == GC_EVAL_FREEZE_MODEL ) + iterCount = 1; + + if( mode == GC_EVAL || mode == GC_EVAL_FREEZE_MODEL ) checkMask( img, mask ); const double gamma = 50; @@ -571,7 +574,8 @@ void cv::grabCut( InputArray _img, InputOutputArray _mask, Rect rect, { GCGraph graph; assignGMMsComponents( img, mask, bgdGMM, fgdGMM, compIdxs ); - learnGMMs( img, mask, compIdxs, bgdGMM, fgdGMM ); + if( mode != GC_EVAL_FREEZE_MODEL ) + learnGMMs( img, mask, compIdxs, bgdGMM, fgdGMM ); constructGCGraph(img, mask, bgdGMM, fgdGMM, lambda, leftW, upleftW, upW, uprightW, graph ); estimateSegmentation( graph, mask ); } diff --git a/modules/imgproc/test/test_grabcut.cpp b/modules/imgproc/test/test_grabcut.cpp index 5b711b3edb..eae8b3e482 100644 --- a/modules/imgproc/test/test_grabcut.cpp +++ b/modules/imgproc/test/test_grabcut.cpp @@ -92,7 +92,9 @@ void CV_GrabcutTest::run( int /* start_from */) mask = Scalar(0); Mat bgdModel, fgdModel; grabCut( img, mask, rect, bgdModel, fgdModel, 0, GC_INIT_WITH_RECT ); - grabCut( img, mask, rect, bgdModel, fgdModel, 2, GC_EVAL ); + bgdModel.copyTo(exp_bgdModel); + fgdModel.copyTo(exp_fgdModel); + grabCut( img, mask, rect, bgdModel, fgdModel, 2, GC_EVAL_FREEZE_MODEL ); // Multiply images by 255 for more visuality of test data. if( mask_prob.empty() ) @@ -105,12 +107,20 @@ void CV_GrabcutTest::run( int /* start_from */) exp_mask1 = (mask & 1) * 255; imwrite(string(ts->get_data_path()) + "grabcut/exp_mask1.png", exp_mask1); } - if (!verify((mask & 1) * 255, exp_mask1)) { ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); return; } + // The model should not be changed after calling with GC_EVAL_FREEZE_MODEL + double sumBgdModel = cv::sum(cv::abs(bgdModel) - cv::abs(exp_bgdModel))[0]; + double sumFgdModel = cv::sum(cv::abs(fgdModel) - cv::abs(exp_fgdModel))[0]; + if (sumBgdModel >= 0.1 || sumFgdModel >= 0.1) + { + ts->printf(cvtest::TS::LOG, "sumBgdModel = %f, sumFgdModel = %f\n", sumBgdModel, sumFgdModel); + ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); + return; + } mask = mask_prob; bgdModel.release(); @@ -124,7 +134,6 @@ void CV_GrabcutTest::run( int /* start_from */) exp_mask2 = (mask & 1) * 255; imwrite(string(ts->get_data_path()) + "grabcut/exp_mask2.png", exp_mask2); } - if (!verify((mask & 1) * 255, exp_mask2)) { ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);