Merge remote-tracking branch 'upstream/3.4' into merge-3.4

This commit is contained in:
Alexander Alekhin 2020-01-22 16:58:30 +03:00
commit 3d14dd4e39
32 changed files with 1151 additions and 94 deletions

View File

@ -20,8 +20,11 @@ if(CMAKE_COMPILER_IS_GNUCC)
# - matchTemplate about 5-10%
# - goodFeaturesToTrack 10-20%
# - cornerHarris 30% for some cases
set_source_files_properties(${carotene_sources} COMPILE_FLAGS "--param ipcp-unit-growth=100000 --param inline-unit-growth=100000 --param large-stack-frame-growth=5000")
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")
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()
add_library(carotene_objs OBJECT

View File

@ -90,7 +90,11 @@ set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS ${carotene_defs})
# matchTemplate about 5-10%
# goodFeaturesToTrack 10-20%
# cornerHarris 30% for some cases
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")
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")
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")
endif()

View File

@ -318,6 +318,21 @@ if(PPC64LE)
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
if(NOT OPENCV_SKIP_EXTRA_COMPILER_FLAGS)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPENCV_EXTRA_FLAGS} ${OPENCV_EXTRA_C_FLAGS}")

View File

@ -20,6 +20,8 @@ if(WIN32)
elseif(MSVC)
SET(OPENEXR_LIBSEARCH_SUFFIXES Win32/Release Win32 Win32/Debug)
endif()
elseif(UNIX)
SET(OPENEXR_LIBSEARCH_SUFFIXES ${CMAKE_LIBRARY_ARCHITECTURE})
endif()
SET(SEARCH_PATHS
@ -39,6 +41,25 @@ MACRO(FIND_OPENEXR_LIBRARY LIBRARY_NAME LIBRARY_SUFFIX)
PATHS "${SEARCH_PATH}/lib" "${SEARCH_PATH}/lib/static")
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})
FIND_PATH(OPENEXR_INCLUDE_PATH ImfRgbaFile.h
PATH_SUFFIXES OpenEXR
@ -64,32 +85,14 @@ FOREACH(SEARCH_PATH ${SEARCH_PATHS})
set(OPENEXR_VERSION "${OPENEXR_VERSION_MAJOR}_${OPENEXR_VERSION_MINOR}")
ENDIF ()
SET(LIBRARY_SUFFIXES
"-${OPENEXR_VERSION}"
"-${OPENEXR_VERSION}_s"
"-${OPENEXR_VERSION}_d"
"-${OPEXEXR_VERSION}_s_d"
""
"_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()
ocv_find_openexr("-${OPENEXR_VERSION}")
ocv_find_openexr("-${OPENEXR_VERSION}_s")
ocv_find_openexr("-${OPENEXR_VERSION}_d")
ocv_find_openexr("-${OPEXEXR_VERSION}_s_d")
ocv_find_openexr("")
ocv_find_openexr("_s")
ocv_find_openexr("_d")
ocv_find_openexr("_s_d")
IF (OPENEXR_FOUND)
BREAK()

View File

@ -540,7 +540,7 @@ macro(ocv_check_flag_support lang flag varname base_options)
string(TOUPPER "${flag}" ${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})
endmacro()

View File

@ -213,7 +213,7 @@ Regular integers:
|min, max | x | x | x | x | x | x |
|absdiff | x | x | x | x | x | x |
|absdiffs | | x | | x | | |
|reduce | | | | | x | x |
|reduce | x | x | x | x | x | x |
|mask | x | x | x | x | x | x |
|pack | x | x | x | x | x | x |
|pack_u | x | | x | | | |
@ -670,7 +670,7 @@ Scheme:
@code
{A1 A2 A3 ...} => min(A1,A2,A3,...)
@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)
/** @brief Find one max value
@ -679,7 +679,7 @@ Scheme:
@code
{A1 A2 A3 ...} => max(A1,A2,A3,...)
@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)
static const unsigned char popCountTable[] =
@ -1219,7 +1219,7 @@ Scheme:
@code
{A1 A2 A3 ...} => sum{A1,A2,A3,...}
@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)
{
typename V_TypeTraits<_Tp>::sum_type c = a.s[0];

View File

@ -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, 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) \
inline scalartype v_reduce_sum(const _Tpvec& a) \
{ \

View File

@ -1241,6 +1241,20 @@ inline int v_reduce_sum(const v_int16x8& a)
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) \
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); \
}
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, unsigned int, 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, int, min, min, s16)
OPENCV_HAL_IMPL_NEON_REDUCE_OP_8(v_uint16x8, uint16x4, ushort, max, max, 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, short, max, max, 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) \
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)
{
typedef uint64 CV_DECL_ALIGNED(1) unaligned_uint64;
uint64 CV_DECL_ALIGNED(32) elems[2] =
{
*(uint64*)(tab + idx[0]),
*(uint64*)(tab + idx[1])
*(unaligned_uint64*)(tab + idx[0]),
*(unaligned_uint64*)(tab + idx[1])
};
return v_float32x4(vreinterpretq_f32_u64(vld1q_u64(elems)));
}

View File

@ -71,33 +71,759 @@ minMaxIdx_( const T* src, const uchar* mask, WT* _minVal, WT* _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,
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,
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,
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,
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,
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,
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,
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);

View File

@ -894,13 +894,18 @@ template<typename R> struct TheTest
TheTest & test_reduce()
{
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;
EXPECT_EQ((LaneType)1, v_reduce_min(a));
EXPECT_EQ((LaneType)R::nlanes, v_reduce_max(a));
EXPECT_EQ((LaneType)((1 + R::nlanes)*R::nlanes/2), v_reduce_sum(a));
EXPECT_EQ((LaneType)1, (LaneType)v_reduce_min(a));
EXPECT_EQ((LaneType)(R::nlanes), (LaneType)v_reduce_max(a));
EXPECT_EQ((int)(sum), (int)v_reduce_sum(a));
dataA[0] += R::nlanes;
R an = dataA;
EXPECT_EQ((LaneType)2, v_reduce_min(an));
EXPECT_EQ((LaneType)2, (LaneType)v_reduce_min(an));
return *this;
}
@ -1588,6 +1593,7 @@ void test_hal_intrin_uint8()
.test_dotprod_expand()
.test_min_max()
.test_absdiff()
.test_reduce()
.test_reduce_sad()
.test_mask()
.test_popcount()
@ -1629,6 +1635,7 @@ void test_hal_intrin_int8()
.test_absdiff()
.test_absdiffs()
.test_abs()
.test_reduce()
.test_reduce_sad()
.test_mask()
.test_popcount()

View File

@ -86,7 +86,7 @@ CV__DNN_INLINE_NS_BEGIN
*/
enum Target
{
DNN_TARGET_CPU,
DNN_TARGET_CPU = 0,
DNN_TARGET_OPENCL,
DNN_TARGET_OPENCL_FP16,
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<Target> getAvailableTargets(Backend be);
CV_EXPORTS_W std::vector<Target> getAvailableTargets(dnn::Backend be);
/** @brief This class provides all data needed to initialize layer.
*

View File

@ -36,6 +36,14 @@
"v_type": "vector_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": {
"j_type": "DictValue",
"jn_type": "long",

View File

@ -60,6 +60,25 @@ jobject vector_Ptr_Layer_to_List(JNIEnv* env, std::vector<cv::Ptr<cv::dnn::Layer
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)
{
static jclass juArrayList = ARRAYLIST(env);

View File

@ -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);
jobject vector_Target_to_List(JNIEnv* env, std::vector<cv::dnn::Target>& vs);
#endif /* DNN_CONVERTERS_HPP */

View File

@ -141,4 +141,9 @@ public class DnnTensorFlowTest extends OpenCVTestCase {
net = Dnn.readNetFromTensorflow(new MatOfByte(modelBuffer));
checkInceptionNet(net);
}
public void testGetAvailableTargets() {
List<Integer> targets = Dnn.getAvailableTargets(Dnn.DNN_BACKEND_OPENCV);
assertTrue(targets.contains(Dnn.DNN_TARGET_CPU));
}
}

View File

@ -71,6 +71,12 @@ PyObject* pyopencv_from(const dnn::LayerParams& lp)
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
{
public:

View File

@ -117,6 +117,10 @@ class dnn_test(NewOpenCVTests):
return False
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):
np.random.seed(324)

View File

@ -556,6 +556,7 @@ namespace cv {
{
int kernel_size = getParam<int>(layer_params, "size", -1);
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 filters = getParam<int>(layer_params, "filters", -1);
bool batch_normalize = getParam<int>(layer_params, "batch_normalize", 0) == 1;
@ -563,13 +564,13 @@ namespace cv {
if (flipped == 1)
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 (kernel_size < 3) pad = 0;
if (pad)
padding = kernel_size / 2;
CV_Assert(kernel_size > 0 && filters > 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);
current_channels = filters;

View File

@ -109,7 +109,7 @@ public:
#ifdef HAVE_INF_ENGINE
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
const std::vector<std::string> devices = getCore().GetAvailableDevices();
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)
{
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)
{
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]));
}
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());
throw;
}

