mirror of
https://github.com/opencv/opencv.git
synced 2025-06-10 11:03:03 +08:00
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
commit
3d14dd4e39
5
3rdparty/carotene/CMakeLists.txt
vendored
5
3rdparty/carotene/CMakeLists.txt
vendored
@ -20,8 +20,11 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
|||||||
# - matchTemplate about 5-10%
|
# - matchTemplate about 5-10%
|
||||||
# - goodFeaturesToTrack 10-20%
|
# - goodFeaturesToTrack 10-20%
|
||||||
# - cornerHarris 30% for some cases
|
# - cornerHarris 30% for some cases
|
||||||
|
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "10.0.0")
|
||||||
set_source_files_properties(${carotene_sources} COMPILE_FLAGS "--param ipcp-unit-growth=100000 --param inline-unit-growth=100000 --param large-stack-frame-growth=5000")
|
set_source_files_properties(${carotene_sources} COMPILE_FLAGS "--param ipcp-unit-growth=100000 --param inline-unit-growth=100000 --param large-stack-frame-growth=5000")
|
||||||
|
else()
|
||||||
|
set_source_files_properties(${carotene_sources} COMPILE_FLAGS "--param ipa-cp-unit-growth=100000 --param inline-unit-growth=100000 --param large-stack-frame-growth=5000")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(carotene_objs OBJECT
|
add_library(carotene_objs OBJECT
|
||||||
|
4
3rdparty/carotene/hal/CMakeLists.txt
vendored
4
3rdparty/carotene/hal/CMakeLists.txt
vendored
@ -90,7 +90,11 @@ set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS ${carotene_defs})
|
|||||||
# matchTemplate about 5-10%
|
# matchTemplate about 5-10%
|
||||||
# goodFeaturesToTrack 10-20%
|
# goodFeaturesToTrack 10-20%
|
||||||
# cornerHarris 30% for some cases
|
# cornerHarris 30% for some cases
|
||||||
|
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "10.0.0")
|
||||||
set_source_files_properties(impl.cpp $<TARGET_OBJECTS:carotene_objs> COMPILE_FLAGS "--param ipcp-unit-growth=100000 --param inline-unit-growth=100000 --param large-stack-frame-growth=5000")
|
set_source_files_properties(impl.cpp $<TARGET_OBJECTS:carotene_objs> COMPILE_FLAGS "--param ipcp-unit-growth=100000 --param inline-unit-growth=100000 --param large-stack-frame-growth=5000")
|
||||||
|
else()
|
||||||
|
set_source_files_properties(impl.cpp $<TARGET_OBJECTS:carotene_objs> COMPILE_FLAGS "--param ipa-cp-unit-growth=100000 --param inline-unit-growth=100000 --param large-stack-frame-growth=5000")
|
||||||
|
endif()
|
||||||
# set_source_files_properties(impl.cpp $<TARGET_OBJECTS:carotene_objs> COMPILE_FLAGS "--param ipcp-unit-growth=100000 --param inline-unit-growth=100000 --param large-stack-frame-growth=5000")
|
# set_source_files_properties(impl.cpp $<TARGET_OBJECTS:carotene_objs> COMPILE_FLAGS "--param ipcp-unit-growth=100000 --param inline-unit-growth=100000 --param large-stack-frame-growth=5000")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -318,6 +318,21 @@ if(PPC64LE)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Apply "-Wl,--as-needed" linker flags: https://github.com/opencv/opencv/issues/7001
|
||||||
|
if(NOT OPENCV_SKIP_LINK_AS_NEEDED)
|
||||||
|
if(UNIX AND (NOT APPLE OR NOT CMAKE_VERSION VERSION_LESS "3.2"))
|
||||||
|
set(_option "-Wl,--as-needed")
|
||||||
|
set(_saved_CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${_option}") # requires CMake 3.2+ and CMP0056
|
||||||
|
ocv_check_compiler_flag(CXX "" HAVE_LINK_AS_NEEDED)
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${_saved_CMAKE_EXE_LINKER_FLAGS}")
|
||||||
|
if(HAVE_LINK_AS_NEEDED)
|
||||||
|
set(OPENCV_EXTRA_EXE_LINKER_FLAGS "${OPENCV_EXTRA_EXE_LINKER_FLAGS} ${_option}")
|
||||||
|
set(OPENCV_EXTRA_SHARED_LINKER_FLAGS "${OPENCV_EXTRA_SHARED_LINKER_FLAGS} ${_option}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
# combine all "extra" options
|
# combine all "extra" options
|
||||||
if(NOT OPENCV_SKIP_EXTRA_COMPILER_FLAGS)
|
if(NOT OPENCV_SKIP_EXTRA_COMPILER_FLAGS)
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPENCV_EXTRA_FLAGS} ${OPENCV_EXTRA_C_FLAGS}")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPENCV_EXTRA_FLAGS} ${OPENCV_EXTRA_C_FLAGS}")
|
||||||
|
@ -20,6 +20,8 @@ if(WIN32)
|
|||||||
elseif(MSVC)
|
elseif(MSVC)
|
||||||
SET(OPENEXR_LIBSEARCH_SUFFIXES Win32/Release Win32 Win32/Debug)
|
SET(OPENEXR_LIBSEARCH_SUFFIXES Win32/Release Win32 Win32/Debug)
|
||||||
endif()
|
endif()
|
||||||
|
elseif(UNIX)
|
||||||
|
SET(OPENEXR_LIBSEARCH_SUFFIXES ${CMAKE_LIBRARY_ARCHITECTURE})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
SET(SEARCH_PATHS
|
SET(SEARCH_PATHS
|
||||||
@ -39,6 +41,25 @@ MACRO(FIND_OPENEXR_LIBRARY LIBRARY_NAME LIBRARY_SUFFIX)
|
|||||||
PATHS "${SEARCH_PATH}/lib" "${SEARCH_PATH}/lib/static")
|
PATHS "${SEARCH_PATH}/lib" "${SEARCH_PATH}/lib/static")
|
||||||
ENDMACRO()
|
ENDMACRO()
|
||||||
|
|
||||||
|
MACRO(ocv_find_openexr LIBRARY_SUFFIX)
|
||||||
|
IF(NOT OPENEXR_FOUND)
|
||||||
|
FIND_OPENEXR_LIBRARY("Half" "${LIBRARY_SUFFIX}")
|
||||||
|
FIND_OPENEXR_LIBRARY("Iex" "${LIBRARY_SUFFIX}")
|
||||||
|
FIND_OPENEXR_LIBRARY("Imath" "${LIBRARY_SUFFIX}")
|
||||||
|
FIND_OPENEXR_LIBRARY("IlmImf" "${LIBRARY_SUFFIX}")
|
||||||
|
FIND_OPENEXR_LIBRARY("IlmThread" "${LIBRARY_SUFFIX}")
|
||||||
|
IF (OPENEXR_INCLUDE_PATH AND OPENEXR_IMATH_LIBRARY AND OPENEXR_ILMIMF_LIBRARY AND OPENEXR_IEX_LIBRARY AND OPENEXR_HALF_LIBRARY AND OPENEXR_ILMTHREAD_LIBRARY)
|
||||||
|
SET(OPENEXR_FOUND TRUE)
|
||||||
|
ELSE()
|
||||||
|
UNSET(OPENEXR_IMATH_LIBRARY)
|
||||||
|
UNSET(OPENEXR_ILMIMF_LIBRARY)
|
||||||
|
UNSET(OPENEXR_IEX_LIBRARY)
|
||||||
|
UNSET(OPENEXR_ILMTHREAD_LIBRARY)
|
||||||
|
UNSET(OPENEXR_HALF_LIBRARY)
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
ENDMACRO()
|
||||||
|
|
||||||
FOREACH(SEARCH_PATH ${SEARCH_PATHS})
|
FOREACH(SEARCH_PATH ${SEARCH_PATHS})
|
||||||
FIND_PATH(OPENEXR_INCLUDE_PATH ImfRgbaFile.h
|
FIND_PATH(OPENEXR_INCLUDE_PATH ImfRgbaFile.h
|
||||||
PATH_SUFFIXES OpenEXR
|
PATH_SUFFIXES OpenEXR
|
||||||
@ -64,32 +85,14 @@ FOREACH(SEARCH_PATH ${SEARCH_PATHS})
|
|||||||
set(OPENEXR_VERSION "${OPENEXR_VERSION_MAJOR}_${OPENEXR_VERSION_MINOR}")
|
set(OPENEXR_VERSION "${OPENEXR_VERSION_MAJOR}_${OPENEXR_VERSION_MINOR}")
|
||||||
ENDIF ()
|
ENDIF ()
|
||||||
|
|
||||||
SET(LIBRARY_SUFFIXES
|
ocv_find_openexr("-${OPENEXR_VERSION}")
|
||||||
"-${OPENEXR_VERSION}"
|
ocv_find_openexr("-${OPENEXR_VERSION}_s")
|
||||||
"-${OPENEXR_VERSION}_s"
|
ocv_find_openexr("-${OPENEXR_VERSION}_d")
|
||||||
"-${OPENEXR_VERSION}_d"
|
ocv_find_openexr("-${OPEXEXR_VERSION}_s_d")
|
||||||
"-${OPEXEXR_VERSION}_s_d"
|
ocv_find_openexr("")
|
||||||
""
|
ocv_find_openexr("_s")
|
||||||
"_s"
|
ocv_find_openexr("_d")
|
||||||
"_d"
|
ocv_find_openexr("_s_d")
|
||||||
"_s_d")
|
|
||||||
|
|
||||||
FOREACH(LIBRARY_SUFFIX ${LIBRARY_SUFFIXES})
|
|
||||||
FIND_OPENEXR_LIBRARY("Half" ${LIBRARY_SUFFIX})
|
|
||||||
FIND_OPENEXR_LIBRARY("Iex" ${LIBRARY_SUFFIX})
|
|
||||||
FIND_OPENEXR_LIBRARY("Imath" ${LIBRARY_SUFFIX})
|
|
||||||
FIND_OPENEXR_LIBRARY("IlmImf" ${LIBRARY_SUFFIX})
|
|
||||||
FIND_OPENEXR_LIBRARY("IlmThread" ${LIBRARY_SUFFIX})
|
|
||||||
IF (OPENEXR_INCLUDE_PATH AND OPENEXR_IMATH_LIBRARY AND OPENEXR_ILMIMF_LIBRARY AND OPENEXR_IEX_LIBRARY AND OPENEXR_HALF_LIBRARY)
|
|
||||||
SET(OPENEXR_FOUND TRUE)
|
|
||||||
BREAK()
|
|
||||||
ENDIF()
|
|
||||||
UNSET(OPENEXR_IMATH_LIBRARY)
|
|
||||||
UNSET(OPENEXR_ILMIMF_LIBRARY)
|
|
||||||
UNSET(OPENEXR_IEX_LIBRARY)
|
|
||||||
UNSET(OPENEXR_ILMTHREAD_LIBRARY)
|
|
||||||
UNSET(OPENEXR_HALF_LIBRARY)
|
|
||||||
ENDFOREACH()
|
|
||||||
|
|
||||||
IF (OPENEXR_FOUND)
|
IF (OPENEXR_FOUND)
|
||||||
BREAK()
|
BREAK()
|
||||||
|
@ -540,7 +540,7 @@ macro(ocv_check_flag_support lang flag varname base_options)
|
|||||||
|
|
||||||
string(TOUPPER "${flag}" ${varname})
|
string(TOUPPER "${flag}" ${varname})
|
||||||
string(REGEX REPLACE "^(/|-)" "HAVE_${_lang}_" ${varname} "${${varname}}")
|
string(REGEX REPLACE "^(/|-)" "HAVE_${_lang}_" ${varname} "${${varname}}")
|
||||||
string(REGEX REPLACE " -|-|=| |\\." "_" ${varname} "${${varname}}")
|
string(REGEX REPLACE " -|-|=| |\\.|," "_" ${varname} "${${varname}}")
|
||||||
|
|
||||||
ocv_check_compiler_flag("${_lang}" "${base_options} ${flag}" ${${varname}} ${ARGN})
|
ocv_check_compiler_flag("${_lang}" "${base_options} ${flag}" ${${varname}} ${ARGN})
|
||||||
endmacro()
|
endmacro()
|
||||||
|
@ -213,7 +213,7 @@ Regular integers:
|
|||||||
|min, max | x | x | x | x | x | x |
|
|min, max | x | x | x | x | x | x |
|
||||||
|absdiff | x | x | x | x | x | x |
|
|absdiff | x | x | x | x | x | x |
|
||||||
|absdiffs | | x | | x | | |
|
|absdiffs | | x | | x | | |
|
||||||
|reduce | | | | | x | x |
|
|reduce | x | x | x | x | x | x |
|
||||||
|mask | x | x | x | x | x | x |
|
|mask | x | x | x | x | x | x |
|
||||||
|pack | x | x | x | x | x | x |
|
|pack | x | x | x | x | x | x |
|
||||||
|pack_u | x | | x | | | |
|
|pack_u | x | | x | | | |
|
||||||
@ -670,7 +670,7 @@ Scheme:
|
|||||||
@code
|
@code
|
||||||
{A1 A2 A3 ...} => min(A1,A2,A3,...)
|
{A1 A2 A3 ...} => min(A1,A2,A3,...)
|
||||||
@endcode
|
@endcode
|
||||||
For 32-bit integer and 32-bit floating point types. */
|
For all types except 64-bit integer and 64-bit floating point types. */
|
||||||
OPENCV_HAL_IMPL_REDUCE_MINMAX_FUNC(v_reduce_min, std::min)
|
OPENCV_HAL_IMPL_REDUCE_MINMAX_FUNC(v_reduce_min, std::min)
|
||||||
|
|
||||||
/** @brief Find one max value
|
/** @brief Find one max value
|
||||||
@ -679,7 +679,7 @@ Scheme:
|
|||||||
@code
|
@code
|
||||||
{A1 A2 A3 ...} => max(A1,A2,A3,...)
|
{A1 A2 A3 ...} => max(A1,A2,A3,...)
|
||||||
@endcode
|
@endcode
|
||||||
For 32-bit integer and 32-bit floating point types. */
|
For all types except 64-bit integer and 64-bit floating point types. */
|
||||||
OPENCV_HAL_IMPL_REDUCE_MINMAX_FUNC(v_reduce_max, std::max)
|
OPENCV_HAL_IMPL_REDUCE_MINMAX_FUNC(v_reduce_max, std::max)
|
||||||
|
|
||||||
static const unsigned char popCountTable[] =
|
static const unsigned char popCountTable[] =
|
||||||
@ -1219,7 +1219,7 @@ Scheme:
|
|||||||
@code
|
@code
|
||||||
{A1 A2 A3 ...} => sum{A1,A2,A3,...}
|
{A1 A2 A3 ...} => sum{A1,A2,A3,...}
|
||||||
@endcode
|
@endcode
|
||||||
For 32-bit integer and 32-bit floating point types.*/
|
*/
|
||||||
template<typename _Tp, int n> inline typename V_TypeTraits<_Tp>::sum_type v_reduce_sum(const v_reg<_Tp, n>& a)
|
template<typename _Tp, int n> inline typename V_TypeTraits<_Tp>::sum_type v_reduce_sum(const v_reg<_Tp, n>& a)
|
||||||
{
|
{
|
||||||
typename V_TypeTraits<_Tp>::sum_type c = a.s[0];
|
typename V_TypeTraits<_Tp>::sum_type c = a.s[0];
|
||||||
|
@ -1000,6 +1000,22 @@ OPENCV_HAL_IMPL_MSA_REDUCE_OP_4(v_int32x4, int, min, std::min)
|
|||||||
OPENCV_HAL_IMPL_MSA_REDUCE_OP_4(v_float32x4, float, max, std::max)
|
OPENCV_HAL_IMPL_MSA_REDUCE_OP_4(v_float32x4, float, max, std::max)
|
||||||
OPENCV_HAL_IMPL_MSA_REDUCE_OP_4(v_float32x4, float, min, std::min)
|
OPENCV_HAL_IMPL_MSA_REDUCE_OP_4(v_float32x4, float, min, std::min)
|
||||||
|
|
||||||
|
|
||||||
|
#define OPENCV_HAL_IMPL_MSA_REDUCE_OP_16(_Tpvec, scalartype, _Tpvec2, func) \
|
||||||
|
inline scalartype v_reduce_##func(const _Tpvec& a) \
|
||||||
|
{ \
|
||||||
|
_Tpvec2 a1, a2; \
|
||||||
|
v_expand(a, a1, a2); \
|
||||||
|
return (scalartype)v_reduce_##func(v_##func(a1, a2)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
OPENCV_HAL_IMPL_MSA_REDUCE_OP_16(v_uint8x16, uchar, v_uint16x8, min)
|
||||||
|
OPENCV_HAL_IMPL_MSA_REDUCE_OP_16(v_uint8x16, uchar, v_uint16x8, max)
|
||||||
|
OPENCV_HAL_IMPL_MSA_REDUCE_OP_16(v_int8x16, char, v_int16x8, min)
|
||||||
|
OPENCV_HAL_IMPL_MSA_REDUCE_OP_16(v_int8x16, char, v_int16x8, max)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define OPENCV_HAL_IMPL_MSA_REDUCE_SUM(_Tpvec, scalartype, suffix) \
|
#define OPENCV_HAL_IMPL_MSA_REDUCE_SUM(_Tpvec, scalartype, suffix) \
|
||||||
inline scalartype v_reduce_sum(const _Tpvec& a) \
|
inline scalartype v_reduce_sum(const _Tpvec& a) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -1241,6 +1241,20 @@ inline int v_reduce_sum(const v_int16x8& a)
|
|||||||
return vget_lane_s32(vpadd_s32(t1, t1), 0);
|
return vget_lane_s32(vpadd_s32(t1, t1), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_16(_Tpvec, _Tpnvec, scalartype, func, vectorfunc, suffix) \
|
||||||
|
inline scalartype v_reduce_##func(const _Tpvec& a) \
|
||||||
|
{ \
|
||||||
|
_Tpnvec##_t a0 = vp##vectorfunc##_##suffix(vget_low_##suffix(a.val), vget_high_##suffix(a.val)); \
|
||||||
|
a0 = vp##vectorfunc##_##suffix(a0, a0); \
|
||||||
|
a0 = vp##vectorfunc##_##suffix(a0, a0); \
|
||||||
|
return (scalartype)vget_lane_##suffix(vp##vectorfunc##_##suffix(a0, a0),0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
OPENCV_HAL_IMPL_NEON_REDUCE_OP_16(v_uint8x16, uint8x8, uchar, max, max, u8)
|
||||||
|
OPENCV_HAL_IMPL_NEON_REDUCE_OP_16(v_uint8x16, uint8x8, uchar, min, min, u8)
|
||||||
|
OPENCV_HAL_IMPL_NEON_REDUCE_OP_16(v_int8x16, int8x8, schar, max, max, s8)
|
||||||
|
OPENCV_HAL_IMPL_NEON_REDUCE_OP_16(v_int8x16, int8x8, schar, min, min, s8)
|
||||||
|
|
||||||
#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(_Tpvec, _Tpnvec, scalartype, func, vectorfunc, suffix) \
|
#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(_Tpvec, _Tpnvec, scalartype, func, vectorfunc, suffix) \
|
||||||
inline scalartype v_reduce_##func(const _Tpvec& a) \
|
inline scalartype v_reduce_##func(const _Tpvec& a) \
|
||||||
{ \
|
{ \
|
||||||
@ -1249,10 +1263,10 @@ inline scalartype v_reduce_##func(const _Tpvec& a) \
|
|||||||
return (scalartype)vget_lane_##suffix(vp##vectorfunc##_##suffix(a0, a0),0); \
|
return (scalartype)vget_lane_##suffix(vp##vectorfunc##_##suffix(a0, a0),0); \
|
||||||
}
|
}
|
||||||
|
|
||||||
OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(v_uint16x8, uint16x4, unsigned int, max, max, u16)
|
OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(v_uint16x8, uint16x4, ushort, max, max, u16)
|
||||||
OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(v_uint16x8, uint16x4, unsigned int, min, min, u16)
|
OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(v_uint16x8, uint16x4, ushort, min, min, u16)
|
||||||
OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(v_int16x8, int16x4, int, max, max, s16)
|
OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(v_int16x8, int16x4, short, max, max, s16)
|
||||||
OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(v_int16x8, int16x4, int, min, min, s16)
|
OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(v_int16x8, int16x4, short, min, min, s16)
|
||||||
|
|
||||||
#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(_Tpvec, _Tpnvec, scalartype, func, vectorfunc, suffix) \
|
#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(_Tpvec, _Tpnvec, scalartype, func, vectorfunc, suffix) \
|
||||||
inline scalartype v_reduce_##func(const _Tpvec& a) \
|
inline scalartype v_reduce_##func(const _Tpvec& a) \
|
||||||
@ -2129,10 +2143,12 @@ inline v_float32x4 v_lut(const float* tab, const int* idx)
|
|||||||
}
|
}
|
||||||
inline v_float32x4 v_lut_pairs(const float* tab, const int* idx)
|
inline v_float32x4 v_lut_pairs(const float* tab, const int* idx)
|
||||||
{
|
{
|
||||||
|
typedef uint64 CV_DECL_ALIGNED(1) unaligned_uint64;
|
||||||
|
|
||||||
uint64 CV_DECL_ALIGNED(32) elems[2] =
|
uint64 CV_DECL_ALIGNED(32) elems[2] =
|
||||||
{
|
{
|
||||||
*(uint64*)(tab + idx[0]),
|
*(unaligned_uint64*)(tab + idx[0]),
|
||||||
*(uint64*)(tab + idx[1])
|
*(unaligned_uint64*)(tab + idx[1])
|
||||||
};
|
};
|
||||||
return v_float32x4(vreinterpretq_f32_u64(vld1q_u64(elems)));
|
return v_float32x4(vreinterpretq_f32_u64(vld1q_u64(elems)));
|
||||||
}
|
}
|
||||||
|
@ -71,33 +71,759 @@ minMaxIdx_( const T* src, const uchar* mask, WT* _minVal, WT* _maxVal,
|
|||||||
*_maxVal = maxVal;
|
*_maxVal = maxVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CV_SIMD128
|
||||||
|
template<typename T, typename WT> CV_ALWAYS_INLINE void
|
||||||
|
minMaxIdx_init( const T* src, const uchar* mask, WT* minval, WT* maxval,
|
||||||
|
size_t* minidx, size_t* maxidx, WT &minVal, WT &maxVal,
|
||||||
|
size_t &minIdx, size_t &maxIdx, const WT minInit, const WT maxInit,
|
||||||
|
const int nlanes, int len, size_t startidx, int &j, int &len0 )
|
||||||
|
{
|
||||||
|
len0 = len & -nlanes;
|
||||||
|
j = 0;
|
||||||
|
|
||||||
|
minVal = *minval, maxVal = *maxval;
|
||||||
|
minIdx = *minidx, maxIdx = *maxidx;
|
||||||
|
|
||||||
|
// To handle start values out of range
|
||||||
|
if ( minVal < minInit || maxVal < minInit || minVal > maxInit || maxVal > maxInit )
|
||||||
|
{
|
||||||
|
uchar done = 0x00;
|
||||||
|
|
||||||
|
for ( ; (j < len) && (done != 0x03); j++ )
|
||||||
|
{
|
||||||
|
if ( !mask || mask[j] ) {
|
||||||
|
T val = src[j];
|
||||||
|
if ( val < minVal )
|
||||||
|
{
|
||||||
|
minVal = val;
|
||||||
|
minIdx = startidx + j;
|
||||||
|
done |= 0x01;
|
||||||
|
}
|
||||||
|
if ( val > maxVal )
|
||||||
|
{
|
||||||
|
maxVal = val;
|
||||||
|
maxIdx = startidx + j;
|
||||||
|
done |= 0x02;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
len0 = j + ((len - j) & -nlanes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CV_SIMD128_64F
|
||||||
|
CV_ALWAYS_INLINE double v_reduce_min(const v_float64x2& a)
|
||||||
|
{
|
||||||
|
double CV_DECL_ALIGNED(32) idx[2];
|
||||||
|
v_store_aligned(idx, a);
|
||||||
|
return std::min(idx[0], idx[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
CV_ALWAYS_INLINE double v_reduce_max(const v_float64x2& a)
|
||||||
|
{
|
||||||
|
double CV_DECL_ALIGNED(32) idx[2];
|
||||||
|
v_store_aligned(idx, a);
|
||||||
|
return std::max(idx[0], idx[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
CV_ALWAYS_INLINE uint64_t v_reduce_min(const v_uint64x2& a)
|
||||||
|
{
|
||||||
|
uint64_t CV_DECL_ALIGNED(32) idx[2];
|
||||||
|
v_store_aligned(idx, a);
|
||||||
|
return std::min(idx[0], idx[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
CV_ALWAYS_INLINE v_uint64x2 v_select(const v_uint64x2& mask, const v_uint64x2& a, const v_uint64x2& b)
|
||||||
|
{
|
||||||
|
return b ^ ((a ^ b) & mask);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MINMAXIDX_REDUCE(suffix, suffix2, maxLimit, IR) \
|
||||||
|
template<typename T, typename VT, typename IT> CV_ALWAYS_INLINE void \
|
||||||
|
minMaxIdx_reduce_##suffix( VT &valMin, VT &valMax, IT &idxMin, IT &idxMax, IT &none, \
|
||||||
|
T &minVal, T &maxVal, size_t &minIdx, size_t &maxIdx, \
|
||||||
|
size_t delta ) \
|
||||||
|
{ \
|
||||||
|
if ( v_check_any(idxMin != none) ) \
|
||||||
|
{ \
|
||||||
|
minVal = v_reduce_min(valMin); \
|
||||||
|
minIdx = (size_t)v_reduce_min(v_select(v_reinterpret_as_##suffix2(v_setall_##suffix((IR)minVal) == valMin), \
|
||||||
|
idxMin, v_setall_##suffix2(maxLimit))) + delta; \
|
||||||
|
} \
|
||||||
|
if ( v_check_any(idxMax != none) ) \
|
||||||
|
{ \
|
||||||
|
maxVal = v_reduce_max(valMax); \
|
||||||
|
maxIdx = (size_t)v_reduce_min(v_select(v_reinterpret_as_##suffix2(v_setall_##suffix((IR)maxVal) == valMax), \
|
||||||
|
idxMax, v_setall_##suffix2(maxLimit))) + delta; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
MINMAXIDX_REDUCE(u8, u8, UCHAR_MAX, uchar)
|
||||||
|
MINMAXIDX_REDUCE(s8, u8, UCHAR_MAX, uchar)
|
||||||
|
MINMAXIDX_REDUCE(u16, u16, USHRT_MAX, ushort)
|
||||||
|
MINMAXIDX_REDUCE(s16, u16, USHRT_MAX, ushort)
|
||||||
|
MINMAXIDX_REDUCE(s32, u32, UINT_MAX, uint)
|
||||||
|
MINMAXIDX_REDUCE(f32, u32, (1 << 23) - 1, float)
|
||||||
|
#if CV_SIMD128_64F
|
||||||
|
MINMAXIDX_REDUCE(f64, u64, UINT_MAX, double)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<typename T, typename WT> CV_ALWAYS_INLINE void
|
||||||
|
minMaxIdx_finish( const T* src, const uchar* mask, WT* minval, WT* maxval,
|
||||||
|
size_t* minidx, size_t* maxidx, WT minVal, WT maxVal,
|
||||||
|
size_t minIdx, size_t maxIdx, int len, size_t startidx,
|
||||||
|
int j )
|
||||||
|
{
|
||||||
|
for ( ; j < len ; j++ )
|
||||||
|
{
|
||||||
|
if ( !mask || mask[j] )
|
||||||
|
{
|
||||||
|
T val = src[j];
|
||||||
|
if ( val < minVal )
|
||||||
|
{
|
||||||
|
minVal = val;
|
||||||
|
minIdx = startidx + j;
|
||||||
|
}
|
||||||
|
if ( val > maxVal )
|
||||||
|
{
|
||||||
|
maxVal = val;
|
||||||
|
maxIdx = startidx + j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*minidx = minIdx;
|
||||||
|
*maxidx = maxIdx;
|
||||||
|
*minval = minVal;
|
||||||
|
*maxval = maxVal;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void minMaxIdx_8u(const uchar* src, const uchar* mask, int* minval, int* maxval,
|
static void minMaxIdx_8u(const uchar* src, const uchar* mask, int* minval, int* maxval,
|
||||||
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
||||||
{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
|
{
|
||||||
|
#if CV_SIMD128
|
||||||
|
if ( len >= v_uint8x16::nlanes )
|
||||||
|
{
|
||||||
|
int j, len0;
|
||||||
|
int minVal, maxVal;
|
||||||
|
size_t minIdx, maxIdx;
|
||||||
|
|
||||||
|
minMaxIdx_init( src, mask, minval, maxval, minidx, maxidx, minVal, maxVal, minIdx, maxIdx,
|
||||||
|
(int)0, (int)UCHAR_MAX, v_uint8x16::nlanes, len, startidx, j, len0 );
|
||||||
|
|
||||||
|
if ( j <= len0 - v_uint8x16::nlanes )
|
||||||
|
{
|
||||||
|
v_uint8x16 inc = v_setall_u8(v_uint8x16::nlanes);
|
||||||
|
v_uint8x16 none = v_reinterpret_as_u8(v_setall_s8(-1));
|
||||||
|
v_uint8x16 idxStart(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
v_uint8x16 valMin = v_setall_u8((uchar)minVal), valMax = v_setall_u8((uchar)maxVal);
|
||||||
|
v_uint8x16 idx = idxStart, idxMin = none, idxMax = none;
|
||||||
|
|
||||||
|
int k = j;
|
||||||
|
size_t delta = startidx + j;
|
||||||
|
|
||||||
|
if ( !mask )
|
||||||
|
{
|
||||||
|
for( ; k < std::min(len0, j + 15 * v_uint8x16::nlanes); k += v_uint8x16::nlanes )
|
||||||
|
{
|
||||||
|
v_uint8x16 data = v_load(src + k);
|
||||||
|
v_uint8x16 cmpMin = (data < valMin);
|
||||||
|
v_uint8x16 cmpMax = (data > valMax);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_min(data, valMin);
|
||||||
|
valMax = v_max(data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( ; k < std::min(len0, j + 15 * v_uint8x16::nlanes); k += v_uint8x16::nlanes )
|
||||||
|
{
|
||||||
|
v_uint8x16 data = v_load(src + k);
|
||||||
|
v_uint8x16 maskVal = v_load(mask + k) != v_setzero_u8();
|
||||||
|
v_uint8x16 cmpMin = (data < valMin) & maskVal;
|
||||||
|
v_uint8x16 cmpMax = (data > valMax) & maskVal;
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_select(cmpMin, data, valMin);
|
||||||
|
valMax = v_select(cmpMax, data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
j = k;
|
||||||
|
|
||||||
|
minMaxIdx_reduce_u8( valMin, valMax, idxMin, idxMax, none, minVal, maxVal,
|
||||||
|
minIdx, maxIdx, delta );
|
||||||
|
}
|
||||||
|
while ( j < len0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
minMaxIdx_finish( src, mask, minval, maxval, minidx, maxidx, minVal, maxVal,
|
||||||
|
minIdx, maxIdx, len, startidx, j );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void minMaxIdx_8s(const schar* src, const uchar* mask, int* minval, int* maxval,
|
static void minMaxIdx_8s(const schar* src, const uchar* mask, int* minval, int* maxval,
|
||||||
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
||||||
{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
|
{
|
||||||
|
#if CV_SIMD128
|
||||||
|
if ( len >= v_int8x16::nlanes )
|
||||||
|
{
|
||||||
|
int j, len0;
|
||||||
|
int minVal, maxVal;
|
||||||
|
size_t minIdx, maxIdx;
|
||||||
|
|
||||||
|
minMaxIdx_init( src, mask, minval, maxval, minidx, maxidx, minVal, maxVal, minIdx, maxIdx,
|
||||||
|
(int)SCHAR_MIN, (int)SCHAR_MAX, v_int8x16::nlanes, len, startidx, j, len0 );
|
||||||
|
|
||||||
|
if ( j <= len0 - v_int8x16::nlanes )
|
||||||
|
{
|
||||||
|
v_uint8x16 inc = v_setall_u8(v_int8x16::nlanes);
|
||||||
|
v_uint8x16 none = v_reinterpret_as_u8(v_setall_s8(-1));
|
||||||
|
v_uint8x16 idxStart(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
v_int8x16 valMin = v_setall_s8((schar)minVal), valMax = v_setall_s8((schar)maxVal);
|
||||||
|
v_uint8x16 idx = idxStart, idxMin = none, idxMax = none;
|
||||||
|
|
||||||
|
int k = j;
|
||||||
|
size_t delta = startidx + j;
|
||||||
|
|
||||||
|
if ( !mask )
|
||||||
|
{
|
||||||
|
for( ; k < std::min(len0, j + 15 * v_int8x16::nlanes); k += v_int8x16::nlanes )
|
||||||
|
{
|
||||||
|
v_int8x16 data = v_load(src + k);
|
||||||
|
v_uint8x16 cmpMin = v_reinterpret_as_u8(data < valMin);
|
||||||
|
v_uint8x16 cmpMax = v_reinterpret_as_u8(data > valMax);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_min(data, valMin);
|
||||||
|
valMax = v_max(data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( ; k < std::min(len0, j + 15 * v_int8x16::nlanes); k += v_int8x16::nlanes )
|
||||||
|
{
|
||||||
|
v_int8x16 data = v_load(src + k);
|
||||||
|
v_uint8x16 maskVal = v_load(mask + k) != v_setzero_u8();
|
||||||
|
v_uint8x16 cmpMin = v_reinterpret_as_u8(data < valMin) & maskVal;
|
||||||
|
v_uint8x16 cmpMax = v_reinterpret_as_u8(data > valMax) & maskVal;
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_select(v_reinterpret_as_s8(cmpMin), data, valMin);
|
||||||
|
valMax = v_select(v_reinterpret_as_s8(cmpMax), data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
j = k;
|
||||||
|
|
||||||
|
minMaxIdx_reduce_s8( valMin, valMax, idxMin, idxMax, none, minVal, maxVal,
|
||||||
|
minIdx, maxIdx, delta );
|
||||||
|
}
|
||||||
|
while ( j < len0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
minMaxIdx_finish( src, mask, minval, maxval, minidx, maxidx, minVal, maxVal,
|
||||||
|
minIdx, maxIdx, len, startidx, j );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void minMaxIdx_16u(const ushort* src, const uchar* mask, int* minval, int* maxval,
|
static void minMaxIdx_16u(const ushort* src, const uchar* mask, int* minval, int* maxval,
|
||||||
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
||||||
{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
|
{
|
||||||
|
#if CV_SIMD128
|
||||||
|
if ( len >= v_uint16x8::nlanes )
|
||||||
|
{
|
||||||
|
int j, len0;
|
||||||
|
int minVal, maxVal;
|
||||||
|
size_t minIdx, maxIdx;
|
||||||
|
|
||||||
|
minMaxIdx_init( src, mask, minval, maxval, minidx, maxidx, minVal, maxVal, minIdx, maxIdx,
|
||||||
|
(int)0, (int)USHRT_MAX, v_uint16x8::nlanes, len, startidx, j, len0 );
|
||||||
|
|
||||||
|
if ( j <= len0 - v_uint16x8::nlanes )
|
||||||
|
{
|
||||||
|
v_uint16x8 inc = v_setall_u16(v_uint16x8::nlanes);
|
||||||
|
v_uint16x8 none = v_reinterpret_as_u16(v_setall_s16(-1));
|
||||||
|
v_uint16x8 idxStart(0, 1, 2, 3, 4, 5, 6, 7);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
v_uint16x8 valMin = v_setall_u16((ushort)minVal), valMax = v_setall_u16((ushort)maxVal);
|
||||||
|
v_uint16x8 idx = idxStart, idxMin = none, idxMax = none;
|
||||||
|
|
||||||
|
int k = j;
|
||||||
|
size_t delta = startidx + j;
|
||||||
|
|
||||||
|
if ( !mask )
|
||||||
|
{
|
||||||
|
for( ; k < std::min(len0, j + 8191 * v_uint16x8::nlanes); k += v_uint16x8::nlanes )
|
||||||
|
{
|
||||||
|
v_uint16x8 data = v_load(src + k);
|
||||||
|
v_uint16x8 cmpMin = (data < valMin);
|
||||||
|
v_uint16x8 cmpMax = (data > valMax);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_min(data, valMin);
|
||||||
|
valMax = v_max(data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( ; k < std::min(len0, j + 8191 * v_uint16x8::nlanes); k += v_uint16x8::nlanes )
|
||||||
|
{
|
||||||
|
v_uint16x8 data = v_load(src + k);
|
||||||
|
v_uint16x8 maskVal = v_load_expand(mask + k) != v_setzero_u16();
|
||||||
|
v_uint16x8 cmpMin = (data < valMin) & maskVal;
|
||||||
|
v_uint16x8 cmpMax = (data > valMax) & maskVal;
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_select(cmpMin, data, valMin);
|
||||||
|
valMax = v_select(cmpMax, data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
j = k;
|
||||||
|
|
||||||
|
minMaxIdx_reduce_u16( valMin, valMax, idxMin, idxMax, none, minVal, maxVal,
|
||||||
|
minIdx, maxIdx, delta );
|
||||||
|
}
|
||||||
|
while ( j < len0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
minMaxIdx_finish( src, mask, minval, maxval, minidx, maxidx, minVal, maxVal,
|
||||||
|
minIdx, maxIdx, len, startidx, j );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void minMaxIdx_16s(const short* src, const uchar* mask, int* minval, int* maxval,
|
static void minMaxIdx_16s(const short* src, const uchar* mask, int* minval, int* maxval,
|
||||||
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
||||||
{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
|
{
|
||||||
|
#if CV_SIMD128
|
||||||
|
if ( len >= v_int16x8::nlanes )
|
||||||
|
{
|
||||||
|
int j, len0;
|
||||||
|
int minVal, maxVal;
|
||||||
|
size_t minIdx, maxIdx;
|
||||||
|
|
||||||
|
minMaxIdx_init( src, mask, minval, maxval, minidx, maxidx, minVal, maxVal, minIdx, maxIdx,
|
||||||
|
(int)SHRT_MIN, (int)SHRT_MAX, v_int16x8::nlanes, len, startidx, j, len0 );
|
||||||
|
|
||||||
|
if ( j <= len0 - v_int16x8::nlanes )
|
||||||
|
{
|
||||||
|
v_uint16x8 inc = v_setall_u16(v_int16x8::nlanes);
|
||||||
|
v_uint16x8 none = v_reinterpret_as_u16(v_setall_s16(-1));
|
||||||
|
v_uint16x8 idxStart(0, 1, 2, 3, 4, 5, 6, 7);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
v_int16x8 valMin = v_setall_s16((short)minVal), valMax = v_setall_s16((short)maxVal);
|
||||||
|
v_uint16x8 idx = idxStart, idxMin = none, idxMax = none;
|
||||||
|
|
||||||
|
int k = j;
|
||||||
|
size_t delta = startidx + j;
|
||||||
|
|
||||||
|
if ( !mask )
|
||||||
|
{
|
||||||
|
for( ; k < std::min(len0, j + 8191 * v_int16x8::nlanes); k += v_int16x8::nlanes )
|
||||||
|
{
|
||||||
|
v_int16x8 data = v_load(src + k);
|
||||||
|
v_uint16x8 cmpMin = v_reinterpret_as_u16(data < valMin);
|
||||||
|
v_uint16x8 cmpMax = v_reinterpret_as_u16(data > valMax);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_min(data, valMin);
|
||||||
|
valMax = v_max(data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( ; k < std::min(len0, j + 8191 * v_int16x8::nlanes); k += v_int16x8::nlanes )
|
||||||
|
{
|
||||||
|
v_int16x8 data = v_load(src + k);
|
||||||
|
v_uint16x8 maskVal = v_load_expand(mask + k) != v_setzero_u16();
|
||||||
|
v_uint16x8 cmpMin = v_reinterpret_as_u16(data < valMin) & maskVal;
|
||||||
|
v_uint16x8 cmpMax = v_reinterpret_as_u16(data > valMax) & maskVal;
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_select(v_reinterpret_as_s16(cmpMin), data, valMin);
|
||||||
|
valMax = v_select(v_reinterpret_as_s16(cmpMax), data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
j = k;
|
||||||
|
|
||||||
|
minMaxIdx_reduce_s16( valMin, valMax, idxMin, idxMax, none, minVal, maxVal,
|
||||||
|
minIdx, maxIdx, delta );
|
||||||
|
}
|
||||||
|
while ( j < len0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
minMaxIdx_finish( src, mask, minval, maxval, minidx, maxidx, minVal, maxVal,
|
||||||
|
minIdx, maxIdx, len, startidx, j );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void minMaxIdx_32s(const int* src, const uchar* mask, int* minval, int* maxval,
|
static void minMaxIdx_32s(const int* src, const uchar* mask, int* minval, int* maxval,
|
||||||
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
||||||
{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
|
{
|
||||||
|
#if CV_SIMD128
|
||||||
|
if ( len >= 2 * v_int32x4::nlanes )
|
||||||
|
{
|
||||||
|
int j = 0, len0 = len & -(2 * v_int32x4::nlanes);
|
||||||
|
int minVal = *minval, maxVal = *maxval;
|
||||||
|
size_t minIdx = *minidx, maxIdx = *maxidx;
|
||||||
|
|
||||||
|
{
|
||||||
|
v_uint32x4 inc = v_setall_u32(v_int32x4::nlanes);
|
||||||
|
v_uint32x4 none = v_reinterpret_as_u32(v_setall_s32(-1));
|
||||||
|
v_uint32x4 idxStart(0, 1, 2, 3);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
v_int32x4 valMin = v_setall_s32(minVal), valMax = v_setall_s32(maxVal);
|
||||||
|
v_uint32x4 idx = idxStart, idxMin = none, idxMax = none;
|
||||||
|
|
||||||
|
int k = j;
|
||||||
|
size_t delta = startidx + j;
|
||||||
|
|
||||||
|
if ( !mask )
|
||||||
|
{
|
||||||
|
for( ; k < std::min(len0, j + 32766 * 2 * v_int32x4::nlanes); k += 2 * v_int32x4::nlanes )
|
||||||
|
{
|
||||||
|
v_int32x4 data = v_load(src + k);
|
||||||
|
v_uint32x4 cmpMin = v_reinterpret_as_u32(data < valMin);
|
||||||
|
v_uint32x4 cmpMax = v_reinterpret_as_u32(data > valMax);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_min(data, valMin);
|
||||||
|
valMax = v_max(data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
data = v_load(src + k + v_int32x4::nlanes);
|
||||||
|
cmpMin = v_reinterpret_as_u32(data < valMin);
|
||||||
|
cmpMax = v_reinterpret_as_u32(data > valMax);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_min(data, valMin);
|
||||||
|
valMax = v_max(data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( ; k < std::min(len0, j + 32766 * 2 * v_int32x4::nlanes); k += 2 * v_int32x4::nlanes )
|
||||||
|
{
|
||||||
|
v_int32x4 data = v_load(src + k);
|
||||||
|
v_uint16x8 maskVal = v_load_expand(mask + k) != v_setzero_u16();
|
||||||
|
v_int32x4 maskVal1, maskVal2;
|
||||||
|
v_expand(v_reinterpret_as_s16(maskVal), maskVal1, maskVal2);
|
||||||
|
v_uint32x4 cmpMin = v_reinterpret_as_u32((data < valMin) & maskVal1);
|
||||||
|
v_uint32x4 cmpMax = v_reinterpret_as_u32((data > valMax) & maskVal1);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_select(v_reinterpret_as_s32(cmpMin), data, valMin);
|
||||||
|
valMax = v_select(v_reinterpret_as_s32(cmpMax), data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
data = v_load(src + k + v_int32x4::nlanes);
|
||||||
|
cmpMin = v_reinterpret_as_u32((data < valMin) & maskVal2);
|
||||||
|
cmpMax = v_reinterpret_as_u32((data > valMax) & maskVal2);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_select(v_reinterpret_as_s32(cmpMin), data, valMin);
|
||||||
|
valMax = v_select(v_reinterpret_as_s32(cmpMax), data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
j = k;
|
||||||
|
|
||||||
|
minMaxIdx_reduce_s32( valMin, valMax, idxMin, idxMax, none, minVal, maxVal,
|
||||||
|
minIdx, maxIdx, delta );
|
||||||
|
}
|
||||||
|
while ( j < len0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
minMaxIdx_finish( src, mask, minval, maxval, minidx, maxidx, minVal, maxVal,
|
||||||
|
minIdx, maxIdx, len, startidx, j );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void minMaxIdx_32f(const float* src, const uchar* mask, float* minval, float* maxval,
|
static void minMaxIdx_32f(const float* src, const uchar* mask, float* minval, float* maxval,
|
||||||
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
||||||
{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
|
{
|
||||||
|
#if CV_SIMD128
|
||||||
|
if ( len >= 2 * v_float32x4::nlanes )
|
||||||
|
{
|
||||||
|
int j, len0;
|
||||||
|
float minVal, maxVal;
|
||||||
|
size_t minIdx, maxIdx;
|
||||||
|
|
||||||
|
minMaxIdx_init( src, mask, minval, maxval, minidx, maxidx, minVal, maxVal, minIdx, maxIdx,
|
||||||
|
FLT_MIN, FLT_MAX, 2 * v_float32x4::nlanes, len, startidx, j, len0 );
|
||||||
|
|
||||||
|
if ( j <= len0 - 2 * v_float32x4::nlanes )
|
||||||
|
{
|
||||||
|
v_uint32x4 inc = v_setall_u32(v_float32x4::nlanes);
|
||||||
|
v_uint32x4 none = v_reinterpret_as_u32(v_setall_s32(-1));
|
||||||
|
v_uint32x4 idxStart(0, 1, 2, 3);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
v_float32x4 valMin = v_setall_f32(minVal), valMax = v_setall_f32(maxVal);
|
||||||
|
v_uint32x4 idx = idxStart, idxMin = none, idxMax = none;
|
||||||
|
|
||||||
|
int k = j;
|
||||||
|
size_t delta = startidx + j;
|
||||||
|
|
||||||
|
if ( !mask )
|
||||||
|
{
|
||||||
|
for( ; k < std::min(len0, j + 32766 * 2 * v_float32x4::nlanes); k += 2 * v_float32x4::nlanes )
|
||||||
|
{
|
||||||
|
v_float32x4 data = v_load(src + k);
|
||||||
|
v_uint32x4 cmpMin = v_reinterpret_as_u32(data < valMin);
|
||||||
|
v_uint32x4 cmpMax = v_reinterpret_as_u32(data > valMax);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_min(data, valMin);
|
||||||
|
valMax = v_max(data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
data = v_load(src + k + v_float32x4::nlanes);
|
||||||
|
cmpMin = v_reinterpret_as_u32(data < valMin);
|
||||||
|
cmpMax = v_reinterpret_as_u32(data > valMax);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_min(data, valMin);
|
||||||
|
valMax = v_max(data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( ; k < std::min(len0, j + 32766 * 2 * v_float32x4::nlanes); k += 2 * v_float32x4::nlanes )
|
||||||
|
{
|
||||||
|
v_float32x4 data = v_load(src + k);
|
||||||
|
v_uint16x8 maskVal = v_load_expand(mask + k) != v_setzero_u16();
|
||||||
|
v_int32x4 maskVal1, maskVal2;
|
||||||
|
v_expand(v_reinterpret_as_s16(maskVal), maskVal1, maskVal2);
|
||||||
|
v_uint32x4 cmpMin = v_reinterpret_as_u32(v_reinterpret_as_s32(data < valMin) & maskVal1);
|
||||||
|
v_uint32x4 cmpMax = v_reinterpret_as_u32(v_reinterpret_as_s32(data > valMax) & maskVal1);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_select(v_reinterpret_as_f32(cmpMin), data, valMin);
|
||||||
|
valMax = v_select(v_reinterpret_as_f32(cmpMax), data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
data = v_load(src + k + v_float32x4::nlanes);
|
||||||
|
cmpMin = v_reinterpret_as_u32(v_reinterpret_as_s32(data < valMin) & maskVal2);
|
||||||
|
cmpMax = v_reinterpret_as_u32(v_reinterpret_as_s32(data > valMax) & maskVal2);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_select(v_reinterpret_as_f32(cmpMin), data, valMin);
|
||||||
|
valMax = v_select(v_reinterpret_as_f32(cmpMax), data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
j = k;
|
||||||
|
|
||||||
|
minMaxIdx_reduce_f32( valMin, valMax, idxMin, idxMax, none, minVal, maxVal,
|
||||||
|
minIdx, maxIdx, delta );
|
||||||
|
}
|
||||||
|
while ( j < len0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
minMaxIdx_finish( src, mask, minval, maxval, minidx, maxidx, minVal, maxVal,
|
||||||
|
minIdx, maxIdx, len, startidx, j );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void minMaxIdx_64f(const double* src, const uchar* mask, double* minval, double* maxval,
|
static void minMaxIdx_64f(const double* src, const uchar* mask, double* minval, double* maxval,
|
||||||
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
size_t* minidx, size_t* maxidx, int len, size_t startidx )
|
||||||
{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); }
|
{
|
||||||
|
#if CV_SIMD128_64F
|
||||||
|
if ( len >= 4 * v_float64x2::nlanes )
|
||||||
|
{
|
||||||
|
int j, len0;
|
||||||
|
double minVal, maxVal;
|
||||||
|
size_t minIdx, maxIdx;
|
||||||
|
|
||||||
|
minMaxIdx_init( src, mask, minval, maxval, minidx, maxidx, minVal, maxVal, minIdx, maxIdx,
|
||||||
|
DBL_MIN, DBL_MAX, 4 * v_float64x2::nlanes, len, startidx, j, len0 );
|
||||||
|
|
||||||
|
if ( j <= len0 - 4 * v_float64x2::nlanes )
|
||||||
|
{
|
||||||
|
v_uint64x2 inc = v_setall_u64(v_float64x2::nlanes);
|
||||||
|
v_uint64x2 none = v_reinterpret_as_u64(v_setall_s64(-1));
|
||||||
|
v_uint64x2 idxStart(0, 1);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
v_float64x2 valMin = v_setall_f64(minVal), valMax = v_setall_f64(maxVal);
|
||||||
|
v_uint64x2 idx = idxStart, idxMin = none, idxMax = none;
|
||||||
|
|
||||||
|
int k = j;
|
||||||
|
size_t delta = startidx + j;
|
||||||
|
|
||||||
|
if ( !mask )
|
||||||
|
{
|
||||||
|
for( ; k < std::min(len0, j + 32764 * 4 * v_float64x2::nlanes); k += 4 * v_float64x2::nlanes )
|
||||||
|
{
|
||||||
|
v_float64x2 data = v_load(src + k);
|
||||||
|
v_uint64x2 cmpMin = v_reinterpret_as_u64(data < valMin);
|
||||||
|
v_uint64x2 cmpMax = v_reinterpret_as_u64(data > valMax);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_min(data, valMin);
|
||||||
|
valMax = v_max(data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
data = v_load(src + k + v_float64x2::nlanes);
|
||||||
|
cmpMin = v_reinterpret_as_u64(data < valMin);
|
||||||
|
cmpMax = v_reinterpret_as_u64(data > valMax);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_min(data, valMin);
|
||||||
|
valMax = v_max(data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
data = v_load(src + k + 2 * v_float64x2::nlanes);
|
||||||
|
cmpMin = v_reinterpret_as_u64(data < valMin);
|
||||||
|
cmpMax = v_reinterpret_as_u64(data > valMax);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_min(data, valMin);
|
||||||
|
valMax = v_max(data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
data = v_load(src + k + 3 * v_float64x2::nlanes);
|
||||||
|
cmpMin = v_reinterpret_as_u64(data < valMin);
|
||||||
|
cmpMax = v_reinterpret_as_u64(data > valMax);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_min(data, valMin);
|
||||||
|
valMax = v_max(data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( ; k < std::min(len0, j + 32764 * 4 * v_float64x2::nlanes); k += 4 * v_float64x2::nlanes )
|
||||||
|
{
|
||||||
|
v_float64x2 data = v_load(src + k);
|
||||||
|
v_uint16x8 maskVal = v_load_expand(mask + k) != v_setzero_u16();
|
||||||
|
v_int32x4 maskVal1, maskVal2;
|
||||||
|
v_expand(v_reinterpret_as_s16(maskVal), maskVal1, maskVal2);
|
||||||
|
v_int64x2 maskVal3, maskVal4;
|
||||||
|
v_expand(maskVal1, maskVal3, maskVal4);
|
||||||
|
v_uint64x2 cmpMin = v_reinterpret_as_u64(v_reinterpret_as_s64(data < valMin) & maskVal3);
|
||||||
|
v_uint64x2 cmpMax = v_reinterpret_as_u64(v_reinterpret_as_s64(data > valMax) & maskVal3);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_select(v_reinterpret_as_f64(cmpMin), data, valMin);
|
||||||
|
valMax = v_select(v_reinterpret_as_f64(cmpMax), data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
data = v_load(src + k + v_float64x2::nlanes);
|
||||||
|
cmpMin = v_reinterpret_as_u64(v_reinterpret_as_s64(data < valMin) & maskVal4);
|
||||||
|
cmpMax = v_reinterpret_as_u64(v_reinterpret_as_s64(data > valMax) & maskVal4);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_select(v_reinterpret_as_f64(cmpMin), data, valMin);
|
||||||
|
valMax = v_select(v_reinterpret_as_f64(cmpMax), data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
data = v_load(src + k + 2 * v_float64x2::nlanes);
|
||||||
|
v_expand(maskVal2, maskVal3, maskVal4);
|
||||||
|
cmpMin = v_reinterpret_as_u64(v_reinterpret_as_s64(data < valMin) & maskVal3);
|
||||||
|
cmpMax = v_reinterpret_as_u64(v_reinterpret_as_s64(data > valMax) & maskVal3);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_select(v_reinterpret_as_f64(cmpMin), data, valMin);
|
||||||
|
valMax = v_select(v_reinterpret_as_f64(cmpMax), data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
data = v_load(src + k + 3 * v_float64x2::nlanes);
|
||||||
|
cmpMin = v_reinterpret_as_u64(v_reinterpret_as_s64(data < valMin) & maskVal4);
|
||||||
|
cmpMax = v_reinterpret_as_u64(v_reinterpret_as_s64(data > valMax) & maskVal4);
|
||||||
|
idxMin = v_select(cmpMin, idx, idxMin);
|
||||||
|
idxMax = v_select(cmpMax, idx, idxMax);
|
||||||
|
valMin = v_select(v_reinterpret_as_f64(cmpMin), data, valMin);
|
||||||
|
valMax = v_select(v_reinterpret_as_f64(cmpMax), data, valMax);
|
||||||
|
idx += inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
j = k;
|
||||||
|
|
||||||
|
minMaxIdx_reduce_f64( valMin, valMax, idxMin, idxMax, none, minVal, maxVal,
|
||||||
|
minIdx, maxIdx, delta );
|
||||||
|
}
|
||||||
|
while ( j < len0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
minMaxIdx_finish( src, mask, minval, maxval, minidx, maxidx, minVal, maxVal,
|
||||||
|
minIdx, maxIdx, len, startidx, j );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
typedef void (*MinMaxIdxFunc)(const uchar*, const uchar*, int*, int*, size_t*, size_t*, int, size_t);
|
typedef void (*MinMaxIdxFunc)(const uchar*, const uchar*, int*, int*, size_t*, size_t*, int, size_t);
|
||||||
|
|
||||||
|
@ -894,13 +894,18 @@ template<typename R> struct TheTest
|
|||||||
TheTest & test_reduce()
|
TheTest & test_reduce()
|
||||||
{
|
{
|
||||||
Data<R> dataA;
|
Data<R> dataA;
|
||||||
|
int sum = 0;
|
||||||
|
for (int i = 0; i < R::nlanes; ++i)
|
||||||
|
{
|
||||||
|
sum += (int)(dataA[i]); // To prevent a constant overflow with int8
|
||||||
|
}
|
||||||
R a = dataA;
|
R a = dataA;
|
||||||
EXPECT_EQ((LaneType)1, v_reduce_min(a));
|
EXPECT_EQ((LaneType)1, (LaneType)v_reduce_min(a));
|
||||||
EXPECT_EQ((LaneType)R::nlanes, v_reduce_max(a));
|
EXPECT_EQ((LaneType)(R::nlanes), (LaneType)v_reduce_max(a));
|
||||||
EXPECT_EQ((LaneType)((1 + R::nlanes)*R::nlanes/2), v_reduce_sum(a));
|
EXPECT_EQ((int)(sum), (int)v_reduce_sum(a));
|
||||||
dataA[0] += R::nlanes;
|
dataA[0] += R::nlanes;
|
||||||
R an = dataA;
|
R an = dataA;
|
||||||
EXPECT_EQ((LaneType)2, v_reduce_min(an));
|
EXPECT_EQ((LaneType)2, (LaneType)v_reduce_min(an));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1588,6 +1593,7 @@ void test_hal_intrin_uint8()
|
|||||||
.test_dotprod_expand()
|
.test_dotprod_expand()
|
||||||
.test_min_max()
|
.test_min_max()
|
||||||
.test_absdiff()
|
.test_absdiff()
|
||||||
|
.test_reduce()
|
||||||
.test_reduce_sad()
|
.test_reduce_sad()
|
||||||
.test_mask()
|
.test_mask()
|
||||||
.test_popcount()
|
.test_popcount()
|
||||||
@ -1629,6 +1635,7 @@ void test_hal_intrin_int8()
|
|||||||
.test_absdiff()
|
.test_absdiff()
|
||||||
.test_absdiffs()
|
.test_absdiffs()
|
||||||
.test_abs()
|
.test_abs()
|
||||||
|
.test_reduce()
|
||||||
.test_reduce_sad()
|
.test_reduce_sad()
|
||||||
.test_mask()
|
.test_mask()
|
||||||
.test_popcount()
|
.test_popcount()
|
||||||
|
@ -86,7 +86,7 @@ CV__DNN_INLINE_NS_BEGIN
|
|||||||
*/
|
*/
|
||||||
enum Target
|
enum Target
|
||||||
{
|
{
|
||||||
DNN_TARGET_CPU,
|
DNN_TARGET_CPU = 0,
|
||||||
DNN_TARGET_OPENCL,
|
DNN_TARGET_OPENCL,
|
||||||
DNN_TARGET_OPENCL_FP16,
|
DNN_TARGET_OPENCL_FP16,
|
||||||
DNN_TARGET_MYRIAD,
|
DNN_TARGET_MYRIAD,
|
||||||
@ -97,7 +97,7 @@ CV__DNN_INLINE_NS_BEGIN
|
|||||||
};
|
};
|
||||||
|
|
||||||
CV_EXPORTS std::vector< std::pair<Backend, Target> > getAvailableBackends();
|
CV_EXPORTS std::vector< std::pair<Backend, Target> > getAvailableBackends();
|
||||||
CV_EXPORTS std::vector<Target> getAvailableTargets(Backend be);
|
CV_EXPORTS_W std::vector<Target> getAvailableTargets(dnn::Backend be);
|
||||||
|
|
||||||
/** @brief This class provides all data needed to initialize layer.
|
/** @brief This class provides all data needed to initialize layer.
|
||||||
*
|
*
|
||||||
|
@ -36,6 +36,14 @@
|
|||||||
"v_type": "vector_Layer",
|
"v_type": "vector_Layer",
|
||||||
"j_import": "org.opencv.dnn.Layer"
|
"j_import": "org.opencv.dnn.Layer"
|
||||||
},
|
},
|
||||||
|
"vector_Target": {
|
||||||
|
"j_type": "List<Integer>",
|
||||||
|
"jn_type": "List<Integer>",
|
||||||
|
"jni_type": "jobject",
|
||||||
|
"jni_var": "std::vector< cv::dnn::Target > %(n)s",
|
||||||
|
"suffix": "Ljava_util_List",
|
||||||
|
"v_type": "vector_Target"
|
||||||
|
},
|
||||||
"LayerId": {
|
"LayerId": {
|
||||||
"j_type": "DictValue",
|
"j_type": "DictValue",
|
||||||
"jn_type": "long",
|
"jn_type": "long",
|
||||||
|
@ -60,6 +60,25 @@ jobject vector_Ptr_Layer_to_List(JNIEnv* env, std::vector<cv::Ptr<cv::dnn::Layer
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jobject vector_Target_to_List(JNIEnv* env, std::vector<cv::dnn::Target>& vs)
|
||||||
|
{
|
||||||
|
static jclass juArrayList = ARRAYLIST(env);
|
||||||
|
static jmethodID m_create = CONSTRUCTOR(env, juArrayList);
|
||||||
|
jmethodID m_add = LIST_ADD(env, juArrayList);
|
||||||
|
|
||||||
|
static jclass jInteger = env->FindClass("java/lang/Integer");
|
||||||
|
static jmethodID m_create_Integer = env->GetMethodID(jInteger, "<init>", "(I)V");
|
||||||
|
|
||||||
|
jobject result = env->NewObject(juArrayList, m_create, vs.size());
|
||||||
|
for (size_t i = 0; i < vs.size(); ++i)
|
||||||
|
{
|
||||||
|
jobject element = env->NewObject(jInteger, m_create_Integer, vs[i]);
|
||||||
|
env->CallBooleanMethod(result, m_add, element);
|
||||||
|
env->DeleteLocalRef(element);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<cv::Ptr<cv::dnn::Layer> > List_to_vector_Ptr_Layer(JNIEnv* env, jobject list)
|
std::vector<cv::Ptr<cv::dnn::Layer> > List_to_vector_Ptr_Layer(JNIEnv* env, jobject list)
|
||||||
{
|
{
|
||||||
static jclass juArrayList = ARRAYLIST(env);
|
static jclass juArrayList = ARRAYLIST(env);
|
||||||
|
@ -28,5 +28,6 @@ jobject vector_Ptr_Layer_to_List(JNIEnv* env, std::vector<cv::Ptr<cv::dnn::Layer
|
|||||||
|
|
||||||
std::vector<cv::Ptr<cv::dnn::Layer> > List_to_vector_Ptr_Layer(JNIEnv* env, jobject list);
|
std::vector<cv::Ptr<cv::dnn::Layer> > List_to_vector_Ptr_Layer(JNIEnv* env, jobject list);
|
||||||
|
|
||||||
|
jobject vector_Target_to_List(JNIEnv* env, std::vector<cv::dnn::Target>& vs);
|
||||||
|
|
||||||
#endif /* DNN_CONVERTERS_HPP */
|
#endif /* DNN_CONVERTERS_HPP */
|
||||||
|
@ -141,4 +141,9 @@ public class DnnTensorFlowTest extends OpenCVTestCase {
|
|||||||
net = Dnn.readNetFromTensorflow(new MatOfByte(modelBuffer));
|
net = Dnn.readNetFromTensorflow(new MatOfByte(modelBuffer));
|
||||||
checkInceptionNet(net);
|
checkInceptionNet(net);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testGetAvailableTargets() {
|
||||||
|
List<Integer> targets = Dnn.getAvailableTargets(Dnn.DNN_BACKEND_OPENCV);
|
||||||
|
assertTrue(targets.contains(Dnn.DNN_TARGET_CPU));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,12 @@ PyObject* pyopencv_from(const dnn::LayerParams& lp)
|
|||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
PyObject* pyopencv_from(const std::vector<dnn::Target> &t)
|
||||||
|
{
|
||||||
|
return pyopencv_from(std::vector<int>(t.begin(), t.end()));
|
||||||
|
}
|
||||||
|
|
||||||
class pycvLayer CV_FINAL : public dnn::Layer
|
class pycvLayer CV_FINAL : public dnn::Layer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -117,6 +117,10 @@ class dnn_test(NewOpenCVTests):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def test_getAvailableTargets(self):
|
||||||
|
targets = cv.dnn.getAvailableTargets(cv.dnn.DNN_BACKEND_OPENCV)
|
||||||
|
self.assertTrue(cv.dnn.DNN_TARGET_CPU in targets)
|
||||||
|
|
||||||
def test_blobFromImage(self):
|
def test_blobFromImage(self):
|
||||||
np.random.seed(324)
|
np.random.seed(324)
|
||||||
|
|
||||||
|
@ -556,6 +556,7 @@ namespace cv {
|
|||||||
{
|
{
|
||||||
int kernel_size = getParam<int>(layer_params, "size", -1);
|
int kernel_size = getParam<int>(layer_params, "size", -1);
|
||||||
int pad = getParam<int>(layer_params, "pad", 0);
|
int pad = getParam<int>(layer_params, "pad", 0);
|
||||||
|
int padding = getParam<int>(layer_params, "padding", 0);
|
||||||
int stride = getParam<int>(layer_params, "stride", 1);
|
int stride = getParam<int>(layer_params, "stride", 1);
|
||||||
int filters = getParam<int>(layer_params, "filters", -1);
|
int filters = getParam<int>(layer_params, "filters", -1);
|
||||||
bool batch_normalize = getParam<int>(layer_params, "batch_normalize", 0) == 1;
|
bool batch_normalize = getParam<int>(layer_params, "batch_normalize", 0) == 1;
|
||||||
@ -563,13 +564,13 @@ namespace cv {
|
|||||||
if (flipped == 1)
|
if (flipped == 1)
|
||||||
CV_Error(cv::Error::StsNotImplemented, "Transpose the convolutional weights is not implemented");
|
CV_Error(cv::Error::StsNotImplemented, "Transpose the convolutional weights is not implemented");
|
||||||
|
|
||||||
// correct the strange value of pad=1 for kernel_size=1 in the Darknet cfg-file
|
if (pad)
|
||||||
if (kernel_size < 3) pad = 0;
|
padding = kernel_size / 2;
|
||||||
|
|
||||||
CV_Assert(kernel_size > 0 && filters > 0);
|
CV_Assert(kernel_size > 0 && filters > 0);
|
||||||
CV_Assert(current_channels > 0);
|
CV_Assert(current_channels > 0);
|
||||||
|
|
||||||
setParams.setConvolution(kernel_size, pad, stride, filters, current_channels,
|
setParams.setConvolution(kernel_size, padding, stride, filters, current_channels,
|
||||||
batch_normalize);
|
batch_normalize);
|
||||||
|
|
||||||
current_channels = filters;
|
current_channels = filters;
|
||||||
|
@ -109,7 +109,7 @@ public:
|
|||||||
#ifdef HAVE_INF_ENGINE
|
#ifdef HAVE_INF_ENGINE
|
||||||
static inline bool checkIETarget(Target target)
|
static inline bool checkIETarget(Target target)
|
||||||
{
|
{
|
||||||
#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2019R3)
|
#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2019R3)
|
||||||
// Lightweight detection
|
// Lightweight detection
|
||||||
const std::vector<std::string> devices = getCore().GetAvailableDevices();
|
const std::vector<std::string> devices = getCore().GetAvailableDevices();
|
||||||
for (std::vector<std::string>::const_iterator i = devices.begin(); i != devices.end(); ++i)
|
for (std::vector<std::string>::const_iterator i = devices.begin(); i != devices.end(); ++i)
|
||||||
@ -3098,7 +3098,9 @@ struct Net::Impl
|
|||||||
catch (const cv::Exception& e)
|
catch (const cv::Exception& e)
|
||||||
{
|
{
|
||||||
CV_LOG_ERROR(NULL, "OPENCV/DNN: [" << l->type << "]:(" << l->name << "): getMemoryShapes() throws exception." <<
|
CV_LOG_ERROR(NULL, "OPENCV/DNN: [" << l->type << "]:(" << l->name << "): getMemoryShapes() throws exception." <<
|
||||||
" inputs=" << is.size() << " outputs=" << os.size() << "/" << requiredOutputs);
|
" inputs=" << is.size() <<
|
||||||
|
" outputs=" << os.size() << "/" << requiredOutputs <<
|
||||||
|
" blobs=" << l->blobs.size());
|
||||||
for (size_t i = 0; i < is.size(); ++i)
|
for (size_t i = 0; i < is.size(); ++i)
|
||||||
{
|
{
|
||||||
CV_LOG_ERROR(NULL, " input[" << i << "] = " << toString(is[i]));
|
CV_LOG_ERROR(NULL, " input[" << i << "] = " << toString(is[i]));
|
||||||
@ -3107,6 +3109,10 @@ struct Net::Impl
|
|||||||
{
|
{
|
||||||
CV_LOG_ERROR(NULL, " output[" << i << "] = " << toString(os[i]));
|
CV_LOG_ERROR(NULL, " output[" << i << "] = " << toString(os[i]));
|
||||||
}
|
}
|
||||||
|
for (size_t i = 0; i < l->blobs.size(); ++i)
|
||||||
|
{
|
||||||
|
CV_LOG_ERROR(NULL, " blobs[" << i << "] = " << typeToString(l->blobs[i].type()) << " " << toString(shape(l->blobs[i])));
|
||||||
|
}
|
||||||
CV_LOG_ERROR(NULL, "Exception message: " << e.what());
|
CV_LOG_ERROR(NULL, "Exception message: " << e.what());
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
@ -323,7 +323,14 @@ void InfEngineNgraphNet::initPlugin(InferenceEngine::CNNNetwork& net)
|
|||||||
}
|
}
|
||||||
// Some of networks can work without a library of extra layers.
|
// Some of networks can work without a library of extra layers.
|
||||||
// OpenCV fallbacks as extensions.
|
// OpenCV fallbacks as extensions.
|
||||||
|
try
|
||||||
|
{
|
||||||
ie.AddExtension(std::make_shared<InfEngineExtension>(), "CPU");
|
ie.AddExtension(std::make_shared<InfEngineExtension>(), "CPU");
|
||||||
|
}
|
||||||
|
catch(const std::exception& e)
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "DNN-IE: Can't register OpenCV custom layers extension: " << e.what());
|
||||||
|
}
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
// Limit the number of CPU threads.
|
// Limit the number of CPU threads.
|
||||||
if (device_name == "CPU")
|
if (device_name == "CPU")
|
||||||
|
@ -103,7 +103,7 @@ public:
|
|||||||
return bias == (int)bias;
|
return bias == (int)bias;
|
||||||
}
|
}
|
||||||
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) {
|
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) {
|
||||||
return type == CHANNEL_NRM && bias == (int)bias;
|
return bias == (int)bias;
|
||||||
}
|
}
|
||||||
return backendId == DNN_BACKEND_OPENCV ||
|
return backendId == DNN_BACKEND_OPENCV ||
|
||||||
backendId == DNN_BACKEND_CUDA ||
|
backendId == DNN_BACKEND_CUDA ||
|
||||||
@ -471,7 +471,15 @@ public:
|
|||||||
alphaSize *= (type == SPATIAL_NRM ? size*size : size);
|
alphaSize *= (type == SPATIAL_NRM ? size*size : size);
|
||||||
|
|
||||||
auto& ieInpNode = nodes[0].dynamicCast<InfEngineNgraphNode>()->node;
|
auto& ieInpNode = nodes[0].dynamicCast<InfEngineNgraphNode>()->node;
|
||||||
auto lrn = std::make_shared<ngraph::op::LRN>(ieInpNode, (double)alphaSize, (double)beta, (double)bias, (size_t)size);
|
std::vector<int64_t> axes;
|
||||||
|
if (type != SPATIAL_NRM) {
|
||||||
|
axes = {1};
|
||||||
|
} else {
|
||||||
|
axes.resize(ieInpNode->get_shape().size() - 2);
|
||||||
|
std::iota(axes.begin(), axes.end(), 2);
|
||||||
|
}
|
||||||
|
auto ngraph_axes = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{axes.size()}, axes.data());
|
||||||
|
auto lrn = std::make_shared<ngraph::op::LRN>(ieInpNode, ngraph_axes, alphaSize, beta, bias, size);
|
||||||
return Ptr<BackendNode>(new InfEngineNgraphNode(lrn));
|
return Ptr<BackendNode>(new InfEngineNgraphNode(lrn));
|
||||||
}
|
}
|
||||||
#endif // HAVE_DNN_NGRAPH
|
#endif // HAVE_DNN_NGRAPH
|
||||||
|
@ -119,8 +119,10 @@ public:
|
|||||||
virtual bool supportBackend(int backendId) CV_OVERRIDE
|
virtual bool supportBackend(int backendId) CV_OVERRIDE
|
||||||
{
|
{
|
||||||
#ifdef HAVE_INF_ENGINE
|
#ifdef HAVE_INF_ENGINE
|
||||||
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
|
||||||
return !zeroDev && (preferableTarget != DNN_TARGET_MYRIAD || eps <= 1e-7f);
|
return !zeroDev && (preferableTarget != DNN_TARGET_MYRIAD || eps <= 1e-7f);
|
||||||
|
else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||||
|
return true;
|
||||||
else
|
else
|
||||||
#endif // HAVE_INF_ENGINE
|
#endif // HAVE_INF_ENGINE
|
||||||
return backendId == DNN_BACKEND_OPENCV;
|
return backendId == DNN_BACKEND_OPENCV;
|
||||||
|
@ -98,7 +98,7 @@ private:
|
|||||||
class SoftMaxSubgraph : public Subgraph
|
class SoftMaxSubgraph : public Subgraph
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SoftMaxSubgraph()
|
SoftMaxSubgraph() : axis(1)
|
||||||
{
|
{
|
||||||
int input = addNodeToMatch("");
|
int input = addNodeToMatch("");
|
||||||
int inpExp = addNodeToMatch("Exp", input);
|
int inpExp = addNodeToMatch("Exp", input);
|
||||||
|
@ -147,8 +147,18 @@ Mat getMatFromTensor(opencv_onnx::TensorProto& tensor_proto)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char* val = const_cast<char*>(tensor_proto.raw_data().c_str());
|
const char* val = tensor_proto.raw_data().c_str();
|
||||||
int64_t* src = reinterpret_cast<int64_t*>(val);
|
// Aligned pointer is required: https://github.com/opencv/opencv/issues/16373
|
||||||
|
// this doesn't work: typedef int64_t CV_DECL_ALIGNED(1) unaligned_int64_t;
|
||||||
|
AutoBuffer<int64_t, 16> aligned_val;
|
||||||
|
if (!isAligned<sizeof(int64_t)>(val))
|
||||||
|
{
|
||||||
|
size_t sz = tensor_proto.raw_data().size();
|
||||||
|
aligned_val.allocate(divUp(sz, sizeof(int64_t)));
|
||||||
|
memcpy(aligned_val.data(), val, sz);
|
||||||
|
val = (const char*)aligned_val.data();
|
||||||
|
}
|
||||||
|
const int64_t* src = reinterpret_cast<const int64_t*>(val);
|
||||||
convertInt64ToInt32(src, dst, blob.total());
|
convertInt64ToInt32(src, dst, blob.total());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -574,7 +574,7 @@ InferenceEngine::Core& getCore()
|
|||||||
#if !defined(OPENCV_DNN_IE_VPU_TYPE_DEFAULT)
|
#if !defined(OPENCV_DNN_IE_VPU_TYPE_DEFAULT)
|
||||||
static bool detectMyriadX_()
|
static bool detectMyriadX_()
|
||||||
{
|
{
|
||||||
#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2019R3)
|
#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2019R3)
|
||||||
// Lightweight detection
|
// Lightweight detection
|
||||||
InferenceEngine::Core& ie = getCore();
|
InferenceEngine::Core& ie = getCore();
|
||||||
const std::vector<std::string> devices = ie.GetAvailableDevices();
|
const std::vector<std::string> devices = ie.GetAvailableDevices();
|
||||||
@ -739,7 +739,14 @@ void InfEngineBackendNet::initPlugin(InferenceEngine::CNNNetwork& net)
|
|||||||
// Some of networks can work without a library of extra layers.
|
// Some of networks can work without a library of extra layers.
|
||||||
#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2019R1)
|
#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2019R1)
|
||||||
// OpenCV fallbacks as extensions.
|
// OpenCV fallbacks as extensions.
|
||||||
|
try
|
||||||
|
{
|
||||||
ie.AddExtension(std::make_shared<InfEngineExtension>(), "CPU");
|
ie.AddExtension(std::make_shared<InfEngineExtension>(), "CPU");
|
||||||
|
}
|
||||||
|
catch(const std::exception& e)
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "DNN-IE: Can't register OpenCV custom layers extension: " << e.what());
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
// Limit the number of CPU threads.
|
// Limit the number of CPU threads.
|
||||||
@ -1068,8 +1075,14 @@ void resetMyriadDevice()
|
|||||||
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1)
|
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1)
|
||||||
getSharedPlugins().erase("MYRIAD");
|
getSharedPlugins().erase("MYRIAD");
|
||||||
#else
|
#else
|
||||||
// To unregister both "MYRIAD" and "HETERO:MYRIAD,CPU" plugins
|
// Unregister both "MYRIAD" and "HETERO:MYRIAD,CPU" plugins
|
||||||
getCore() = InferenceEngine::Core();
|
InferenceEngine::Core& ie = getCore();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ie.UnregisterPlugin("MYRIAD");
|
||||||
|
ie.UnregisterPlugin("HETERO");
|
||||||
|
}
|
||||||
|
catch (...) {}
|
||||||
#endif
|
#endif
|
||||||
#endif // HAVE_INF_ENGINE
|
#endif // HAVE_INF_ENGINE
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ public:
|
|||||||
std::string cfg = findDataFile("dnn/darknet/" + name + ".cfg");
|
std::string cfg = findDataFile("dnn/darknet/" + name + ".cfg");
|
||||||
std::string model = "";
|
std::string model = "";
|
||||||
if (hasWeights)
|
if (hasWeights)
|
||||||
model = findDataFile("dnn/darknet/" + name + ".weights", false);
|
model = findDataFile("dnn/darknet/" + name + ".weights");
|
||||||
|
|
||||||
checkBackend(&inp, &ref);
|
checkBackend(&inp, &ref);
|
||||||
|
|
||||||
@ -554,6 +554,15 @@ TEST_P(Test_Darknet_layers, reorg)
|
|||||||
testDarknetLayer("reorg");
|
testDarknetLayer("reorg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(Test_Darknet_layers, convolutional)
|
||||||
|
{
|
||||||
|
if (target == DNN_TARGET_MYRIAD)
|
||||||
|
{
|
||||||
|
default_l1 = 0.01f;
|
||||||
|
}
|
||||||
|
testDarknetLayer("convolutional", true);
|
||||||
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_CASE_P(/**/, Test_Darknet_layers, dnnBackendsAndTargets());
|
INSTANTIATE_TEST_CASE_P(/**/, Test_Darknet_layers, dnnBackendsAndTargets());
|
||||||
|
|
||||||
}} // namespace
|
}} // namespace
|
||||||
|
@ -738,6 +738,20 @@ imdecode_( const Mat& buf, int flags, Mat& mat )
|
|||||||
if( !decoder )
|
if( !decoder )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
int scale_denom = 1;
|
||||||
|
if( flags > IMREAD_LOAD_GDAL )
|
||||||
|
{
|
||||||
|
if( flags & IMREAD_REDUCED_GRAYSCALE_2 )
|
||||||
|
scale_denom = 2;
|
||||||
|
else if( flags & IMREAD_REDUCED_GRAYSCALE_4 )
|
||||||
|
scale_denom = 4;
|
||||||
|
else if( flags & IMREAD_REDUCED_GRAYSCALE_8 )
|
||||||
|
scale_denom = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// set the scale_denom in the driver
|
||||||
|
decoder->setScale( scale_denom );
|
||||||
|
|
||||||
if( !decoder->setSource(buf_row) )
|
if( !decoder->setSource(buf_row) )
|
||||||
{
|
{
|
||||||
filename = tempfile();
|
filename = tempfile();
|
||||||
@ -816,7 +830,7 @@ imdecode_( const Mat& buf, int flags, Mat& mat )
|
|||||||
{
|
{
|
||||||
std::cerr << "imdecode_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush;
|
std::cerr << "imdecode_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush;
|
||||||
}
|
}
|
||||||
decoder.release();
|
|
||||||
if (!filename.empty())
|
if (!filename.empty())
|
||||||
{
|
{
|
||||||
if (0 != remove(filename.c_str()))
|
if (0 != remove(filename.c_str()))
|
||||||
@ -831,6 +845,11 @@ imdecode_( const Mat& buf, int flags, Mat& mat )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( decoder->setScale( scale_denom ) > 1 ) // if decoder is JpegDecoder then decoder->setScale always returns 1
|
||||||
|
{
|
||||||
|
resize(mat, mat, Size( size.width / scale_denom, size.height / scale_denom ), 0, 0, INTER_LINEAR_EXACT);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,4 +8,68 @@
|
|||||||
#include "opencv2/imgcodecs.hpp"
|
#include "opencv2/imgcodecs.hpp"
|
||||||
#include "opencv2/imgproc/imgproc_c.h"
|
#include "opencv2/imgproc/imgproc_c.h"
|
||||||
|
|
||||||
|
namespace cv {
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void PrintTo(const ImreadModes& val, std::ostream* os)
|
||||||
|
{
|
||||||
|
int v = val;
|
||||||
|
if (v == IMREAD_UNCHANGED && (v & IMREAD_IGNORE_ORIENTATION) != 0)
|
||||||
|
{
|
||||||
|
CV_Assert(IMREAD_UNCHANGED == -1);
|
||||||
|
*os << "IMREAD_UNCHANGED";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((v & IMREAD_COLOR) != 0)
|
||||||
|
{
|
||||||
|
CV_Assert(IMREAD_COLOR == 1);
|
||||||
|
v &= ~IMREAD_COLOR;
|
||||||
|
*os << "IMREAD_COLOR" << (v == 0 ? "" : " | ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CV_Assert(IMREAD_GRAYSCALE == 0);
|
||||||
|
*os << "IMREAD_GRAYSCALE" << (v == 0 ? "" : " | ");
|
||||||
|
}
|
||||||
|
if ((v & IMREAD_ANYDEPTH) != 0)
|
||||||
|
{
|
||||||
|
v &= ~IMREAD_ANYDEPTH;
|
||||||
|
*os << "IMREAD_ANYDEPTH" << (v == 0 ? "" : " | ");
|
||||||
|
}
|
||||||
|
if ((v & IMREAD_ANYCOLOR) != 0)
|
||||||
|
{
|
||||||
|
v &= ~IMREAD_ANYCOLOR;
|
||||||
|
*os << "IMREAD_ANYCOLOR" << (v == 0 ? "" : " | ");
|
||||||
|
}
|
||||||
|
if ((v & IMREAD_LOAD_GDAL) != 0)
|
||||||
|
{
|
||||||
|
v &= ~IMREAD_LOAD_GDAL;
|
||||||
|
*os << "IMREAD_LOAD_GDAL" << (v == 0 ? "" : " | ");
|
||||||
|
}
|
||||||
|
if ((v & IMREAD_IGNORE_ORIENTATION) != 0)
|
||||||
|
{
|
||||||
|
v &= ~IMREAD_IGNORE_ORIENTATION;
|
||||||
|
*os << "IMREAD_IGNORE_ORIENTATION" << (v == 0 ? "" : " | ");
|
||||||
|
}
|
||||||
|
switch (v)
|
||||||
|
{
|
||||||
|
case IMREAD_UNCHANGED: return;
|
||||||
|
case IMREAD_GRAYSCALE: return;
|
||||||
|
case IMREAD_COLOR: return;
|
||||||
|
case IMREAD_ANYDEPTH: return;
|
||||||
|
case IMREAD_ANYCOLOR: return;
|
||||||
|
case IMREAD_LOAD_GDAL: return;
|
||||||
|
case IMREAD_REDUCED_GRAYSCALE_2: // fallthru
|
||||||
|
case IMREAD_REDUCED_COLOR_2: *os << "REDUCED_2"; return;
|
||||||
|
case IMREAD_REDUCED_GRAYSCALE_4: // fallthru
|
||||||
|
case IMREAD_REDUCED_COLOR_4: *os << "REDUCED_4"; return;
|
||||||
|
case IMREAD_REDUCED_GRAYSCALE_8: // fallthru
|
||||||
|
case IMREAD_REDUCED_COLOR_8: *os << "REDUCED_8"; return;
|
||||||
|
case IMREAD_IGNORE_ORIENTATION: return;
|
||||||
|
} // don't use "default:" to emit compiler warnings
|
||||||
|
*os << "IMREAD_UNKNOWN(" << (int)v << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,6 +5,95 @@
|
|||||||
|
|
||||||
namespace opencv_test { namespace {
|
namespace opencv_test { namespace {
|
||||||
|
|
||||||
|
/* < <file_name, image_size>, <imread mode, scale> > */
|
||||||
|
typedef tuple< tuple<string, Size>, tuple<ImreadModes, int> > Imgcodecs_Resize_t;
|
||||||
|
|
||||||
|
typedef testing::TestWithParam< Imgcodecs_Resize_t > Imgcodecs_Resize;
|
||||||
|
|
||||||
|
/* resize_flag_and_dims = <imread_flag, scale>*/
|
||||||
|
const tuple <ImreadModes, int> resize_flag_and_dims[] =
|
||||||
|
{
|
||||||
|
make_tuple(IMREAD_UNCHANGED, 1),
|
||||||
|
make_tuple(IMREAD_REDUCED_GRAYSCALE_2, 2),
|
||||||
|
make_tuple(IMREAD_REDUCED_GRAYSCALE_4, 4),
|
||||||
|
make_tuple(IMREAD_REDUCED_GRAYSCALE_8, 8),
|
||||||
|
make_tuple(IMREAD_REDUCED_COLOR_2, 2),
|
||||||
|
make_tuple(IMREAD_REDUCED_COLOR_4, 4),
|
||||||
|
make_tuple(IMREAD_REDUCED_COLOR_8, 8)
|
||||||
|
};
|
||||||
|
|
||||||
|
const tuple<string, Size> images[] =
|
||||||
|
{
|
||||||
|
#ifdef HAVE_JPEG
|
||||||
|
make_tuple<string, Size>("../cv/imgproc/stuff.jpg", Size(640, 480)),
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_PNG
|
||||||
|
make_tuple<string, Size>("../cv/shared/pic1.png", Size(400, 300)),
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_P(Imgcodecs_Resize, imread_reduce_flags)
|
||||||
|
{
|
||||||
|
const string file_name = findDataFile(get<0>(get<0>(GetParam())));
|
||||||
|
const Size imageSize = get<1>(get<0>(GetParam()));
|
||||||
|
|
||||||
|
const int imread_flag = get<0>(get<1>(GetParam()));
|
||||||
|
const int scale = get<1>(get<1>(GetParam()));
|
||||||
|
|
||||||
|
const int cols = imageSize.width / scale;
|
||||||
|
const int rows = imageSize.height / scale;
|
||||||
|
{
|
||||||
|
Mat img = imread(file_name, imread_flag);
|
||||||
|
ASSERT_FALSE(img.empty());
|
||||||
|
EXPECT_EQ(cols, img.cols);
|
||||||
|
EXPECT_EQ(rows, img.rows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
|
||||||
|
TEST_P(Imgcodecs_Resize, imdecode_reduce_flags)
|
||||||
|
{
|
||||||
|
const string file_name = findDataFile(get<0>(get<0>(GetParam())));
|
||||||
|
const Size imageSize = get<1>(get<0>(GetParam()));
|
||||||
|
|
||||||
|
const int imread_flag = get<0>(get<1>(GetParam()));
|
||||||
|
const int scale = get<1>(get<1>(GetParam()));
|
||||||
|
|
||||||
|
const int cols = imageSize.width / scale;
|
||||||
|
const int rows = imageSize.height / scale;
|
||||||
|
|
||||||
|
const std::ios::openmode mode = std::ios::in | std::ios::binary;
|
||||||
|
std::ifstream ifs(file_name.c_str(), mode);
|
||||||
|
ASSERT_TRUE(ifs.is_open());
|
||||||
|
|
||||||
|
ifs.seekg(0, std::ios::end);
|
||||||
|
const size_t sz = static_cast<size_t>(ifs.tellg());
|
||||||
|
ifs.seekg(0, std::ios::beg);
|
||||||
|
|
||||||
|
std::vector<char> content(sz);
|
||||||
|
ifs.read((char*)content.data(), sz);
|
||||||
|
ASSERT_FALSE(ifs.fail());
|
||||||
|
|
||||||
|
{
|
||||||
|
Mat img = imdecode(Mat(content), imread_flag);
|
||||||
|
ASSERT_FALSE(img.empty());
|
||||||
|
EXPECT_EQ(cols, img.cols);
|
||||||
|
EXPECT_EQ(rows, img.rows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_CASE_P(/*nothing*/, Imgcodecs_Resize,
|
||||||
|
testing::Combine(
|
||||||
|
testing::ValuesIn(images),
|
||||||
|
testing::ValuesIn(resize_flag_and_dims)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
|
||||||
TEST(Imgcodecs_Image, read_write_bmp)
|
TEST(Imgcodecs_Image, read_write_bmp)
|
||||||
{
|
{
|
||||||
const size_t IMAGE_COUNT = 10;
|
const size_t IMAGE_COUNT = 10;
|
||||||
|
@ -1526,7 +1526,7 @@ struct HResizeLinearVec_X4
|
|||||||
struct HResizeLinearVecU8_X4
|
struct HResizeLinearVecU8_X4
|
||||||
{
|
{
|
||||||
int operator()(const uchar** src, int** dst, int count, const int* xofs,
|
int operator()(const uchar** src, int** dst, int count, const int* xofs,
|
||||||
const short* alpha/*[xmax]*/, int smax, int /*dmax*/, int cn, int /*xmin*/, int xmax) const
|
const short* alpha/*[xmax]*/, int /*smax*/, int dmax, int cn, int /*xmin*/, int xmax) const
|
||||||
{
|
{
|
||||||
int dx = 0, k = 0;
|
int dx = 0, k = 0;
|
||||||
|
|
||||||
@ -1612,17 +1612,11 @@ struct HResizeLinearVecU8_X4
|
|||||||
}
|
}
|
||||||
else if(cn == 3)
|
else if(cn == 3)
|
||||||
{
|
{
|
||||||
int len0 = xmax - cn;
|
/* Peek at the last x offset to find the maximal s offset. We know the loop
|
||||||
|
will terminate prior to value which may be 1 or more elements prior to the
|
||||||
/* This may need to trim 1 or more extra units depending on the amount of
|
final valid offset. xofs[] is constucted to be an array of increasingly
|
||||||
scaling. Test until we find the first value which we know cannot overrun. */
|
large offsets (i.e xofs[x] <= xofs[x+1] for x < xmax). */
|
||||||
while (len0 >= cn &&
|
int smax = xofs[dmax-cn];
|
||||||
xofs[len0 - cn] + cn >= smax - cn // check access: v_load_expand_q(S+xofs[dx]+cn)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
len0 -= cn;
|
|
||||||
}
|
|
||||||
CV_DbgAssert(len0 <= 0 || len0 >= cn);
|
|
||||||
|
|
||||||
for( ; k <= (count - 2); k+=2 )
|
for( ; k <= (count - 2); k+=2 )
|
||||||
{
|
{
|
||||||
@ -1631,7 +1625,7 @@ struct HResizeLinearVecU8_X4
|
|||||||
const uchar *S1 = src[k+1];
|
const uchar *S1 = src[k+1];
|
||||||
int *D1 = dst[k+1];
|
int *D1 = dst[k+1];
|
||||||
|
|
||||||
for( dx = 0; dx < len0; dx += cn )
|
for( dx = 0; (xofs[dx] + cn) < smax; dx += cn )
|
||||||
{
|
{
|
||||||
v_int16x8 a = v_load(alpha+dx*2);
|
v_int16x8 a = v_load(alpha+dx*2);
|
||||||
v_store(&D0[dx], v_dotprod(v_reinterpret_as_s16(v_load_expand_q(S0+xofs[dx]) | (v_load_expand_q(S0+xofs[dx]+cn)<<16)), a));
|
v_store(&D0[dx], v_dotprod(v_reinterpret_as_s16(v_load_expand_q(S0+xofs[dx]) | (v_load_expand_q(S0+xofs[dx]+cn)<<16)), a));
|
||||||
@ -1642,12 +1636,14 @@ struct HResizeLinearVecU8_X4
|
|||||||
{
|
{
|
||||||
const uchar *S = src[k];
|
const uchar *S = src[k];
|
||||||
int *D = dst[k];
|
int *D = dst[k];
|
||||||
for( dx = 0; dx < len0; dx += cn )
|
for( dx = 0; (xofs[dx] + cn) < smax; dx += cn )
|
||||||
{
|
{
|
||||||
v_int16x8 a = v_load(alpha+dx*2);
|
v_int16x8 a = v_load(alpha+dx*2);
|
||||||
v_store(&D[dx], v_dotprod(v_reinterpret_as_s16(v_load_expand_q(S+xofs[dx]) | (v_load_expand_q(S+xofs[dx]+cn)<<16)), a));
|
v_store(&D[dx], v_dotprod(v_reinterpret_as_s16(v_load_expand_q(S+xofs[dx]) | (v_load_expand_q(S+xofs[dx]+cn)<<16)), a));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Debug check to ensure truthiness that we never vector the final value. */
|
||||||
|
CV_DbgAssert(dx < dmax);
|
||||||
}
|
}
|
||||||
else if(cn == 4)
|
else if(cn == 4)
|
||||||
{
|
{
|
||||||
|
@ -51,8 +51,8 @@ static Mat checkMask(InputArray _mask, Size size)
|
|||||||
{
|
{
|
||||||
Mat mask = _mask.getMat();
|
Mat mask = _mask.getMat();
|
||||||
Mat gray;
|
Mat gray;
|
||||||
if (mask.channels() == 3)
|
if (mask.channels() > 1)
|
||||||
cvtColor(mask, gray, COLOR_BGR2GRAY);
|
cvtColor(mask, gray, COLOR_BGRA2GRAY);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (mask.empty())
|
if (mask.empty())
|
||||||
|
@ -1008,10 +1008,10 @@ static std::string findData(const std::string& relative_path, bool required, boo
|
|||||||
CHECK_FILE_WITH_PREFIX(prefix, result_);
|
CHECK_FILE_WITH_PREFIX(prefix, result_);
|
||||||
if (!required && !result_.empty())
|
if (!required && !result_.empty())
|
||||||
{
|
{
|
||||||
std::cout << "TEST ERROR: Don't use 'optional' findData() for " << relative_path << std::endl;
|
|
||||||
static bool checkOptionalFlag = cv::utils::getConfigurationParameterBool("OPENCV_TEST_CHECK_OPTIONAL_DATA", false);
|
static bool checkOptionalFlag = cv::utils::getConfigurationParameterBool("OPENCV_TEST_CHECK_OPTIONAL_DATA", false);
|
||||||
if (checkOptionalFlag)
|
if (checkOptionalFlag)
|
||||||
{
|
{
|
||||||
|
std::cout << "TEST ERROR: Don't use 'optional' findData() for " << relative_path << std::endl;
|
||||||
CV_Assert(required || result_.empty());
|
CV_Assert(required || result_.empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user