mirror of
https://github.com/opencv/opencv.git
synced 2026-07-21 19:33:03 +04:00
Merge pull request #27125 from asmorkalov:as/ipp_minmax
Move IPP minMaxIdx to HAL
This commit is contained in:
Vendored
+4
-2
@@ -8,8 +8,10 @@ set(IPP_HAL_HEADERS
|
||||
CACHE INTERNAL "")
|
||||
|
||||
add_library(ipphal STATIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/mean_ipp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/norm_ipp.cpp")
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/mean_ipp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/minmax_ipp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/norm_ipp.cpp"
|
||||
)
|
||||
|
||||
if(HAVE_IPP_ICV)
|
||||
target_compile_definitions(ipphal PRIVATE HAVE_IPP_ICV)
|
||||
|
||||
+6
@@ -11,6 +11,12 @@ int ipp_hal_meanStdDev(const uchar* src_data, size_t src_step, int width, int he
|
||||
#undef cv_hal_meanStdDev
|
||||
#define cv_hal_meanStdDev ipp_hal_meanStdDev
|
||||
|
||||
int ipp_hal_minMaxIdxMaskStep(const uchar* src_data, size_t src_step, int width, int height, int depth,
|
||||
double* _minVal, double* _maxVal, int* _minIdx, int* _maxIdx, uchar* mask, size_t mask_step);
|
||||
|
||||
#undef cv_hal_minMaxIdxMaskStep
|
||||
#define cv_hal_minMaxIdxMaskStep ipp_hal_minMaxIdxMaskStep
|
||||
|
||||
#define IPP_DISABLE_NORM_8U 1 // accuracy difference in perf test sanity check
|
||||
|
||||
int ipp_hal_norm(const uchar* src, size_t src_step, const uchar* mask, size_t mask_step,
|
||||
|
||||
Vendored
+252
@@ -0,0 +1,252 @@
|
||||
#include "ipp_hal_core.hpp"
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/core/base.hpp>
|
||||
|
||||
#define IPP_DISABLE_MINMAXIDX_MANY_ROWS 1 // see Core_MinMaxIdx.rows_overflow test
|
||||
|
||||
static inline IppDataType ippiGetDataType(int depth)
|
||||
{
|
||||
depth = CV_MAT_DEPTH(depth);
|
||||
return depth == CV_8U ? ipp8u :
|
||||
depth == CV_8S ? ipp8s :
|
||||
depth == CV_16U ? ipp16u :
|
||||
depth == CV_16S ? ipp16s :
|
||||
depth == CV_32S ? ipp32s :
|
||||
depth == CV_32F ? ipp32f :
|
||||
depth == CV_64F ? ipp64f :
|
||||
(IppDataType)-1;
|
||||
}
|
||||
|
||||
#if IPP_VERSION_X100 >= 700
|
||||
|
||||
|
||||
static IppStatus ipp_minMaxIndex_wrap(const void* pSrc, int srcStep, IppiSize size, IppDataType dataType,
|
||||
float* pMinVal, float* pMaxVal, IppiPoint* pMinIndex, IppiPoint* pMaxIndex, const Ipp8u*, int)
|
||||
{
|
||||
switch(dataType)
|
||||
{
|
||||
case ipp8u: return CV_INSTRUMENT_FUN_IPP(ippiMinMaxIndx_8u_C1R, (const Ipp8u*)pSrc, srcStep, size, pMinVal, pMaxVal, pMinIndex, pMaxIndex);
|
||||
case ipp16u: return CV_INSTRUMENT_FUN_IPP(ippiMinMaxIndx_16u_C1R, (const Ipp16u*)pSrc, srcStep, size, pMinVal, pMaxVal, pMinIndex, pMaxIndex);
|
||||
case ipp32f: return CV_INSTRUMENT_FUN_IPP(ippiMinMaxIndx_32f_C1R, (const Ipp32f*)pSrc, srcStep, size, pMinVal, pMaxVal, pMinIndex, pMaxIndex);
|
||||
default: return ippStsDataTypeErr;
|
||||
}
|
||||
}
|
||||
|
||||
static IppStatus ipp_minMaxIndexMask_wrap(const void* pSrc, int srcStep, IppiSize size, IppDataType dataType,
|
||||
float* pMinVal, float* pMaxVal, IppiPoint* pMinIndex, IppiPoint* pMaxIndex, const Ipp8u* pMask, int maskStep)
|
||||
{
|
||||
switch(dataType)
|
||||
{
|
||||
case ipp8u: return CV_INSTRUMENT_FUN_IPP(ippiMinMaxIndx_8u_C1MR, (const Ipp8u*)pSrc, srcStep, pMask, maskStep, size, pMinVal, pMaxVal, pMinIndex, pMaxIndex);
|
||||
case ipp16u: return CV_INSTRUMENT_FUN_IPP(ippiMinMaxIndx_16u_C1MR, (const Ipp16u*)pSrc, srcStep, pMask, maskStep, size, pMinVal, pMaxVal, pMinIndex, pMaxIndex);
|
||||
case ipp32f: return CV_INSTRUMENT_FUN_IPP(ippiMinMaxIndx_32f_C1MR, (const Ipp32f*)pSrc, srcStep, pMask, maskStep, size, pMinVal, pMaxVal, pMinIndex, pMaxIndex);
|
||||
default: return ippStsDataTypeErr;
|
||||
}
|
||||
}
|
||||
|
||||
static IppStatus ipp_minMax_wrap(const void* pSrc, int srcStep, IppiSize size, IppDataType dataType,
|
||||
float* pMinVal, float* pMaxVal, IppiPoint*, IppiPoint*, const Ipp8u*, int)
|
||||
{
|
||||
IppStatus status;
|
||||
|
||||
switch(dataType)
|
||||
{
|
||||
#if IPP_VERSION_X100 > 201701 // wrong min values
|
||||
case ipp8u:
|
||||
{
|
||||
Ipp8u val[2];
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMinMax_8u_C1R, (const Ipp8u*)pSrc, srcStep, size, &val[0], &val[1]);
|
||||
*pMinVal = val[0];
|
||||
*pMaxVal = val[1];
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
case ipp16u:
|
||||
{
|
||||
Ipp16u val[2];
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMinMax_16u_C1R, (const Ipp16u*)pSrc, srcStep, size, &val[0], &val[1]);
|
||||
*pMinVal = val[0];
|
||||
*pMaxVal = val[1];
|
||||
return status;
|
||||
}
|
||||
case ipp16s:
|
||||
{
|
||||
Ipp16s val[2];
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMinMax_16s_C1R, (const Ipp16s*)pSrc, srcStep, size, &val[0], &val[1]);
|
||||
*pMinVal = val[0];
|
||||
*pMaxVal = val[1];
|
||||
return status;
|
||||
}
|
||||
case ipp32f: return CV_INSTRUMENT_FUN_IPP(ippiMinMax_32f_C1R, (const Ipp32f*)pSrc, srcStep, size, pMinVal, pMaxVal);
|
||||
default: return ipp_minMaxIndex_wrap(pSrc, srcStep, size, dataType, pMinVal, pMaxVal, NULL, NULL, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static IppStatus ipp_minIdx_wrap(const void* pSrc, int srcStep, IppiSize size, IppDataType dataType,
|
||||
float* pMinVal, float*, IppiPoint* pMinIndex, IppiPoint*, const Ipp8u*, int)
|
||||
{
|
||||
IppStatus status;
|
||||
|
||||
switch(dataType)
|
||||
{
|
||||
case ipp8u:
|
||||
{
|
||||
Ipp8u val;
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMinIndx_8u_C1R, (const Ipp8u*)pSrc, srcStep, size, &val, &pMinIndex->x, &pMinIndex->y);
|
||||
*pMinVal = val;
|
||||
return status;
|
||||
}
|
||||
case ipp16u:
|
||||
{
|
||||
Ipp16u val;
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMinIndx_16u_C1R, (const Ipp16u*)pSrc, srcStep, size, &val, &pMinIndex->x, &pMinIndex->y);
|
||||
*pMinVal = val;
|
||||
return status;
|
||||
}
|
||||
case ipp16s:
|
||||
{
|
||||
Ipp16s val;
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMinIndx_16s_C1R, (const Ipp16s*)pSrc, srcStep, size, &val, &pMinIndex->x, &pMinIndex->y);
|
||||
*pMinVal = val;
|
||||
return status;
|
||||
}
|
||||
case ipp32f: return CV_INSTRUMENT_FUN_IPP(ippiMinIndx_32f_C1R, (const Ipp32f*)pSrc, srcStep, size, pMinVal, &pMinIndex->x, &pMinIndex->y);
|
||||
default: return ipp_minMaxIndex_wrap(pSrc, srcStep, size, dataType, pMinVal, NULL, pMinIndex, NULL, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static IppStatus ipp_maxIdx_wrap(const void* pSrc, int srcStep, IppiSize size, IppDataType dataType,
|
||||
float*, float* pMaxVal, IppiPoint*, IppiPoint* pMaxIndex, const Ipp8u*, int)
|
||||
{
|
||||
IppStatus status;
|
||||
|
||||
switch(dataType)
|
||||
{
|
||||
case ipp8u:
|
||||
{
|
||||
Ipp8u val;
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMaxIndx_8u_C1R, (const Ipp8u*)pSrc, srcStep, size, &val, &pMaxIndex->x, &pMaxIndex->y);
|
||||
*pMaxVal = val;
|
||||
return status;
|
||||
}
|
||||
case ipp16u:
|
||||
{
|
||||
Ipp16u val;
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMaxIndx_16u_C1R, (const Ipp16u*)pSrc, srcStep, size, &val, &pMaxIndex->x, &pMaxIndex->y);
|
||||
*pMaxVal = val;
|
||||
return status;
|
||||
}
|
||||
case ipp16s:
|
||||
{
|
||||
Ipp16s val;
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMaxIndx_16s_C1R, (const Ipp16s*)pSrc, srcStep, size, &val, &pMaxIndex->x, &pMaxIndex->y);
|
||||
*pMaxVal = val;
|
||||
return status;
|
||||
}
|
||||
case ipp32f: return CV_INSTRUMENT_FUN_IPP(ippiMaxIndx_32f_C1R, (const Ipp32f*)pSrc, srcStep, size, pMaxVal, &pMaxIndex->x, &pMaxIndex->y);
|
||||
default: return ipp_minMaxIndex_wrap(pSrc, srcStep, size, dataType, NULL, pMaxVal, NULL, pMaxIndex, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
typedef IppStatus (*IppMinMaxSelector)(const void* pSrc, int srcStep, IppiSize size, IppDataType dataType,
|
||||
float* pMinVal, float* pMaxVal, IppiPoint* pMinIndex, IppiPoint* pMaxIndex, const Ipp8u* pMask, int maskStep);
|
||||
|
||||
|
||||
int ipp_hal_minMaxIdxMaskStep(const uchar* src_data, size_t src_step, int width, int height, int depth,
|
||||
double* _minVal, double* _maxVal, int* _minIdx, int* _maxIdx, uchar* mask, size_t mask_step)
|
||||
{
|
||||
#if IPP_VERSION_X100 < 201800
|
||||
// cv::minMaxIdx problem with NaN input
|
||||
// Disable 32F processing only
|
||||
if(depth == CV_32F && cv::ipp::getIppTopFeatures() == ippCPUID_SSE42)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
|
||||
#if IPP_VERSION_X100 < 201801
|
||||
// cv::minMaxIdx problem with index positions on AVX
|
||||
if(mask && _maxIdx && cv::ipp::getIppTopFeatures() != ippCPUID_SSE42)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
|
||||
IppStatus status;
|
||||
IppDataType dataType = ippiGetDataType(depth);
|
||||
float minVal = 0;
|
||||
float maxVal = 0;
|
||||
IppiPoint minIdx = {-1, -1};
|
||||
IppiPoint maxIdx = {-1, -1};
|
||||
|
||||
float *pMinVal = (_minVal || _minIdx)?&minVal:NULL;
|
||||
float *pMaxVal = (_maxVal || _maxIdx)?&maxVal:NULL;
|
||||
IppiPoint *pMinIdx = (_minIdx)?&minIdx:NULL;
|
||||
IppiPoint *pMaxIdx = (_maxIdx)?&maxIdx:NULL;
|
||||
|
||||
IppMinMaxSelector ippMinMaxFun = ipp_minMaxIndexMask_wrap;
|
||||
if(!mask)
|
||||
{
|
||||
if(_maxVal && _maxIdx && !_minVal && !_minIdx)
|
||||
ippMinMaxFun = ipp_maxIdx_wrap;
|
||||
else if(!_maxVal && !_maxIdx && _minVal && _minIdx)
|
||||
ippMinMaxFun = ipp_minIdx_wrap;
|
||||
else if(_maxVal && !_maxIdx && _minVal && !_minIdx)
|
||||
ippMinMaxFun = ipp_minMax_wrap;
|
||||
else if(!_maxVal && !_maxIdx && !_minVal && !_minIdx)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
else
|
||||
ippMinMaxFun = ipp_minMaxIndex_wrap;
|
||||
}
|
||||
|
||||
IppiSize size = { width, height };
|
||||
#if defined(_WIN32) && !defined(_WIN64) && IPP_VERSION_X100 == 201900 && IPP_DISABLE_MINMAXIDX_MANY_ROWS
|
||||
if (size.height > 65536)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED; // test: Core_MinMaxIdx.rows_overflow
|
||||
#endif
|
||||
|
||||
status = ippMinMaxFun(src_data, (int)src_step, size, dataType, pMinVal, pMaxVal, pMinIdx, pMaxIdx, (Ipp8u*)mask, (int)mask_step);
|
||||
if(status < 0)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
if(_minVal)
|
||||
*_minVal = minVal;
|
||||
if(_maxVal)
|
||||
*_maxVal = maxVal;
|
||||
if(_minIdx)
|
||||
{
|
||||
#if IPP_VERSION_X100 < 201801
|
||||
// Should be just ippStsNoOperation check, but there is a bug in the function so we need additional checks
|
||||
if(status == ippStsNoOperation && mask && !pMinIdx->x && !pMinIdx->y)
|
||||
#else
|
||||
if(status == ippStsNoOperation)
|
||||
#endif
|
||||
{
|
||||
_minIdx[0] = -1;
|
||||
_minIdx[1] = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_minIdx[0] = minIdx.y;
|
||||
_minIdx[1] = minIdx.x;
|
||||
}
|
||||
}
|
||||
if(_maxIdx)
|
||||
{
|
||||
#if IPP_VERSION_X100 < 201801
|
||||
// Should be just ippStsNoOperation check, but there is a bug in the function so we need additional checks
|
||||
if(status == ippStsNoOperation && mask && !pMaxIdx->x && !pMaxIdx->y)
|
||||
#else
|
||||
if(status == ippStsNoOperation)
|
||||
#endif
|
||||
{
|
||||
_maxIdx[0] = -1;
|
||||
_maxIdx[1] = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_maxIdx[0] = maxIdx.y;
|
||||
_maxIdx[1] = maxIdx.x;
|
||||
}
|
||||
}
|
||||
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
#endif // IPP_VERSION_X100 >= 700
|
||||
@@ -7,24 +7,9 @@
|
||||
#include "opencl_kernels_core.hpp"
|
||||
#include "stat.hpp"
|
||||
|
||||
#ifndef OPENCV_IPP_MEAN
|
||||
#undef HAVE_IPP
|
||||
#undef CV_IPP_RUN_FAST
|
||||
#define CV_IPP_RUN_FAST(f, ...)
|
||||
#undef CV_IPP_RUN
|
||||
#define CV_IPP_RUN(c, f, ...)
|
||||
#endif // OPENCV_IPP_MEAN
|
||||
|
||||
#include "mean.simd.hpp"
|
||||
#include "mean.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
|
||||
|
||||
#ifndef OPENCV_IPP_MEAN
|
||||
#undef HAVE_IPP
|
||||
#undef CV_IPP_RUN_FAST
|
||||
#define CV_IPP_RUN_FAST(f, ...)
|
||||
#undef CV_IPP_RUN
|
||||
#define CV_IPP_RUN(c, f, ...)
|
||||
#endif // OPENCV_IPP_MEAN
|
||||
|
||||
namespace cv {
|
||||
|
||||
@@ -40,8 +25,6 @@ Scalar mean(InputArray _src, InputArray _mask)
|
||||
|
||||
CV_Assert( cn <= 4 );
|
||||
|
||||
CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_mean(src, mask, s), s)
|
||||
|
||||
if (src.isContinuous() && mask.isContinuous())
|
||||
{
|
||||
CALL_HAL_RET2(meanStdDev, cv_hal_meanStdDev, s, src.data, 0, (int)src.total(), 1, src.type(),
|
||||
|
||||
@@ -10,16 +10,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#ifndef OPENCV_IPP_MINMAX
|
||||
#undef HAVE_IPP
|
||||
#undef CV_IPP_RUN_FAST
|
||||
#define CV_IPP_RUN_FAST(f, ...)
|
||||
#undef CV_IPP_RUN
|
||||
#define CV_IPP_RUN(c, f, ...)
|
||||
#endif // OPENCV_IPP_MINMAX
|
||||
|
||||
#define IPP_DISABLE_MINMAXIDX_MANY_ROWS 1 // see Core_MinMaxIdx.rows_overflow test
|
||||
|
||||
/****************************************************************************************\
|
||||
* minMaxLoc *
|
||||
\****************************************************************************************/
|
||||
@@ -1118,306 +1108,6 @@ bool ocl_minMaxIdx( InputArray _src, double* minVal, double* maxVal, int* minLoc
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
static IppStatus ipp_minMaxIndex_wrap(const void* pSrc, int srcStep, IppiSize size, IppDataType dataType,
|
||||
float* pMinVal, float* pMaxVal, IppiPoint* pMinIndex, IppiPoint* pMaxIndex, const Ipp8u*, int)
|
||||
{
|
||||
switch(dataType)
|
||||
{
|
||||
case ipp8u: return CV_INSTRUMENT_FUN_IPP(ippiMinMaxIndx_8u_C1R, (const Ipp8u*)pSrc, srcStep, size, pMinVal, pMaxVal, pMinIndex, pMaxIndex);
|
||||
case ipp16u: return CV_INSTRUMENT_FUN_IPP(ippiMinMaxIndx_16u_C1R, (const Ipp16u*)pSrc, srcStep, size, pMinVal, pMaxVal, pMinIndex, pMaxIndex);
|
||||
case ipp32f: return CV_INSTRUMENT_FUN_IPP(ippiMinMaxIndx_32f_C1R, (const Ipp32f*)pSrc, srcStep, size, pMinVal, pMaxVal, pMinIndex, pMaxIndex);
|
||||
default: return ippStsDataTypeErr;
|
||||
}
|
||||
}
|
||||
|
||||
static IppStatus ipp_minMaxIndexMask_wrap(const void* pSrc, int srcStep, IppiSize size, IppDataType dataType,
|
||||
float* pMinVal, float* pMaxVal, IppiPoint* pMinIndex, IppiPoint* pMaxIndex, const Ipp8u* pMask, int maskStep)
|
||||
{
|
||||
switch(dataType)
|
||||
{
|
||||
case ipp8u: return CV_INSTRUMENT_FUN_IPP(ippiMinMaxIndx_8u_C1MR, (const Ipp8u*)pSrc, srcStep, pMask, maskStep, size, pMinVal, pMaxVal, pMinIndex, pMaxIndex);
|
||||
case ipp16u: return CV_INSTRUMENT_FUN_IPP(ippiMinMaxIndx_16u_C1MR, (const Ipp16u*)pSrc, srcStep, pMask, maskStep, size, pMinVal, pMaxVal, pMinIndex, pMaxIndex);
|
||||
case ipp32f: return CV_INSTRUMENT_FUN_IPP(ippiMinMaxIndx_32f_C1MR, (const Ipp32f*)pSrc, srcStep, pMask, maskStep, size, pMinVal, pMaxVal, pMinIndex, pMaxIndex);
|
||||
default: return ippStsDataTypeErr;
|
||||
}
|
||||
}
|
||||
|
||||
static IppStatus ipp_minMax_wrap(const void* pSrc, int srcStep, IppiSize size, IppDataType dataType,
|
||||
float* pMinVal, float* pMaxVal, IppiPoint*, IppiPoint*, const Ipp8u*, int)
|
||||
{
|
||||
IppStatus status;
|
||||
|
||||
switch(dataType)
|
||||
{
|
||||
#if IPP_VERSION_X100 > 201701 // wrong min values
|
||||
case ipp8u:
|
||||
{
|
||||
Ipp8u val[2];
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMinMax_8u_C1R, (const Ipp8u*)pSrc, srcStep, size, &val[0], &val[1]);
|
||||
*pMinVal = val[0];
|
||||
*pMaxVal = val[1];
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
case ipp16u:
|
||||
{
|
||||
Ipp16u val[2];
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMinMax_16u_C1R, (const Ipp16u*)pSrc, srcStep, size, &val[0], &val[1]);
|
||||
*pMinVal = val[0];
|
||||
*pMaxVal = val[1];
|
||||
return status;
|
||||
}
|
||||
case ipp16s:
|
||||
{
|
||||
Ipp16s val[2];
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMinMax_16s_C1R, (const Ipp16s*)pSrc, srcStep, size, &val[0], &val[1]);
|
||||
*pMinVal = val[0];
|
||||
*pMaxVal = val[1];
|
||||
return status;
|
||||
}
|
||||
case ipp32f: return CV_INSTRUMENT_FUN_IPP(ippiMinMax_32f_C1R, (const Ipp32f*)pSrc, srcStep, size, pMinVal, pMaxVal);
|
||||
default: return ipp_minMaxIndex_wrap(pSrc, srcStep, size, dataType, pMinVal, pMaxVal, NULL, NULL, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static IppStatus ipp_minIdx_wrap(const void* pSrc, int srcStep, IppiSize size, IppDataType dataType,
|
||||
float* pMinVal, float*, IppiPoint* pMinIndex, IppiPoint*, const Ipp8u*, int)
|
||||
{
|
||||
IppStatus status;
|
||||
|
||||
switch(dataType)
|
||||
{
|
||||
case ipp8u:
|
||||
{
|
||||
Ipp8u val;
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMinIndx_8u_C1R, (const Ipp8u*)pSrc, srcStep, size, &val, &pMinIndex->x, &pMinIndex->y);
|
||||
*pMinVal = val;
|
||||
return status;
|
||||
}
|
||||
case ipp16u:
|
||||
{
|
||||
Ipp16u val;
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMinIndx_16u_C1R, (const Ipp16u*)pSrc, srcStep, size, &val, &pMinIndex->x, &pMinIndex->y);
|
||||
*pMinVal = val;
|
||||
return status;
|
||||
}
|
||||
case ipp16s:
|
||||
{
|
||||
Ipp16s val;
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMinIndx_16s_C1R, (const Ipp16s*)pSrc, srcStep, size, &val, &pMinIndex->x, &pMinIndex->y);
|
||||
*pMinVal = val;
|
||||
return status;
|
||||
}
|
||||
case ipp32f: return CV_INSTRUMENT_FUN_IPP(ippiMinIndx_32f_C1R, (const Ipp32f*)pSrc, srcStep, size, pMinVal, &pMinIndex->x, &pMinIndex->y);
|
||||
default: return ipp_minMaxIndex_wrap(pSrc, srcStep, size, dataType, pMinVal, NULL, pMinIndex, NULL, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static IppStatus ipp_maxIdx_wrap(const void* pSrc, int srcStep, IppiSize size, IppDataType dataType,
|
||||
float*, float* pMaxVal, IppiPoint*, IppiPoint* pMaxIndex, const Ipp8u*, int)
|
||||
{
|
||||
IppStatus status;
|
||||
|
||||
switch(dataType)
|
||||
{
|
||||
case ipp8u:
|
||||
{
|
||||
Ipp8u val;
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMaxIndx_8u_C1R, (const Ipp8u*)pSrc, srcStep, size, &val, &pMaxIndex->x, &pMaxIndex->y);
|
||||
*pMaxVal = val;
|
||||
return status;
|
||||
}
|
||||
case ipp16u:
|
||||
{
|
||||
Ipp16u val;
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMaxIndx_16u_C1R, (const Ipp16u*)pSrc, srcStep, size, &val, &pMaxIndex->x, &pMaxIndex->y);
|
||||
*pMaxVal = val;
|
||||
return status;
|
||||
}
|
||||
case ipp16s:
|
||||
{
|
||||
Ipp16s val;
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiMaxIndx_16s_C1R, (const Ipp16s*)pSrc, srcStep, size, &val, &pMaxIndex->x, &pMaxIndex->y);
|
||||
*pMaxVal = val;
|
||||
return status;
|
||||
}
|
||||
case ipp32f: return CV_INSTRUMENT_FUN_IPP(ippiMaxIndx_32f_C1R, (const Ipp32f*)pSrc, srcStep, size, pMaxVal, &pMaxIndex->x, &pMaxIndex->y);
|
||||
default: return ipp_minMaxIndex_wrap(pSrc, srcStep, size, dataType, NULL, pMaxVal, NULL, pMaxIndex, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
typedef IppStatus (*IppMinMaxSelector)(const void* pSrc, int srcStep, IppiSize size, IppDataType dataType,
|
||||
float* pMinVal, float* pMaxVal, IppiPoint* pMinIndex, IppiPoint* pMaxIndex, const Ipp8u* pMask, int maskStep);
|
||||
|
||||
static bool ipp_minMaxIdx(Mat &src, double* _minVal, double* _maxVal, int* _minIdx, int* _maxIdx, Mat &mask)
|
||||
{
|
||||
#if IPP_VERSION_X100 >= 700
|
||||
CV_INSTRUMENT_REGION_IPP();
|
||||
|
||||
#if IPP_VERSION_X100 < 201800
|
||||
// cv::minMaxIdx problem with NaN input
|
||||
// Disable 32F processing only
|
||||
if(src.depth() == CV_32F && cv::ipp::getIppTopFeatures() == ippCPUID_SSE42)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#if IPP_VERSION_X100 < 201801
|
||||
// cv::minMaxIdx problem with index positions on AVX
|
||||
if(!mask.empty() && _maxIdx && cv::ipp::getIppTopFeatures() != ippCPUID_SSE42)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
IppStatus status;
|
||||
IppDataType dataType = ippiGetDataType(src.depth());
|
||||
float minVal = 0;
|
||||
float maxVal = 0;
|
||||
IppiPoint minIdx = {-1, -1};
|
||||
IppiPoint maxIdx = {-1, -1};
|
||||
|
||||
float *pMinVal = (_minVal || _minIdx)?&minVal:NULL;
|
||||
float *pMaxVal = (_maxVal || _maxIdx)?&maxVal:NULL;
|
||||
IppiPoint *pMinIdx = (_minIdx)?&minIdx:NULL;
|
||||
IppiPoint *pMaxIdx = (_maxIdx)?&maxIdx:NULL;
|
||||
|
||||
IppMinMaxSelector ippMinMaxFun = ipp_minMaxIndexMask_wrap;
|
||||
if(mask.empty())
|
||||
{
|
||||
if(_maxVal && _maxIdx && !_minVal && !_minIdx)
|
||||
ippMinMaxFun = ipp_maxIdx_wrap;
|
||||
else if(!_maxVal && !_maxIdx && _minVal && _minIdx)
|
||||
ippMinMaxFun = ipp_minIdx_wrap;
|
||||
else if(_maxVal && !_maxIdx && _minVal && !_minIdx)
|
||||
ippMinMaxFun = ipp_minMax_wrap;
|
||||
else if(!_maxVal && !_maxIdx && !_minVal && !_minIdx)
|
||||
return false;
|
||||
else
|
||||
ippMinMaxFun = ipp_minMaxIndex_wrap;
|
||||
}
|
||||
|
||||
if(src.dims <= 2)
|
||||
{
|
||||
IppiSize size = ippiSize(src.size());
|
||||
#if defined(_WIN32) && !defined(_WIN64) && IPP_VERSION_X100 == 201900 && IPP_DISABLE_MINMAXIDX_MANY_ROWS
|
||||
if (size.height > 65536)
|
||||
return false; // test: Core_MinMaxIdx.rows_overflow
|
||||
#endif
|
||||
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)
|
||||
return false;
|
||||
if(_minVal)
|
||||
*_minVal = minVal;
|
||||
if(_maxVal)
|
||||
*_maxVal = maxVal;
|
||||
if(_minIdx)
|
||||
{
|
||||
#if IPP_VERSION_X100 < 201801
|
||||
// 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)
|
||||
#else
|
||||
if(status == ippStsNoOperation)
|
||||
#endif
|
||||
{
|
||||
_minIdx[0] = -1;
|
||||
_minIdx[1] = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_minIdx[0] = minIdx.y;
|
||||
_minIdx[1] = minIdx.x;
|
||||
}
|
||||
}
|
||||
if(_maxIdx)
|
||||
{
|
||||
#if IPP_VERSION_X100 < 201801
|
||||
// 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)
|
||||
#else
|
||||
if(status == ippStsNoOperation)
|
||||
#endif
|
||||
{
|
||||
_maxIdx[0] = -1;
|
||||
_maxIdx[1] = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_maxIdx[0] = maxIdx.y;
|
||||
_maxIdx[1] = maxIdx.x;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const Mat *arrays[] = {&src, mask.empty()?NULL:&mask, NULL};
|
||||
uchar *ptrs[3] = {NULL};
|
||||
NAryMatIterator it(arrays, ptrs);
|
||||
IppiSize size = ippiSize(it.size*src.channels(), 1);
|
||||
int srcStep = (int)(size.width*src.elemSize1());
|
||||
int maskStep = size.width;
|
||||
size_t idxPos = 1;
|
||||
size_t minIdxAll = 0;
|
||||
size_t maxIdxAll = 0;
|
||||
float minValAll = IPP_MAXABS_32F;
|
||||
float maxValAll = -IPP_MAXABS_32F;
|
||||
|
||||
for(size_t i = 0; i < it.nplanes; i++, ++it, idxPos += size.width)
|
||||
{
|
||||
status = ippMinMaxFun(ptrs[0], srcStep, size, dataType, pMinVal, pMaxVal, pMinIdx, pMaxIdx, ptrs[1], maskStep);
|
||||
if(status < 0)
|
||||
return false;
|
||||
#if IPP_VERSION_X100 > 201701
|
||||
// Zero-mask check, function should return ippStsNoOperation warning
|
||||
if(status == ippStsNoOperation)
|
||||
continue;
|
||||
#else
|
||||
// Crude zero-mask check, waiting for fix in IPP function
|
||||
if(ptrs[1])
|
||||
{
|
||||
Mat localMask(Size(size.width, 1), CV_8U, ptrs[1], maskStep);
|
||||
if(!cv::countNonZero(localMask))
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(_minVal && minVal < minValAll)
|
||||
{
|
||||
minValAll = minVal;
|
||||
minIdxAll = idxPos+minIdx.x;
|
||||
}
|
||||
if(_maxVal && maxVal > maxValAll)
|
||||
{
|
||||
maxValAll = maxVal;
|
||||
maxIdxAll = idxPos+maxIdx.x;
|
||||
}
|
||||
}
|
||||
if(!src.empty() && mask.empty())
|
||||
{
|
||||
if(minIdxAll == 0)
|
||||
minIdxAll = 1;
|
||||
if(maxValAll == 0)
|
||||
maxValAll = 1;
|
||||
}
|
||||
|
||||
if(_minVal)
|
||||
*_minVal = minValAll;
|
||||
if(_maxVal)
|
||||
*_maxVal = maxValAll;
|
||||
if(_minIdx)
|
||||
ofs2idx(src, minIdxAll, _minIdx);
|
||||
if(_maxIdx)
|
||||
ofs2idx(src, maxIdxAll, _maxIdx);
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
CV_UNUSED(src); CV_UNUSED(minVal); CV_UNUSED(maxVal); CV_UNUSED(minIdx); CV_UNUSED(maxIdx); CV_UNUSED(mask);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void cv::minMaxIdx(InputArray _src, double* minVal,
|
||||
@@ -1467,8 +1157,6 @@ void cv::minMaxIdx(InputArray _src, double* minVal,
|
||||
}
|
||||
}
|
||||
|
||||
CV_IPP_RUN_FAST(ipp_minMaxIdx(src, minVal, maxVal, minIdx, maxIdx, mask))
|
||||
|
||||
MinMaxIdxFunc func = getMinmaxTab(depth);
|
||||
CV_Assert( func != 0 );
|
||||
|
||||
|
||||
Reference in New Issue
Block a user