View File

@ -323,7 +323,14 @@ void InfEngineNgraphNet::initPlugin(InferenceEngine::CNNNetwork& net)
}
// Some of networks can work without a library of extra layers.
// OpenCV fallbacks as extensions.
ie.AddExtension(std::make_shared<InfEngineExtension>(), "CPU");
try
{
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
// Limit the number of CPU threads.
if (device_name == "CPU")

View File

@ -103,7 +103,7 @@ public:
return bias == (int)bias;
}
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) {
return type == CHANNEL_NRM && bias == (int)bias;
return bias == (int)bias;
}
return backendId == DNN_BACKEND_OPENCV ||
backendId == DNN_BACKEND_CUDA ||
@ -471,7 +471,15 @@ public:
alphaSize *= (type == SPATIAL_NRM ? size*size : size);
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));
}
#endif // HAVE_DNN_NGRAPH

View File

@ -119,8 +119,10 @@ public:
virtual bool supportBackend(int backendId) CV_OVERRIDE
{
#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);
else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
return true;
else
#endif // HAVE_INF_ENGINE
return backendId == DNN_BACKEND_OPENCV;

View File

@ -98,7 +98,7 @@ private:
class SoftMaxSubgraph : public Subgraph
{
public:
SoftMaxSubgraph()
SoftMaxSubgraph() : axis(1)
{
int input = addNodeToMatch("");
int inpExp = addNodeToMatch("Exp", input);

View File

@ -147,8 +147,18 @@ Mat getMatFromTensor(opencv_onnx::TensorProto& tensor_proto)
}
else
{
char* val = const_cast<char*>(tensor_proto.raw_data().c_str());
int64_t* src = reinterpret_cast<int64_t*>(val);
const char* val = tensor_proto.raw_data().c_str();
// 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());
}
}

View File

@ -574,7 +574,7 @@ InferenceEngine::Core& getCore()
#if !defined(OPENCV_DNN_IE_VPU_TYPE_DEFAULT)
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
InferenceEngine::Core& ie = getCore();
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.
#if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2019R1)
// OpenCV fallbacks as extensions.
ie.AddExtension(std::make_shared<InfEngineExtension>(), "CPU");
try
{
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
#ifndef _WIN32
// Limit the number of CPU threads.
@ -1068,8 +1075,14 @@ void resetMyriadDevice()
#if INF_ENGINE_VER_MAJOR_LE(INF_ENGINE_RELEASE_2019R1)
getSharedPlugins().erase("MYRIAD");
#else
// To unregister both "MYRIAD" and "HETERO:MYRIAD,CPU" plugins
getCore() = InferenceEngine::Core();
// Unregister both "MYRIAD" and "HETERO:MYRIAD,CPU" plugins
InferenceEngine::Core& ie = getCore();
try
{
ie.UnregisterPlugin("MYRIAD");
ie.UnregisterPlugin("HETERO");
}
catch (...) {}
#endif
#endif // HAVE_INF_ENGINE
}

View File

@ -106,7 +106,7 @@ public:
std::string cfg = findDataFile("dnn/darknet/" + name + ".cfg");
std::string model = "";
if (hasWeights)
model = findDataFile("dnn/darknet/" + name + ".weights", false);
model = findDataFile("dnn/darknet/" + name + ".weights");
checkBackend(&inp, &ref);
@ -554,6 +554,15 @@ TEST_P(Test_Darknet_layers, 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());
}} // namespace

