diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 3936daf08b..e324f85dac 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -2530,6 +2530,12 @@ static bool ipp_minMaxIdx(Mat &src, double* _minVal, double* _maxVal, int* _minI return false; #endif + // cv::minMaxIdx problem with index positions on AVX +#if IPP_VERSION_X100 < 201810 + if(!mask.empty() && _maxIdx && ipp::getIppFeatures()&ippCPUID_AVX) + return false; +#endif + IppStatus status; IppDataType dataType = ippiGetDataType(src.depth()); float minVal = 0; @@ -2561,7 +2567,7 @@ static bool ipp_minMaxIdx(Mat &src, double* _minVal, double* _maxVal, int* _minI size.width *= src.channels(); status = ippMinMaxFun(src.ptr(), (int)src.step, size, dataType, pMinVal, pMaxVal, pMinIdx, pMaxIdx, (Ipp8u*)mask.ptr(), (int)mask.step); - if(status < 0 || status == ippStsNoOperation) + if(status < 0) return false; if(_minVal) *_minVal = minVal; @@ -2569,7 +2575,8 @@ static bool ipp_minMaxIdx(Mat &src, double* _minVal, double* _maxVal, int* _minI *_maxVal = maxVal; if(_minIdx) { - if(!mask.empty() && !minIdx.y && !minIdx.x) + // Should be just ippStsNoOperation check, but there is a bug in the function so we need additional checks + if(status == ippStsNoOperation && !mask.empty() && !pMinIdx->x && !pMinIdx->y) { _minIdx[0] = -1; _minIdx[1] = -1; @@ -2582,7 +2589,8 @@ static bool ipp_minMaxIdx(Mat &src, double* _minVal, double* _maxVal, int* _minI } if(_maxIdx) { - if(!mask.empty() && !maxIdx.y && !maxIdx.x) + // Should be just ippStsNoOperation check, but there is a bug in the function so we need additional checks + if(status == ippStsNoOperation && !mask.empty() && !pMaxIdx->x && !pMaxIdx->y) { _maxIdx[0] = -1; _maxIdx[1] = -1; diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index bac5c7ff7b..78c0689852 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -1932,3 +1932,77 @@ TEST(Compare, regression_8999) compare(A, B, C, CMP_LT); }); } + + +TEST(Core_minMaxIdx, regression_9207_1) +{ + const int rows = 4; + const int cols = 3; + uchar mask_[rows*cols] = { + 255, 255, 255, + 255, 0, 255, + 0, 255, 255, + 0, 0, 255 +}; + uchar src_[rows*cols] = { + 1, 1, 1, + 1, 1, 1, + 2, 1, 1, + 2, 2, 1 +}; + Mat mask(Size(cols, rows), CV_8UC1, mask_); + Mat src(Size(cols, rows), CV_8UC1, src_); + double minVal = -0.0, maxVal = -0.0; + int minIdx[2] = { -2, -2 }, maxIdx[2] = { -2, -2 }; + minMaxIdx(src, &minVal, &maxVal, minIdx, maxIdx, mask); + EXPECT_EQ(0, minIdx[0]); + EXPECT_EQ(0, minIdx[1]); + EXPECT_EQ(0, maxIdx[0]); + EXPECT_EQ(0, maxIdx[1]); +} + + +TEST(Core_minMaxIdx, regression_9207_2) +{ + const int rows = 13; + const int cols = 15; + uchar mask_[rows*cols] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, + 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, + 255, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, + 255, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 255, + 255, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 255, 255, 255, 0, + 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 0, 255, 0, + 255, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 255, 255, 0, + 255, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, + 255, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 255, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + uchar src_[15*13] = { + 5, 5, 5, 5, 5, 6, 5, 2, 0, 4, 6, 6, 4, 1, 0, + 6, 5, 4, 4, 5, 6, 6, 5, 2, 0, 4, 6, 5, 2, 0, + 3, 2, 1, 1, 2, 4, 6, 6, 4, 2, 3, 4, 4, 2, 0, + 1, 0, 0, 0, 0, 1, 4, 5, 4, 4, 4, 4, 3, 2, 0, + 0, 0, 0, 0, 0, 0, 2, 3, 4, 4, 4, 3, 2, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 3, 2, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 3, 3, 1, 0, 1, + 0, 0, 0, 0, 0, 0, 1, 4, 5, 6, 5, 4, 3, 2, 0, + 1, 0, 0, 0, 0, 0, 3, 5, 5, 4, 3, 4, 4, 3, 0, + 2, 0, 0, 0, 0, 2, 5, 6, 5, 2, 2, 5, 4, 3, 0 +}; + Mat mask(Size(cols, rows), CV_8UC1, mask_); + Mat src(Size(cols, rows), CV_8UC1, src_); + double minVal = -0.0, maxVal = -0.0; + int minIdx[2] = { -2, -2 }, maxIdx[2] = { -2, -2 }; + minMaxIdx(src, &minVal, &maxVal, minIdx, maxIdx, mask); + EXPECT_EQ(0, minIdx[0]); + EXPECT_EQ(14, minIdx[1]); + EXPECT_EQ(0, maxIdx[0]); + EXPECT_EQ(14, maxIdx[1]); +}