View File

@ -419,12 +419,12 @@ imread_( const String& filename, int flags, Mat& mat )
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;
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
@ -738,6 +738,20 @@ imdecode_( const Mat& buf, int flags, Mat& mat )
if( !decoder )
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) )
{
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;
}
decoder.release();
if (!filename.empty())
{
if (0 != remove(filename.c_str()))
@ -831,6 +845,11 @@ imdecode_( const Mat& buf, int flags, Mat& mat )
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;
}

View File

@ -8,4 +8,68 @@
#include "opencv2/imgcodecs.hpp"
#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

View File

@ -5,6 +5,95 @@
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)
{
const size_t IMAGE_COUNT = 10;

View File

@ -1526,7 +1526,7 @@ struct HResizeLinearVec_X4
struct HResizeLinearVecU8_X4
{
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;
@ -1612,17 +1612,11 @@ struct HResizeLinearVecU8_X4
}
else if(cn == 3)
{
int len0 = xmax - cn;
/* This may need to trim 1 or more extra units depending on the amount of
scaling. Test until we find the first value which we know cannot overrun. */
while (len0 >= 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);
/* 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
final valid offset. xofs[] is constucted to be an array of increasingly
large offsets (i.e xofs[x] <= xofs[x+1] for x < xmax). */
int smax = xofs[dmax-cn];
for( ; k <= (count - 2); k+=2 )
{
@ -1631,7 +1625,7 @@ struct HResizeLinearVecU8_X4
const uchar *S1 = src[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_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];
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_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)
{

View File

@ -51,8 +51,8 @@ static Mat checkMask(InputArray _mask, Size size)
{
Mat mask = _mask.getMat();
Mat gray;
if (mask.channels() == 3)
cvtColor(mask, gray, COLOR_BGR2GRAY);
if (mask.channels() > 1)
cvtColor(mask, gray, COLOR_BGRA2GRAY);
else
{
if (mask.empty())

View File

@ -1008,10 +1008,10 @@ static std::string findData(const std::string& relative_path, bool required, boo
CHECK_FILE_WITH_PREFIX(prefix, result_);
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);
if (checkOptionalFlag)
{
std::cout << "TEST ERROR: Don't use 'optional' findData() for " << relative_path << std::endl;
CV_Assert(required || result_.empty());
}
}