diff --git a/cmake/OpenCVFindIPP.cmake b/cmake/OpenCVFindIPP.cmake index 79555f60d9..59cd497b95 100644 --- a/cmake/OpenCVFindIPP.cmake +++ b/cmake/OpenCVFindIPP.cmake @@ -148,7 +148,7 @@ macro(ipp_detect_version) IMPORTED_LOCATION ${IPP_LIBRARY_DIR}/${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX} ) list(APPEND IPP_LIBRARIES ipp${name}) - if (NOT BUILD_SHARED_LIBS) + if (NOT BUILD_SHARED_LIBS AND (HAVE_IPP_ICV OR ";${OPENCV_INSTALL_EXTERNAL_DEPENDENCIES};" MATCHES ";ipp;")) # CMake doesn't support "install(TARGETS ${IPP_PREFIX}${name} " command with imported targets install(FILES ${IPP_LIBRARY_DIR}/${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX} DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) diff --git a/cmake/OpenCVFindIPPIW.cmake b/cmake/OpenCVFindIPPIW.cmake index 5c3d8a0ea2..1e065e10f6 100644 --- a/cmake/OpenCVFindIPPIW.cmake +++ b/cmake/OpenCVFindIPPIW.cmake @@ -108,12 +108,13 @@ macro(ippiw_setup PATH BUILD) message(STATUS "found Intel IPP Integration Wrappers binaries: ${IW_VERSION_MAJOR}.${IW_VERSION_MINOR}.${IW_VERSION_UPDATE}") message(STATUS "at: ${IPP_IW_PATH}") - add_library(ippiw STATIC IMPORTED) - set_target_properties(ippiw PROPERTIES + add_library(ipp_iw STATIC IMPORTED) + set_target_properties(ipp_iw PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES "" IMPORTED_LOCATION "${FILE}" ) - if (NOT BUILD_SHARED_LIBS) + + if (NOT BUILD_SHARED_LIBS AND ";${OPENCV_INSTALL_EXTERNAL_DEPENDENCIES};" MATCHES ";ipp;") # CMake doesn't support "install(TARGETS ${name} ...)" command with imported targets install(FILES "${FILE}" DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) @@ -122,7 +123,7 @@ macro(ippiw_setup PATH BUILD) endif() set(IPP_IW_INCLUDES "${IPP_IW_PATH}/include") - set(IPP_IW_LIBRARIES ippiw) + set(IPP_IW_LIBRARIES ipp_iw) set(HAVE_IPP_IW 1) set(BUILD_IPP_IW 0) diff --git a/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown b/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown index e7f2ffaec8..7d7788e1a3 100644 --- a/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown +++ b/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown @@ -43,7 +43,7 @@ There are multiple ways in which this model can be modified so it takes into acc misclassification errors. For example, one could think of minimizing the same quantity plus a constant times the number of misclassification errors in the training data, i.e.: -\f[\min ||\beta||^{2} + C \text{(\# misclassication errors)}\f] +\f[\min ||\beta||^{2} + C \text{(misclassification errors)}\f] However, this one is not a very good solution since, among some other reasons, we do not distinguish between samples that are misclassified with a small distance to their appropriate decision region or diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d.hpp index 63e82fdd28..0dd88ed441 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d.hpp @@ -1994,7 +1994,7 @@ Optionally, it computes the essential matrix E: where \f$T_i\f$ are components of the translation vector \f$T\f$ : \f$T=[T_0, T_1, T_2]^T\f$ . And the function can also compute the fundamental matrix F: -\f[F = cameraMatrix2^{-T} E cameraMatrix1^{-1}\f] +\f[F = cameraMatrix2^{-T}\cdot E \cdot cameraMatrix1^{-1}\f] Besides the stereo-related information, the function can also perform a full calibration of each of the two cameras. However, due to the high dimensionality of the parameter space and noise in the diff --git a/modules/core/include/opencv2/core/hal/intrin_avx.hpp b/modules/core/include/opencv2/core/hal/intrin_avx.hpp index ca315ae284..c977dbd5bc 100644 --- a/modules/core/include/opencv2/core/hal/intrin_avx.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_avx.hpp @@ -159,7 +159,8 @@ struct v_uint8x32 (char)v22, (char)v23, (char)v24, (char)v25, (char)v26, (char)v27, (char)v28, (char)v29, (char)v30, (char)v31); } - v_uint8x32() : val(_mm256_setzero_si256()) {} + v_uint8x32() {} + uchar get0() const { return (uchar)_v_cvtsi256_si32(val); } }; @@ -183,7 +184,8 @@ struct v_int8x32 v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31); } - v_int8x32() : val(_mm256_setzero_si256()) {} + v_int8x32() {} + schar get0() const { return (schar)_v_cvtsi256_si32(val); } }; @@ -203,7 +205,8 @@ struct v_uint16x16 (short)v4, (short)v5, (short)v6, (short)v7, (short)v8, (short)v9, (short)v10, (short)v11, (short)v12, (short)v13, (short)v14, (short)v15); } - v_uint16x16() : val(_mm256_setzero_si256()) {} + v_uint16x16() {} + ushort get0() const { return (ushort)_v_cvtsi256_si32(val); } }; @@ -222,7 +225,8 @@ struct v_int16x16 val = _mm256_setr_epi16(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15); } - v_int16x16() : val(_mm256_setzero_si256()) {} + v_int16x16() {} + short get0() const { return (short)_v_cvtsi256_si32(val); } }; @@ -239,7 +243,8 @@ struct v_uint32x8 val = _mm256_setr_epi32((unsigned)v0, (unsigned)v1, (unsigned)v2, (unsigned)v3, (unsigned)v4, (unsigned)v5, (unsigned)v6, (unsigned)v7); } - v_uint32x8() : val(_mm256_setzero_si256()) {} + v_uint32x8() {} + unsigned get0() const { return (unsigned)_v_cvtsi256_si32(val); } }; @@ -255,7 +260,8 @@ struct v_int32x8 { val = _mm256_setr_epi32(v0, v1, v2, v3, v4, v5, v6, v7); } - v_int32x8() : val(_mm256_setzero_si256()) {} + v_int32x8() {} + int get0() const { return _v_cvtsi256_si32(val); } }; @@ -271,7 +277,8 @@ struct v_float32x8 { val = _mm256_setr_ps(v0, v1, v2, v3, v4, v5, v6, v7); } - v_float32x8() : val(_mm256_setzero_ps()) {} + v_float32x8() {} + float get0() const { return _mm_cvtss_f32(_mm256_castps256_ps128(val)); } }; @@ -284,7 +291,7 @@ struct v_uint64x4 explicit v_uint64x4(__m256i v) : val(v) {} v_uint64x4(uint64 v0, uint64 v1, uint64 v2, uint64 v3) { val = _mm256_setr_epi64x((int64)v0, (int64)v1, (int64)v2, (int64)v3); } - v_uint64x4() : val(_mm256_setzero_si256()) {} + v_uint64x4() {} uint64 get0() const { #if defined __x86_64__ || defined _M_X64 @@ -306,7 +313,7 @@ struct v_int64x4 explicit v_int64x4(__m256i v) : val(v) {} v_int64x4(int64 v0, int64 v1, int64 v2, int64 v3) { val = _mm256_setr_epi64x(v0, v1, v2, v3); } - v_int64x4() : val(_mm256_setzero_si256()) {} + v_int64x4() {} int64 get0() const { @@ -329,7 +336,8 @@ struct v_float64x4 explicit v_float64x4(__m256d v) : val(v) {} v_float64x4(double v0, double v1, double v2, double v3) { val = _mm256_setr_pd(v0, v1, v2, v3); } - v_float64x4() : val(_mm256_setzero_pd()) {} + v_float64x4() {} + double get0() const { return _mm_cvtsd_f64(_mm256_castpd256_pd128(val)); } }; diff --git a/modules/core/include/opencv2/core/hal/intrin_avx512.hpp b/modules/core/include/opencv2/core/hal/intrin_avx512.hpp index e189582daa..75a3bd4b85 100644 --- a/modules/core/include/opencv2/core/hal/intrin_avx512.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_avx512.hpp @@ -144,7 +144,10 @@ struct v_uint8x64 v31, v30, v29, v28, v27, v26, v25, v24, v23, v22, v21, v20, v19, v18, v17, v16, v15, v14, v13, v12, v11, v10, v9, v8, v7, v6, v5, v4, v3, v2, v1, v0); } - v_uint8x64() : val(_mm512_setzero_si512()) {} + v_uint8x64() {} + + static inline v_uint8x64 zero() { return v_uint8x64(_mm512_setzero_si512()); } + uchar get0() const { return (uchar)_v_cvtsi512_si32(val); } }; @@ -177,7 +180,10 @@ struct v_int8x64 v31, v30, v29, v28, v27, v26, v25, v24, v23, v22, v21, v20, v19, v18, v17, v16, v15, v14, v13, v12, v11, v10, v9, v8, v7, v6, v5, v4, v3, v2, v1, v0); } - v_int8x64() : val(_mm512_setzero_si512()) {} + v_int8x64() {} + + static inline v_int8x64 zero() { return v_int8x64(_mm512_setzero_si512()); } + schar get0() const { return (schar)_v_cvtsi512_si32(val); } }; @@ -200,7 +206,10 @@ struct v_uint16x32 val = _v512_set_epu16(v31, v30, v29, v28, v27, v26, v25, v24, v23, v22, v21, v20, v19, v18, v17, v16, v15, v14, v13, v12, v11, v10, v9, v8, v7, v6, v5, v4, v3, v2, v1, v0); } - v_uint16x32() : val(_mm512_setzero_si512()) {} + v_uint16x32() {} + + static inline v_uint16x32 zero() { return v_uint16x32(_mm512_setzero_si512()); } + ushort get0() const { return (ushort)_v_cvtsi512_si32(val); } }; @@ -221,7 +230,10 @@ struct v_int16x32 (ushort)v15, (ushort)v14, (ushort)v13, (ushort)v12, (ushort)v11, (ushort)v10, (ushort)v9 , (ushort)v8, (ushort)v7 , (ushort)v6 , (ushort)v5 , (ushort)v4 , (ushort)v3 , (ushort)v2 , (ushort)v1 , (ushort)v0); } - v_int16x32() : val(_mm512_setzero_si512()) {} + v_int16x32() {} + + static inline v_int16x32 zero() { return v_int16x32(_mm512_setzero_si512()); } + short get0() const { return (short)_v_cvtsi512_si32(val); } }; @@ -240,7 +252,10 @@ struct v_uint32x16 val = _mm512_setr_epi32((int)v0, (int)v1, (int)v2, (int)v3, (int)v4, (int)v5, (int)v6, (int)v7, (int)v8, (int)v9, (int)v10, (int)v11, (int)v12, (int)v13, (int)v14, (int)v15); } - v_uint32x16() : val(_mm512_setzero_si512()) {} + v_uint32x16() {} + + static inline v_uint32x16 zero() { return v_uint32x16(_mm512_setzero_si512()); } + unsigned get0() const { return (unsigned)_v_cvtsi512_si32(val); } }; @@ -256,7 +271,10 @@ struct v_int32x16 { val = _mm512_setr_epi32(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15); } - v_int32x16() : val(_mm512_setzero_si512()) {} + v_int32x16() {} + + static inline v_int32x16 zero() { return v_int32x16(_mm512_setzero_si512()); } + int get0() const { return _v_cvtsi512_si32(val); } }; @@ -272,7 +290,10 @@ struct v_float32x16 { val = _mm512_setr_ps(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15); } - v_float32x16() : val(_mm512_setzero_ps()) {} + v_float32x16() {} + + static inline v_float32x16 zero() { return v_float32x16(_mm512_setzero_ps()); } + float get0() const { return _mm_cvtss_f32(_mm512_castps512_ps128(val)); } }; @@ -285,7 +306,10 @@ struct v_uint64x8 explicit v_uint64x8(__m512i v) : val(v) {} v_uint64x8(uint64 v0, uint64 v1, uint64 v2, uint64 v3, uint64 v4, uint64 v5, uint64 v6, uint64 v7) { val = _mm512_setr_epi64((int64)v0, (int64)v1, (int64)v2, (int64)v3, (int64)v4, (int64)v5, (int64)v6, (int64)v7); } - v_uint64x8() : val(_mm512_setzero_si512()) {} + v_uint64x8() {} + + static inline v_uint64x8 zero() { return v_uint64x8(_mm512_setzero_si512()); } + uint64 get0() const { #if defined __x86_64__ || defined _M_X64 @@ -307,7 +331,9 @@ struct v_int64x8 explicit v_int64x8(__m512i v) : val(v) {} v_int64x8(int64 v0, int64 v1, int64 v2, int64 v3, int64 v4, int64 v5, int64 v6, int64 v7) { val = _mm512_setr_epi64(v0, v1, v2, v3, v4, v5, v6, v7); } - v_int64x8() : val(_mm512_setzero_si512()) {} + v_int64x8() {} + + static inline v_int64x8 zero() { return v_int64x8(_mm512_setzero_si512()); } int64 get0() const { @@ -330,7 +356,10 @@ struct v_float64x8 explicit v_float64x8(__m512d v) : val(v) {} v_float64x8(double v0, double v1, double v2, double v3, double v4, double v5, double v6, double v7) { val = _mm512_setr_pd(v0, v1, v2, v3, v4, v5, v6, v7); } - v_float64x8() : val(_mm512_setzero_pd()) {} + v_float64x8() {} + + static inline v_float64x8 zero() { return v_float64x8(_mm512_setzero_pd()); } + double get0() const { return _mm_cvtsd_f64(_mm512_castpd512_pd128(val)); } }; @@ -1030,7 +1059,7 @@ inline _Tpvec v_rotate_left(const _Tpvec& a, const _Tpvec& b) enum { MASK = ((1 << _Tpvec::nlanes) - 1) }; \ if (imm == 0) return a; \ if (imm == _Tpvec::nlanes) return b; \ - if (imm >= 2*_Tpvec::nlanes) return _Tpvec(); \ + if (imm >= 2*_Tpvec::nlanes) return _Tpvec::zero(); \ return _Tpvec(_mm512_mask_expand_##suffix(_mm512_maskz_compress_##suffix((MASK << SHIFT2)&MASK, b.val), (MASK << (imm))&MASK, a.val)); \ } \ template \ @@ -1040,21 +1069,21 @@ inline _Tpvec v_rotate_right(const _Tpvec& a, const _Tpvec& b) enum { MASK = ((1 << _Tpvec::nlanes) - 1) }; \ if (imm == 0) return a; \ if (imm == _Tpvec::nlanes) return b; \ - if (imm >= 2*_Tpvec::nlanes) return _Tpvec(); \ + if (imm >= 2*_Tpvec::nlanes) return _Tpvec::zero(); \ return _Tpvec(_mm512_mask_expand_##suffix(_mm512_maskz_compress_##suffix((MASK << (imm))&MASK, a.val), (MASK << SHIFT2)&MASK, b.val)); \ } \ template \ inline _Tpvec v_rotate_left(const _Tpvec& a) \ { \ if (imm == 0) return a; \ - if (imm >= _Tpvec::nlanes) return _Tpvec(); \ + if (imm >= _Tpvec::nlanes) return _Tpvec::zero(); \ return _Tpvec(_mm512_maskz_expand_##suffix((1 << _Tpvec::nlanes) - (1 << (imm)), a.val)); \ } \ template \ inline _Tpvec v_rotate_right(const _Tpvec& a) \ { \ if (imm == 0) return a; \ - if (imm >= _Tpvec::nlanes) return _Tpvec(); \ + if (imm >= _Tpvec::nlanes) return _Tpvec::zero(); \ return _Tpvec(_mm512_maskz_compress_##suffix((1 << _Tpvec::nlanes) - (1 << (imm)), a.val)); \ } diff --git a/modules/core/include/opencv2/core/hal/intrin_msa.hpp b/modules/core/include/opencv2/core/hal/intrin_msa.hpp index 260350c6aa..a1fbb093a8 100644 --- a/modules/core/include/opencv2/core/hal/intrin_msa.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_msa.hpp @@ -25,7 +25,7 @@ struct v_uint8x16 typedef uchar lane_type; enum { nlanes = 16 }; - v_uint8x16() : val(msa_dupq_n_u8(0)) {} + v_uint8x16() {} explicit v_uint8x16(v16u8 v) : val(v) {} v_uint8x16(uchar v0, uchar v1, uchar v2, uchar v3, uchar v4, uchar v5, uchar v6, uchar v7, uchar v8, uchar v9, uchar v10, uchar v11, uchar v12, uchar v13, uchar v14, uchar v15) @@ -33,6 +33,7 @@ struct v_uint8x16 uchar v[] = {v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15}; val = msa_ld1q_u8(v); } + uchar get0() const { return msa_getq_lane_u8(val, 0); @@ -46,7 +47,7 @@ struct v_int8x16 typedef schar lane_type; enum { nlanes = 16 }; - v_int8x16() : val(msa_dupq_n_s8(0)) {} + v_int8x16() {} explicit v_int8x16(v16i8 v) : val(v) {} v_int8x16(schar v0, schar v1, schar v2, schar v3, schar v4, schar v5, schar v6, schar v7, schar v8, schar v9, schar v10, schar v11, schar v12, schar v13, schar v14, schar v15) @@ -54,6 +55,7 @@ struct v_int8x16 schar v[] = {v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15}; val = msa_ld1q_s8(v); } + schar get0() const { return msa_getq_lane_s8(val, 0); @@ -67,13 +69,14 @@ struct v_uint16x8 typedef ushort lane_type; enum { nlanes = 8 }; - v_uint16x8() : val(msa_dupq_n_u16(0)) {} + v_uint16x8() {} explicit v_uint16x8(v8u16 v) : val(v) {} v_uint16x8(ushort v0, ushort v1, ushort v2, ushort v3, ushort v4, ushort v5, ushort v6, ushort v7) { ushort v[] = {v0, v1, v2, v3, v4, v5, v6, v7}; val = msa_ld1q_u16(v); } + ushort get0() const { return msa_getq_lane_u16(val, 0); @@ -87,13 +90,14 @@ struct v_int16x8 typedef short lane_type; enum { nlanes = 8 }; - v_int16x8() : val(msa_dupq_n_s16(0)) {} + v_int16x8() {} explicit v_int16x8(v8i16 v) : val(v) {} v_int16x8(short v0, short v1, short v2, short v3, short v4, short v5, short v6, short v7) { short v[] = {v0, v1, v2, v3, v4, v5, v6, v7}; val = msa_ld1q_s16(v); } + short get0() const { return msa_getq_lane_s16(val, 0); @@ -107,13 +111,14 @@ struct v_uint32x4 typedef unsigned int lane_type; enum { nlanes = 4 }; - v_uint32x4() : val(msa_dupq_n_u32(0)) {} + v_uint32x4() {} explicit v_uint32x4(v4u32 v) : val(v) {} v_uint32x4(unsigned int v0, unsigned int v1, unsigned int v2, unsigned int v3) { unsigned int v[] = {v0, v1, v2, v3}; val = msa_ld1q_u32(v); } + unsigned int get0() const { return msa_getq_lane_u32(val, 0); @@ -127,17 +132,19 @@ struct v_int32x4 typedef int lane_type; enum { nlanes = 4 }; - v_int32x4() : val(msa_dupq_n_s32(0)) {} + v_int32x4() {} explicit v_int32x4(v4i32 v) : val(v) {} v_int32x4(int v0, int v1, int v2, int v3) { int v[] = {v0, v1, v2, v3}; val = msa_ld1q_s32(v); } + int get0() const { return msa_getq_lane_s32(val, 0); } + v4i32 val; }; @@ -146,17 +153,19 @@ struct v_float32x4 typedef float lane_type; enum { nlanes = 4 }; - v_float32x4() : val(msa_dupq_n_f32(0.0f)) {} + v_float32x4() {} explicit v_float32x4(v4f32 v) : val(v) {} v_float32x4(float v0, float v1, float v2, float v3) { float v[] = {v0, v1, v2, v3}; val = msa_ld1q_f32(v); } + float get0() const { return msa_getq_lane_f32(val, 0); } + v4f32 val; }; @@ -165,17 +174,19 @@ struct v_uint64x2 typedef uint64 lane_type; enum { nlanes = 2 }; - v_uint64x2() : val(msa_dupq_n_u64(0)) {} + v_uint64x2() {} explicit v_uint64x2(v2u64 v) : val(v) {} v_uint64x2(uint64 v0, uint64 v1) { uint64 v[] = {v0, v1}; val = msa_ld1q_u64(v); } + uint64 get0() const { return msa_getq_lane_u64(val, 0); } + v2u64 val; }; @@ -184,17 +195,19 @@ struct v_int64x2 typedef int64 lane_type; enum { nlanes = 2 }; - v_int64x2() : val(msa_dupq_n_s64(0)) {} + v_int64x2() {} explicit v_int64x2(v2i64 v) : val(v) {} v_int64x2(int64 v0, int64 v1) { int64 v[] = {v0, v1}; val = msa_ld1q_s64(v); } + int64 get0() const { return msa_getq_lane_s64(val, 0); } + v2i64 val; }; @@ -203,17 +216,19 @@ struct v_float64x2 typedef double lane_type; enum { nlanes = 2 }; - v_float64x2() : val(msa_dupq_n_f64(0.0f)) {} + v_float64x2() {} explicit v_float64x2(v2f64 v) : val(v) {} v_float64x2(double v0, double v1) { double v[] = {v0, v1}; val = msa_ld1q_f64(v); } + double get0() const { return msa_getq_lane_f64(val, 0); } + v2f64 val; }; diff --git a/modules/core/include/opencv2/core/hal/intrin_sse.hpp b/modules/core/include/opencv2/core/hal/intrin_sse.hpp index 867ff55340..e42e4e0936 100644 --- a/modules/core/include/opencv2/core/hal/intrin_sse.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_sse.hpp @@ -75,7 +75,7 @@ struct v_uint8x16 typedef __m128i vector_type; enum { nlanes = 16 }; - v_uint8x16() : val(_mm_setzero_si128()) {} + v_uint8x16() {} explicit v_uint8x16(__m128i v) : val(v) {} v_uint8x16(uchar v0, uchar v1, uchar v2, uchar v3, uchar v4, uchar v5, uchar v6, uchar v7, uchar v8, uchar v9, uchar v10, uchar v11, uchar v12, uchar v13, uchar v14, uchar v15) @@ -85,6 +85,7 @@ struct v_uint8x16 (char)v8, (char)v9, (char)v10, (char)v11, (char)v12, (char)v13, (char)v14, (char)v15); } + uchar get0() const { return (uchar)_mm_cvtsi128_si32(val); @@ -99,7 +100,7 @@ struct v_int8x16 typedef __m128i vector_type; enum { nlanes = 16 }; - v_int8x16() : val(_mm_setzero_si128()) {} + v_int8x16() {} explicit v_int8x16(__m128i v) : val(v) {} v_int8x16(schar v0, schar v1, schar v2, schar v3, schar v4, schar v5, schar v6, schar v7, schar v8, schar v9, schar v10, schar v11, schar v12, schar v13, schar v14, schar v15) @@ -109,6 +110,7 @@ struct v_int8x16 (char)v8, (char)v9, (char)v10, (char)v11, (char)v12, (char)v13, (char)v14, (char)v15); } + schar get0() const { return (schar)_mm_cvtsi128_si32(val); @@ -123,13 +125,14 @@ struct v_uint16x8 typedef __m128i vector_type; enum { nlanes = 8 }; - v_uint16x8() : val(_mm_setzero_si128()) {} + v_uint16x8() {} explicit v_uint16x8(__m128i v) : val(v) {} v_uint16x8(ushort v0, ushort v1, ushort v2, ushort v3, ushort v4, ushort v5, ushort v6, ushort v7) { val = _mm_setr_epi16((short)v0, (short)v1, (short)v2, (short)v3, (short)v4, (short)v5, (short)v6, (short)v7); } + ushort get0() const { return (ushort)_mm_cvtsi128_si32(val); @@ -144,13 +147,14 @@ struct v_int16x8 typedef __m128i vector_type; enum { nlanes = 8 }; - v_int16x8() : val(_mm_setzero_si128()) {} + v_int16x8() {} explicit v_int16x8(__m128i v) : val(v) {} v_int16x8(short v0, short v1, short v2, short v3, short v4, short v5, short v6, short v7) { val = _mm_setr_epi16((short)v0, (short)v1, (short)v2, (short)v3, (short)v4, (short)v5, (short)v6, (short)v7); } + short get0() const { return (short)_mm_cvtsi128_si32(val); @@ -165,12 +169,13 @@ struct v_uint32x4 typedef __m128i vector_type; enum { nlanes = 4 }; - v_uint32x4() : val(_mm_setzero_si128()) {} + v_uint32x4() {} explicit v_uint32x4(__m128i v) : val(v) {} v_uint32x4(unsigned v0, unsigned v1, unsigned v2, unsigned v3) { val = _mm_setr_epi32((int)v0, (int)v1, (int)v2, (int)v3); } + unsigned get0() const { return (unsigned)_mm_cvtsi128_si32(val); @@ -185,12 +190,13 @@ struct v_int32x4 typedef __m128i vector_type; enum { nlanes = 4 }; - v_int32x4() : val(_mm_setzero_si128()) {} + v_int32x4() {} explicit v_int32x4(__m128i v) : val(v) {} v_int32x4(int v0, int v1, int v2, int v3) { val = _mm_setr_epi32(v0, v1, v2, v3); } + int get0() const { return _mm_cvtsi128_si32(val); @@ -205,12 +211,13 @@ struct v_float32x4 typedef __m128 vector_type; enum { nlanes = 4 }; - v_float32x4() : val(_mm_setzero_ps()) {} + v_float32x4() {} explicit v_float32x4(__m128 v) : val(v) {} v_float32x4(float v0, float v1, float v2, float v3) { val = _mm_setr_ps(v0, v1, v2, v3); } + float get0() const { return _mm_cvtss_f32(val); @@ -225,12 +232,13 @@ struct v_uint64x2 typedef __m128i vector_type; enum { nlanes = 2 }; - v_uint64x2() : val(_mm_setzero_si128()) {} + v_uint64x2() {} explicit v_uint64x2(__m128i v) : val(v) {} v_uint64x2(uint64 v0, uint64 v1) { val = _mm_setr_epi32((int)v0, (int)(v0 >> 32), (int)v1, (int)(v1 >> 32)); } + uint64 get0() const { #if !defined(__x86_64__) && !defined(_M_X64) @@ -251,12 +259,13 @@ struct v_int64x2 typedef __m128i vector_type; enum { nlanes = 2 }; - v_int64x2() : val(_mm_setzero_si128()) {} + v_int64x2() {} explicit v_int64x2(__m128i v) : val(v) {} v_int64x2(int64 v0, int64 v1) { val = _mm_setr_epi32((int)v0, (int)(v0 >> 32), (int)v1, (int)(v1 >> 32)); } + int64 get0() const { #if !defined(__x86_64__) && !defined(_M_X64) @@ -277,12 +286,13 @@ struct v_float64x2 typedef __m128d vector_type; enum { nlanes = 2 }; - v_float64x2() : val(_mm_setzero_pd()) {} + v_float64x2() {} explicit v_float64x2(__m128d v) : val(v) {} v_float64x2(double v0, double v1) { val = _mm_setr_pd(v0, v1); } + double get0() const { return _mm_cvtsd_f64(val); diff --git a/modules/core/include/opencv2/core/hal/intrin_vsx.hpp b/modules/core/include/opencv2/core/hal/intrin_vsx.hpp index e0f6cbf635..b198643cc6 100644 --- a/modules/core/include/opencv2/core/hal/intrin_vsx.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_vsx.hpp @@ -28,7 +28,7 @@ struct v_uint8x16 explicit v_uint8x16(const vec_uchar16& v) : val(v) {} - v_uint8x16() : val(vec_uchar16_z) + v_uint8x16() {} v_uint8x16(vec_bchar16 v) : val(vec_uchar16_c(v)) {} @@ -36,6 +36,9 @@ struct v_uint8x16 uchar v8, uchar v9, uchar v10, uchar v11, uchar v12, uchar v13, uchar v14, uchar v15) : val(vec_uchar16_set(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)) {} + + static inline v_uint8x16 zero() { return v_uint8x16(vec_uchar16_z); } + uchar get0() const { return vec_extract(val, 0); } }; @@ -48,7 +51,7 @@ struct v_int8x16 explicit v_int8x16(const vec_char16& v) : val(v) {} - v_int8x16() : val(vec_char16_z) + v_int8x16() {} v_int8x16(vec_bchar16 v) : val(vec_char16_c(v)) {} @@ -56,6 +59,9 @@ struct v_int8x16 schar v8, schar v9, schar v10, schar v11, schar v12, schar v13, schar v14, schar v15) : val(vec_char16_set(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)) {} + + static inline v_int8x16 zero() { return v_int8x16(vec_char16_z); } + schar get0() const { return vec_extract(val, 0); } }; @@ -68,13 +74,16 @@ struct v_uint16x8 explicit v_uint16x8(const vec_ushort8& v) : val(v) {} - v_uint16x8() : val(vec_ushort8_z) + v_uint16x8() {} v_uint16x8(vec_bshort8 v) : val(vec_ushort8_c(v)) {} v_uint16x8(ushort v0, ushort v1, ushort v2, ushort v3, ushort v4, ushort v5, ushort v6, ushort v7) : val(vec_ushort8_set(v0, v1, v2, v3, v4, v5, v6, v7)) {} + + static inline v_uint16x8 zero() { return v_uint16x8(vec_ushort8_z); } + ushort get0() const { return vec_extract(val, 0); } }; @@ -87,13 +96,16 @@ struct v_int16x8 explicit v_int16x8(const vec_short8& v) : val(v) {} - v_int16x8() : val(vec_short8_z) + v_int16x8() {} v_int16x8(vec_bshort8 v) : val(vec_short8_c(v)) {} v_int16x8(short v0, short v1, short v2, short v3, short v4, short v5, short v6, short v7) : val(vec_short8_set(v0, v1, v2, v3, v4, v5, v6, v7)) {} + + static inline v_int16x8 zero() { return v_int16x8(vec_short8_z); } + short get0() const { return vec_extract(val, 0); } }; @@ -106,12 +118,15 @@ struct v_uint32x4 explicit v_uint32x4(const vec_uint4& v) : val(v) {} - v_uint32x4() : val(vec_uint4_z) + v_uint32x4() {} v_uint32x4(vec_bint4 v) : val(vec_uint4_c(v)) {} v_uint32x4(unsigned v0, unsigned v1, unsigned v2, unsigned v3) : val(vec_uint4_set(v0, v1, v2, v3)) {} + + static inline v_uint32x4 zero() { return v_uint32x4(vec_uint4_z); } + uint get0() const { return vec_extract(val, 0); } }; @@ -124,12 +139,15 @@ struct v_int32x4 explicit v_int32x4(const vec_int4& v) : val(v) {} - v_int32x4() : val(vec_int4_z) + v_int32x4() {} v_int32x4(vec_bint4 v) : val(vec_int4_c(v)) {} v_int32x4(int v0, int v1, int v2, int v3) : val(vec_int4_set(v0, v1, v2, v3)) {} + + static inline v_int32x4 zero() { return v_int32x4(vec_int4_z); } + int get0() const { return vec_extract(val, 0); } }; @@ -142,12 +160,15 @@ struct v_float32x4 explicit v_float32x4(const vec_float4& v) : val(v) {} - v_float32x4() : val(vec_float4_z) + v_float32x4() {} v_float32x4(vec_bint4 v) : val(vec_float4_c(v)) {} v_float32x4(float v0, float v1, float v2, float v3) : val(vec_float4_set(v0, v1, v2, v3)) {} + + static inline v_float32x4 zero() { return v_float32x4(vec_float4_z); } + float get0() const { return vec_extract(val, 0); } }; @@ -160,12 +181,15 @@ struct v_uint64x2 explicit v_uint64x2(const vec_udword2& v) : val(v) {} - v_uint64x2() : val(vec_udword2_z) + v_uint64x2() {} v_uint64x2(vec_bdword2 v) : val(vec_udword2_c(v)) {} v_uint64x2(uint64 v0, uint64 v1) : val(vec_udword2_set(v0, v1)) {} + + static inline v_uint64x2 zero() { return v_uint64x2(vec_udword2_z); } + uint64 get0() const { return vec_extract(val, 0); } }; @@ -178,12 +202,15 @@ struct v_int64x2 explicit v_int64x2(const vec_dword2& v) : val(v) {} - v_int64x2() : val(vec_dword2_z) + v_int64x2() {} v_int64x2(vec_bdword2 v) : val(vec_dword2_c(v)) {} v_int64x2(int64 v0, int64 v1) : val(vec_dword2_set(v0, v1)) {} + + static inline v_int64x2 zero() { return v_int64x2(vec_dword2_z); } + int64 get0() const { return vec_extract(val, 0); } }; @@ -196,12 +223,15 @@ struct v_float64x2 explicit v_float64x2(const vec_double2& v) : val(v) {} - v_float64x2() : val(vec_double2_z) + v_float64x2() {} v_float64x2(vec_bdword2 v) : val(vec_double2_c(v)) {} v_float64x2(double v0, double v1) : val(vec_double2_set(v0, v1)) {} + + static inline v_float64x2 zero() { return v_float64x2(vec_double2_z); } + double get0() const { return vec_extract(val, 0); } }; @@ -229,7 +259,7 @@ OPENCV_HAL_IMPL_VSX_EXTRACT_N(v_float64x2, double) * if vec_xxx_c defined as C++ cast, clang-5 will pass it */ #define OPENCV_HAL_IMPL_VSX_INITVEC(_Tpvec, _Tp, suffix, cast) \ -inline _Tpvec v_setzero_##suffix() { return _Tpvec(); } \ +inline _Tpvec v_setzero_##suffix() { return _Tpvec(vec_splats((_Tp)0)); } \ inline _Tpvec v_setall_##suffix(_Tp v) { return _Tpvec(vec_splats((_Tp)v));} \ template inline _Tpvec v_reinterpret_as_##suffix(const _Tpvec0 &a) \ { return _Tpvec((cast)a.val); } @@ -660,7 +690,7 @@ inline _Tpvec v_rotate_##suffix(const _Tpvec& a) { \ const int wd = imm * sizeof(typename _Tpvec::lane_type); \ if (wd > 15) \ - return _Tpvec(); \ + return _Tpvec::zero(); \ return _Tpvec((cast)shf(vec_uchar16_c(a.val), vec_uchar16_sp(wd << 3))); \ } @@ -973,7 +1003,7 @@ inline int v_scan_forward(const v_float64x2& a) { return trailingZeros32(v_signm template inline bool v_check_all(const _Tpvec& a) -{ return vec_all_lt(a.val, _Tpvec().val); } +{ return vec_all_lt(a.val, _Tpvec::zero().val); } inline bool v_check_all(const v_uint8x16& a) { return v_check_all(v_reinterpret_as_s8(a)); } inline bool v_check_all(const v_uint16x8& a) @@ -989,7 +1019,7 @@ inline bool v_check_all(const v_float64x2& a) template inline bool v_check_any(const _Tpvec& a) -{ return vec_any_lt(a.val, _Tpvec().val); } +{ return vec_any_lt(a.val, _Tpvec::zero().val); } inline bool v_check_any(const v_uint8x16& a) { return v_check_any(v_reinterpret_as_s8(a)); } inline bool v_check_any(const v_uint16x8& a) diff --git a/modules/core/include/opencv2/core/hal/intrin_wasm.hpp b/modules/core/include/opencv2/core/hal/intrin_wasm.hpp index b8c250fcc2..d1bfb6da6d 100644 --- a/modules/core/include/opencv2/core/hal/intrin_wasm.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_wasm.hpp @@ -41,7 +41,7 @@ struct v_uint8x16 typedef v128_t vector_type; enum { nlanes = 16 }; - v_uint8x16() : val(wasm_i8x16_splat(0)) {} + v_uint8x16() {} explicit v_uint8x16(v128_t v) : val(v) {} v_uint8x16(uchar v0, uchar v1, uchar v2, uchar v3, uchar v4, uchar v5, uchar v6, uchar v7, uchar v8, uchar v9, uchar v10, uchar v11, uchar v12, uchar v13, uchar v14, uchar v15) @@ -49,6 +49,7 @@ struct v_uint8x16 uchar v[] = {v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15}; val = wasm_v128_load(v); } + uchar get0() const { return (uchar)wasm_i8x16_extract_lane(val, 0); @@ -63,7 +64,7 @@ struct v_int8x16 typedef v128_t vector_type; enum { nlanes = 16 }; - v_int8x16() : val(wasm_i8x16_splat(0)) {} + v_int8x16() {} explicit v_int8x16(v128_t v) : val(v) {} v_int8x16(schar v0, schar v1, schar v2, schar v3, schar v4, schar v5, schar v6, schar v7, schar v8, schar v9, schar v10, schar v11, schar v12, schar v13, schar v14, schar v15) @@ -71,6 +72,7 @@ struct v_int8x16 schar v[] = {v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15}; val = wasm_v128_load(v); } + schar get0() const { return wasm_i8x16_extract_lane(val, 0); @@ -85,13 +87,14 @@ struct v_uint16x8 typedef v128_t vector_type; enum { nlanes = 8 }; - v_uint16x8() : val(wasm_i16x8_splat(0)) {} + v_uint16x8() {} explicit v_uint16x8(v128_t v) : val(v) {} v_uint16x8(ushort v0, ushort v1, ushort v2, ushort v3, ushort v4, ushort v5, ushort v6, ushort v7) { ushort v[] = {v0, v1, v2, v3, v4, v5, v6, v7}; val = wasm_v128_load(v); } + ushort get0() const { return (ushort)wasm_i16x8_extract_lane(val, 0); // wasm_u16x8_extract_lane() unimplemented yet @@ -106,13 +109,14 @@ struct v_int16x8 typedef v128_t vector_type; enum { nlanes = 8 }; - v_int16x8() : val(wasm_i16x8_splat(0)) {} + v_int16x8() {} explicit v_int16x8(v128_t v) : val(v) {} v_int16x8(short v0, short v1, short v2, short v3, short v4, short v5, short v6, short v7) { short v[] = {v0, v1, v2, v3, v4, v5, v6, v7}; val = wasm_v128_load(v); } + short get0() const { return wasm_i16x8_extract_lane(val, 0); @@ -127,13 +131,14 @@ struct v_uint32x4 typedef v128_t vector_type; enum { nlanes = 4 }; - v_uint32x4() : val(wasm_i32x4_splat(0)) {} + v_uint32x4() {} explicit v_uint32x4(v128_t v) : val(v) {} v_uint32x4(unsigned v0, unsigned v1, unsigned v2, unsigned v3) { unsigned v[] = {v0, v1, v2, v3}; val = wasm_v128_load(v); } + unsigned get0() const { return (unsigned)wasm_i32x4_extract_lane(val, 0); @@ -148,13 +153,14 @@ struct v_int32x4 typedef v128_t vector_type; enum { nlanes = 4 }; - v_int32x4() : val(wasm_i32x4_splat(0)) {} + v_int32x4() {} explicit v_int32x4(v128_t v) : val(v) {} v_int32x4(int v0, int v1, int v2, int v3) { int v[] = {v0, v1, v2, v3}; val = wasm_v128_load(v); } + int get0() const { return wasm_i32x4_extract_lane(val, 0); @@ -169,13 +175,14 @@ struct v_float32x4 typedef v128_t vector_type; enum { nlanes = 4 }; - v_float32x4() : val(wasm_f32x4_splat(0)) {} + v_float32x4() {} explicit v_float32x4(v128_t v) : val(v) {} v_float32x4(float v0, float v1, float v2, float v3) { float v[] = {v0, v1, v2, v3}; val = wasm_v128_load(v); } + float get0() const { return wasm_f32x4_extract_lane(val, 0); @@ -190,17 +197,14 @@ struct v_uint64x2 typedef v128_t vector_type; enum { nlanes = 2 }; -#ifdef __wasm_unimplemented_simd128__ - v_uint64x2() : val(wasm_i64x2_splat(0)) {} -#else - v_uint64x2() : val(wasm_i32x4_splat(0)) {} -#endif + v_uint64x2() {} explicit v_uint64x2(v128_t v) : val(v) {} v_uint64x2(uint64 v0, uint64 v1) { uint64 v[] = {v0, v1}; val = wasm_v128_load(v); } + uint64 get0() const { #ifdef __wasm_unimplemented_simd128__ @@ -221,17 +225,14 @@ struct v_int64x2 typedef v128_t vector_type; enum { nlanes = 2 }; -#ifdef __wasm_unimplemented_simd128__ - v_int64x2() : val(wasm_i64x2_splat(0)) {} -#else - v_int64x2() : val(wasm_i32x4_splat(0)) {} -#endif + v_int64x2() {} explicit v_int64x2(v128_t v) : val(v) {} v_int64x2(int64 v0, int64 v1) { int64 v[] = {v0, v1}; val = wasm_v128_load(v); } + int64 get0() const { #ifdef __wasm_unimplemented_simd128__ @@ -252,17 +253,14 @@ struct v_float64x2 typedef v128_t vector_type; enum { nlanes = 2 }; -#ifdef __wasm_unimplemented_simd128__ - v_float64x2() : val(wasm_f64x2_splat(0)) {} -#else - v_float64x2() : val(wasm_f32x4_splat(0)) {} -#endif + v_float64x2() {} explicit v_float64x2(v128_t v) : val(v) {} v_float64x2(double v0, double v1) { double v[] = {v0, v1}; val = wasm_v128_load(v); } + double get0() const { #ifdef __wasm_unimplemented_simd128__ diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index 7766463edf..73bb1d6a8b 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -170,7 +170,7 @@ public: STD_VECTOR = 3 << KIND_SHIFT, STD_VECTOR_VECTOR = 4 << KIND_SHIFT, STD_VECTOR_MAT = 5 << KIND_SHIFT, - EXPR = 6 << KIND_SHIFT, + EXPR = 6 << KIND_SHIFT, //!< removed OPENGL_BUFFER = 7 << KIND_SHIFT, CUDA_HOST_MEM = 8 << KIND_SHIFT, CUDA_GPU_MAT = 9 << KIND_SHIFT, diff --git a/modules/core/include/opencv2/core/matx.hpp b/modules/core/include/opencv2/core/matx.hpp index 6a22b1788e..45d8a97f34 100644 --- a/modules/core/include/opencv2/core/matx.hpp +++ b/modules/core/include/opencv2/core/matx.hpp @@ -147,7 +147,16 @@ public: static Matx ones(); static Matx eye(); static Matx diag(const diag_type& d); + /** @brief Generates uniformly distributed random numbers + @param a Range boundary. + @param b The other range boundary (boundaries don't have to be ordered, the lower boundary is inclusive, + the upper one is exclusive). + */ static Matx randu(_Tp a, _Tp b); + /** @brief Generates normally distributed random numbers + @param a Mean value. + @param b Standard deviation. + */ static Matx randn(_Tp a, _Tp b); //! dot product computed with the default precision diff --git a/modules/core/include/opencv2/core/utility.hpp b/modules/core/include/opencv2/core/utility.hpp index 3d2a03593f..c52abbbff4 100644 --- a/modules/core/include/opencv2/core/utility.hpp +++ b/modules/core/include/opencv2/core/utility.hpp @@ -284,107 +284,98 @@ CV_EXPORTS_W double getTickFrequency(); The class computes passing time by counting the number of ticks per second. That is, the following code computes the execution time in seconds: -@code -TickMeter tm; -tm.start(); -// do something ... -tm.stop(); -std::cout << tm.getTimeSec(); -@endcode +@snippet snippets/core_various.cpp TickMeter_total It is also possible to compute the average time over multiple runs: -@code -TickMeter tm; -for (int i = 0; i < 100; i++) -{ - tm.start(); - // do something ... - tm.stop(); -} -double average_time = tm.getTimeSec() / tm.getCounter(); -std::cout << "Average time in second per iteration is: " << average_time << std::endl; -@endcode +@snippet snippets/core_various.cpp TickMeter_average + @sa getTickCount, getTickFrequency */ - class CV_EXPORTS_W TickMeter { public: //! the default constructor CV_WRAP TickMeter() { - reset(); + reset(); } - /** - starts counting ticks. - */ + //! starts counting ticks. CV_WRAP void start() { - startTime = cv::getTickCount(); + startTime = cv::getTickCount(); } - /** - stops counting ticks. - */ + //! stops counting ticks. CV_WRAP void stop() { - int64 time = cv::getTickCount(); - if (startTime == 0) - return; - ++counter; - sumTime += (time - startTime); - startTime = 0; + int64 time = cv::getTickCount(); + if (startTime == 0) + return; + ++counter; + sumTime += (time - startTime); + startTime = 0; } - /** - returns counted ticks. - */ + //! returns counted ticks. CV_WRAP int64 getTimeTicks() const { - return sumTime; + return sumTime; } - /** - returns passed time in microseconds. - */ + //! returns passed time in microseconds. CV_WRAP double getTimeMicro() const { - return getTimeMilli()*1e3; + return getTimeMilli()*1e3; } - /** - returns passed time in milliseconds. - */ + //! returns passed time in milliseconds. CV_WRAP double getTimeMilli() const { - return getTimeSec()*1e3; + return getTimeSec()*1e3; } - /** - returns passed time in seconds. - */ + //! returns passed time in seconds. CV_WRAP double getTimeSec() const { - return (double)getTimeTicks() / getTickFrequency(); + return (double)getTimeTicks() / getTickFrequency(); } - /** - returns internal counter value. - */ + //! returns internal counter value. CV_WRAP int64 getCounter() const { - return counter; + return counter; } - /** - resets internal values. - */ + //! returns average FPS (frames per second) value. + CV_WRAP double getFPS() const + { + const double sec = getTimeSec(); + if (sec < DBL_EPSILON) + return 0.; + return counter / sec; + } + + //! returns average time in seconds + CV_WRAP double getAvgTimeSec() const + { + if (counter <= 0) + return 0.; + return getTimeSec() / counter; + } + + //! returns average time in milliseconds + CV_WRAP double getAvgTimeMilli() const + { + return getAvgTimeSec() * 1e3; + } + + //! resets internal values. CV_WRAP void reset() { - startTime = 0; - sumTime = 0; - counter = 0; + startTime = 0; + sumTime = 0; + counter = 0; } private: diff --git a/modules/core/src/matrix_expressions.cpp b/modules/core/src/matrix_expressions.cpp index d4f8b743cf..58c99ed19a 100644 --- a/modules/core/src/matrix_expressions.cpp +++ b/modules/core/src/matrix_expressions.cpp @@ -1739,13 +1739,7 @@ MatExpr Mat::mul(InputArray m, double scale) const CV_INSTRUMENT_REGION(); MatExpr e; - if(m.kind() == _InputArray::EXPR) - { - const MatExpr& me = *(const MatExpr*)m.getObj(); - me.op->multiply(MatExpr(*this), me, e, scale); - } - else - MatOp_Bin::makeExpr(e, '*', *this, m.getMat(), scale); + MatOp_Bin::makeExpr(e, '*', *this, m.getMat(), scale); return e; } @@ -1840,7 +1834,6 @@ void MatExpr::swap(MatExpr& other) _InputArray::_InputArray(const MatExpr& expr) { -#if 1 if (!isIdentity(expr)) { Mat result = expr; // TODO improve through refcount == 1 of expr.a (inplace operation is possible - except gemm?) @@ -1849,9 +1842,6 @@ _InputArray::_InputArray(const MatExpr& expr) } CV_Assert(isIdentity(expr)); init(FIXED_TYPE + FIXED_SIZE + MAT + ACCESS_READ, &expr.a); -#else - init(FIXED_TYPE + FIXED_SIZE + EXPR + ACCESS_READ, &expr); -#endif } } // cv:: diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index b129f243f2..7fe5a8e47a 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -33,12 +33,6 @@ Mat _InputArray::getMat_(int i) const return m->getMat(accessFlags).row(i); } - if( k == EXPR ) - { - CV_Assert( i < 0 ); - return (Mat)*((const MatExpr*)obj); - } - if( k == MATX || k == STD_ARRAY ) { CV_Assert( i < 0 ); @@ -179,17 +173,6 @@ void _InputArray::getMatVector(std::vector& mv) const return; } - if( k == EXPR ) - { - Mat m = *(const MatExpr*)obj; - int n = m.size[0]; - mv.resize(n); - - for( int i = 0; i < n; i++ ) - mv[i] = m.row(i); - return; - } - if( k == MATX || k == STD_ARRAY ) { size_t n = sz.height, esz = CV_ELEM_SIZE(flags); @@ -378,7 +361,9 @@ ogl::Buffer _InputArray::getOGlBuffer() const _InputArray::KindFlag _InputArray::kind() const { - return flags & KIND_MASK; + KindFlag k = flags & KIND_MASK; + CV_DbgAssert(k != EXPR); + return k; } int _InputArray::rows(int i) const @@ -401,12 +386,6 @@ Size _InputArray::size(int i) const return ((const Mat*)obj)->size(); } - if( k == EXPR ) - { - CV_Assert( i < 0 ); - return ((const MatExpr*)obj)->size(); - } - if( k == UMAT ) { CV_Assert( i < 0 ); @@ -570,7 +549,7 @@ int _InputArray::sizend(int* arrsz, int i) const } else { - CV_CheckLE(dims(i), 2, "Not supported"); // TODO Support EXPR with 3+ dims + CV_CheckLE(dims(i), 2, "Not supported"); Size sz2d = size(i); d = 2; if(arrsz) @@ -627,12 +606,6 @@ int _InputArray::dims(int i) const return ((const Mat*)obj)->dims; } - if( k == EXPR ) - { - CV_Assert( i < 0 ); - return ((const MatExpr*)obj)->a.dims; - } - if( k == UMAT ) { CV_Assert( i < 0 ); @@ -773,9 +746,6 @@ int _InputArray::type(int i) const if( k == UMAT ) return ((const UMat*)obj)->type(); - if( k == EXPR ) - return ((const MatExpr*)obj)->type(); - if( k == MATX || k == STD_VECTOR || k == STD_ARRAY || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) return CV_MAT_TYPE(flags); @@ -862,9 +832,6 @@ bool _InputArray::empty() const if( k == UMAT ) return ((const UMat*)obj)->empty(); - if( k == EXPR ) - return false; - if( k == MATX || k == STD_ARRAY ) return false; @@ -934,7 +901,7 @@ bool _InputArray::isContinuous(int i) const if( k == UMAT ) return i < 0 ? ((const UMat*)obj)->isContinuous() : true; - if( k == EXPR || k == MATX || k == STD_VECTOR || k == STD_ARRAY || + if( k == MATX || k == STD_VECTOR || k == STD_ARRAY || k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) return true; @@ -975,7 +942,7 @@ bool _InputArray::isSubmatrix(int i) const if( k == UMAT ) return i < 0 ? ((const UMat*)obj)->isSubmatrix() : false; - if( k == EXPR || k == MATX || k == STD_VECTOR || k == STD_ARRAY || + if( k == MATX || k == STD_VECTOR || k == STD_ARRAY || k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) return false; @@ -1020,7 +987,7 @@ size_t _InputArray::offset(int i) const return ((const UMat*)obj)->offset; } - if( k == EXPR || k == MATX || k == STD_VECTOR || k == STD_ARRAY || + if( k == MATX || k == STD_VECTOR || k == STD_ARRAY || k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) return 0; @@ -1083,7 +1050,7 @@ size_t _InputArray::step(int i) const return ((const UMat*)obj)->step; } - if( k == EXPR || k == MATX || k == STD_VECTOR || k == STD_ARRAY || + if( k == MATX || k == STD_VECTOR || k == STD_ARRAY || k == NONE || k == STD_VECTOR_VECTOR || k == STD_BOOL_VECTOR ) return 0; @@ -1138,14 +1105,6 @@ void _InputArray::copyTo(const _OutputArray& arr) const Mat m = getMat(); m.copyTo(arr); } - else if( k == EXPR ) - { - const MatExpr& e = *((MatExpr*)obj); - if( arr.kind() == MAT ) - arr.getMatRef() = e; - else - Mat(e).copyTo(arr); - } else if( k == UMAT ) ((UMat*)obj)->copyTo(arr); #ifdef HAVE_CUDA diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index 616422ab1d..b7294e7614 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -1757,6 +1757,7 @@ struct Net::Impl Ptr ieNode = node.dynamicCast(); CV_Assert(!ieNode.empty()); + ieNode->net->reset(); for (it = layers.begin(); it != layers.end(); ++it) { @@ -2058,6 +2059,7 @@ struct Net::Impl Ptr ieNode = node.dynamicCast(); CV_Assert(!ieNode.empty()); + ieNode->net->reset(); for (it = layers.begin(); it != layers.end(); ++it) { diff --git a/modules/dnn/src/ie_ngraph.cpp b/modules/dnn/src/ie_ngraph.cpp index e3f0966ab4..05e8205251 100644 --- a/modules/dnn/src/ie_ngraph.cpp +++ b/modules/dnn/src/ie_ngraph.cpp @@ -780,6 +780,13 @@ void forwardNgraph(const std::vector >& outBlobsWrappers, ieNode->net->forward(outBlobsWrappers, isAsync); } +void InfEngineNgraphNet::reset() +{ + allBlobs.clear(); + infRequests.clear(); + isInit = false; +} + void InfEngineNgraphNet::addBlobs(const std::vector >& ptrs) { auto wrappers = ngraphWrappers(ptrs); diff --git a/modules/dnn/src/ie_ngraph.hpp b/modules/dnn/src/ie_ngraph.hpp index 3058178cbe..efbdafa7d9 100644 --- a/modules/dnn/src/ie_ngraph.hpp +++ b/modules/dnn/src/ie_ngraph.hpp @@ -52,6 +52,8 @@ public: void createNet(Target targetId); void setNodePtr(std::shared_ptr* ptr); + + void reset(); private: void release(); int getNumComponents(); diff --git a/modules/dnn/src/layers/region_layer.cpp b/modules/dnn/src/layers/region_layer.cpp index 92112517ad..1e3efd06f4 100644 --- a/modules/dnn/src/layers/region_layer.cpp +++ b/modules/dnn/src/layers/region_layer.cpp @@ -50,11 +50,16 @@ #include "opencl_kernels_dnn.hpp" #endif +#ifdef HAVE_DNN_NGRAPH +#include "../ie_ngraph.hpp" +#endif + #ifdef HAVE_CUDA #include "../cuda4dnn/primitives/region.hpp" using namespace cv::dnn::cuda4dnn; #endif + namespace cv { namespace dnn @@ -93,12 +98,6 @@ public: CV_Error(cv::Error::StsNotImplemented, "Yolo9000 is not implemented"); } - virtual bool supportBackend(int backendId) CV_OVERRIDE - { - return backendId == DNN_BACKEND_OPENCV || - backendId == DNN_BACKEND_CUDA; - } - bool getMemoryShapes(const std::vector &inputs, const int requiredOutputs, std::vector &outputs, @@ -115,6 +114,19 @@ public: return false; } + virtual bool supportBackend(int backendId) CV_OVERRIDE + { +#ifdef HAVE_DNN_NGRAPH + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + return INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2020_2) && preferableTarget != DNN_TARGET_MYRIAD; +#endif +#ifdef HAVE_CUDA + if (backendId == DNN_BACKEND_CUDA) + return true; +#endif + return backendId == DNN_BACKEND_OPENCV; + } + float logistic_activate(float x) { return 1.F / (1.F + exp(-x)); } void softmax_activate(const float* input, const int n, const float temp, float* output) @@ -411,6 +423,202 @@ public: } return flops; } + +#ifdef HAVE_DNN_NGRAPH + virtual Ptr initNgraph(const std::vector > &inputs, + const std::vector >& nodes) CV_OVERRIDE + { + auto& input = nodes[0].dynamicCast()->node; + auto parent_shape = input->get_shape(); + int64_t b = parent_shape[0]; + int64_t h = parent_shape[1]; + int64_t w = parent_shape[2]; + int64_t c = parent_shape[3]; + + int64_t cols = b * h * w * anchors; + int64_t rows = c / anchors; + auto shape_node = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{cols, rows}); + auto tr_axes = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{1, 0}); + + std::shared_ptr input2d; + { + input2d = std::make_shared(input, shape_node, true); + input2d = std::make_shared(input2d, tr_axes); + } + + std::shared_ptr region; + { + auto new_axes = std::make_shared(ngraph::element::i64, ngraph::Shape{4}, std::vector{0, 3, 1, 2}); + auto tr_input = std::make_shared(input, new_axes); + + std::vector anchors_vec(blobs[0].ptr(), blobs[0].ptr() + blobs[0].total()); + std::vector mask(anchors, 1); + region = std::make_shared(tr_input, coords, classes, anchors, useSoftmax, mask, 1, 3, anchors_vec); + + auto shape_as_inp = std::make_shared(ngraph::element::i64, + ngraph::Shape{tr_input->get_shape().size()}, tr_input->get_shape().data()); + + region = std::make_shared(region, shape_as_inp, true); + new_axes = std::make_shared(ngraph::element::i64, ngraph::Shape{4}, std::vector{0, 2, 3, 1}); + region = std::make_shared(region, new_axes); + + region = std::make_shared(region, shape_node, true); + region = std::make_shared(region, tr_axes); + } + + auto strides = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{1, 1}); + std::vector boxes_shape{b, anchors, h, w}; + auto shape_3d = std::make_shared(ngraph::element::i64, ngraph::Shape{boxes_shape.size()}, boxes_shape.data()); + + ngraph::Shape box_broad_shape{1, (size_t)anchors, (size_t)h, (size_t)w}; + + std::shared_ptr box_x; + { + auto lower_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{0, 0}); + auto upper_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{1, cols}); + box_x = std::make_shared(input2d, lower_bounds, upper_bounds, strides, std::vector{}, std::vector{}); + box_x = std::make_shared(box_x); + box_x = std::make_shared(box_x, shape_3d, true); + + std::vector x_indices(w * h * anchors); + auto begin = x_indices.begin(); + for (int i = 0; i < h; i++) + { + std::fill(begin + i * anchors, begin + (i + 1) * anchors, i); + } + + for (int j = 1; j < w; j++) + { + std::copy(begin, begin + h * anchors, begin + j * h * anchors); + } + auto horiz = std::make_shared(ngraph::element::f32, box_broad_shape, x_indices.data()); + box_x = std::make_shared(box_x, horiz, ngraph::op::AutoBroadcastType::NUMPY); + + auto cols_node = std::make_shared(ngraph::element::f32, ngraph::Shape{1}, std::vector{float(w)}); + box_x = std::make_shared(box_x, cols_node, ngraph::op::AutoBroadcastType::NUMPY); + } + + std::shared_ptr box_y; + { + auto lower_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{1, 0}); + auto upper_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{2, cols}); + box_y = std::make_shared(input2d, lower_bounds, upper_bounds, strides, std::vector{}, std::vector{}); + box_y = std::make_shared(box_y); + box_y = std::make_shared(box_y, shape_3d, true); + + std::vector y_indices(h * anchors); + for (int i = 0; i < h; i++) + { + std::fill(y_indices.begin() + i * anchors, y_indices.begin() + (i + 1) * anchors, i); + } + + auto vert = std::make_shared(ngraph::element::f32, ngraph::Shape{1, (size_t)anchors, (size_t)h, 1}, y_indices.data()); + box_y = std::make_shared(box_y, vert, ngraph::op::AutoBroadcastType::NUMPY); + auto rows_node = std::make_shared(ngraph::element::f32, ngraph::Shape{1}, std::vector{float(h)}); + box_y = std::make_shared(box_y, rows_node, ngraph::op::AutoBroadcastType::NUMPY); + } + + std::shared_ptr box_w, box_h; + { + int hNorm, wNorm; + if (nodes.size() > 1) + { + auto node_1_shape = nodes[1].dynamicCast()->node->get_shape(); + hNorm = node_1_shape[2]; + wNorm = node_1_shape[3]; + } + else + { + hNorm = h; + wNorm = w; + } + + std::vector anchors_w(anchors), anchors_h(anchors); + for (size_t a = 0; a < anchors; ++a) + { + anchors_w[a] = blobs[0].at(0, 2 * a) / wNorm; + anchors_h[a] = blobs[0].at(0, 2 * a + 1) / hNorm; + } + + std::vector bias_w(w * h * anchors), bias_h(w * h * anchors); + for (int j = 0; j < h; j++) + { + std::copy(anchors_w.begin(), anchors_w.end(), bias_w.begin() + j * anchors); + std::copy(anchors_h.begin(), anchors_h.end(), bias_h.begin() + j * anchors); + } + + for (int i = 1; i < w; i++) + { + std::copy(bias_w.begin(), bias_w.begin() + h * anchors, bias_w.begin() + i * h * anchors); + std::copy(bias_h.begin(), bias_h.begin() + h * anchors, bias_h.begin() + i * h * anchors); + } + + auto lower_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{2, 0}); + auto upper_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{3, cols}); + box_w = std::make_shared(input2d, lower_bounds, upper_bounds, strides, std::vector{}, std::vector{}); + box_w = std::make_shared(box_w); + box_w = std::make_shared(box_w, shape_3d, true); + auto anchor_w_node = std::make_shared(ngraph::element::f32, box_broad_shape, bias_w.data()); + box_w = std::make_shared(box_w, anchor_w_node, ngraph::op::AutoBroadcastType::NUMPY); + + lower_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{3, 0}); + upper_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{4, cols}); + box_h = std::make_shared(input2d, lower_bounds, upper_bounds, strides, std::vector{}, std::vector{}); + box_h = std::make_shared(box_h); + box_h = std::make_shared(box_h, shape_3d, true); + auto anchor_h_node = std::make_shared(ngraph::element::f32, box_broad_shape, bias_h.data()); + box_h = std::make_shared(box_h, anchor_h_node, ngraph::op::AutoBroadcastType::NUMPY); + } + + std::shared_ptr scale; + { + auto lower_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{4, 0}); + auto upper_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{5, cols}); + scale = std::make_shared(region, lower_bounds, upper_bounds, strides, std::vector{}, std::vector{}); + + if (classfix == -1) + { + auto thresh_node = std::make_shared(ngraph::element::f32, ngraph::Shape{1}, std::vector{0.5}); + auto mask = std::make_shared(scale, thresh_node); + auto zero_node = std::make_shared(ngraph::element::f32, mask->get_shape(), std::vector(b * cols, 0)); + scale = std::make_shared(mask, scale, zero_node); + } + } + + std::shared_ptr probs; + { + auto lower_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{5, 0}); + auto upper_bounds = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{rows, cols}); + auto classes = std::make_shared(region, lower_bounds, upper_bounds, strides, std::vector{}, std::vector{}); + probs = std::make_shared(classes, scale, ngraph::op::AutoBroadcastType::NUMPY); + + auto thresh_node = std::make_shared(ngraph::element::f32, ngraph::Shape{1}, &thresh); + auto mask = std::make_shared(probs, thresh_node); + auto zero_node = std::make_shared(ngraph::element::f32, mask->get_shape(), std::vector((rows - 5) * cols, 0)); + probs = std::make_shared(mask, probs, zero_node); + } + + + auto concat_shape = std::make_shared(ngraph::element::i64, ngraph::Shape{2}, std::vector{1, cols}); + box_x = std::make_shared(box_x, concat_shape, true); + box_y = std::make_shared(box_y, concat_shape, true); + box_w = std::make_shared(box_w, concat_shape, true); + box_h = std::make_shared(box_h, concat_shape, true); + + ngraph::NodeVector inp_nodes{box_x, box_y, box_w, box_h, scale, probs}; + std::shared_ptr result = std::make_shared(inp_nodes, 0); + result = std::make_shared(result, tr_axes); + if (b > 1) + { + std::vector sizes = {(size_t)b, result->get_shape()[0] / b, result->get_shape()[1]}; + auto shape_node = std::make_shared(ngraph::element::i64, ngraph::Shape{sizes.size()}, sizes.data()); + result = std::make_shared(result, shape_node, true); + } + + return Ptr(new InfEngineNgraphNode(result)); + } +#endif // HAVE_DNN_NGRAPH + }; Ptr RegionLayer::create(const LayerParams& params) diff --git a/modules/dnn/src/onnx/onnx_importer.cpp b/modules/dnn/src/onnx/onnx_importer.cpp index 04c3a2f75f..56e9c0a217 100644 --- a/modules/dnn/src/onnx/onnx_importer.cpp +++ b/modules/dnn/src/onnx/onnx_importer.cpp @@ -1397,8 +1397,7 @@ void ONNXImporter::populateNet(Net dstNet) CV_Assert(layer_id.find(node_proto.input(i)) == layer_id.end()); String interp_mode = layerParams.get("coordinate_transformation_mode"); - CV_Assert_N(interp_mode != "tf_crop_and_resize", interp_mode != "asymmetric", - interp_mode != "tf_half_pixel_for_nn"); + CV_Assert_N(interp_mode != "tf_crop_and_resize", interp_mode != "tf_half_pixel_for_nn"); layerParams.set("align_corners", interp_mode == "align_corners"); Mat shapes = getBlob(node_proto, constBlobs, node_proto.input_size() - 1); @@ -1426,6 +1425,22 @@ void ONNXImporter::populateNet(Net dstNet) } else if (layer_type == "Upsample") { + //fused from Resize Subgraph + if (layerParams.has("coordinate_transformation_mode")) + { + String interp_mode = layerParams.get("coordinate_transformation_mode"); + CV_Assert_N(interp_mode != "tf_crop_and_resize", interp_mode != "tf_half_pixel_for_nn"); + + layerParams.set("align_corners", interp_mode == "align_corners"); + if (layerParams.get("mode") == "linear") + { + layerParams.set("mode", interp_mode == "pytorch_half_pixel" ? + "opencv_linear" : "bilinear"); + } + } + if (layerParams.get("mode") == "linear" && framework_name == "pytorch") + layerParams.set("mode", "opencv_linear"); + layerParams.type = "Resize"; if (layerParams.has("scales")) { @@ -1435,22 +1450,21 @@ void ONNXImporter::populateNet(Net dstNet) layerParams.set("zoom_factor_y", scales.getIntValue(2)); layerParams.set("zoom_factor_x", scales.getIntValue(3)); } - else + else if (layerParams.has("height_scale") && layerParams.has("width_scale")) { // Caffe2 layer replaceLayerParam(layerParams, "height_scale", "zoom_factor_y"); replaceLayerParam(layerParams, "width_scale", "zoom_factor_x"); } - replaceLayerParam(layerParams, "mode", "interpolation"); - - if (layerParams.get("interpolation") == "linear" && framework_name == "pytorch") { - layerParams.type = "Resize"; + else + { + // scales as input Mat scales = getBlob(node_proto, constBlobs, 1); CV_Assert(scales.total() == 4); - layerParams.set("interpolation", "opencv_linear"); layerParams.set("zoom_factor_y", scales.at(2)); layerParams.set("zoom_factor_x", scales.at(3)); } + replaceLayerParam(layerParams, "mode", "interpolation"); } else if (layer_type == "SoftMax" || layer_type == "LogSoftmax") { diff --git a/modules/dnn/src/op_inf_engine.cpp b/modules/dnn/src/op_inf_engine.cpp index f48631579a..114f56f1e9 100644 --- a/modules/dnn/src/op_inf_engine.cpp +++ b/modules/dnn/src/op_inf_engine.cpp @@ -891,6 +891,13 @@ bool InfEngineBackendNet::isInitialized() #endif } +void InfEngineBackendNet::reset() +{ + allBlobs.clear(); + infRequests.clear(); + isInit = false; +} + void InfEngineBackendNet::addBlobs(const std::vector >& ptrs) { auto wrappers = infEngineWrappers(ptrs); diff --git a/modules/dnn/src/op_inf_engine.hpp b/modules/dnn/src/op_inf_engine.hpp index 62b2c2f567..cbe77d9107 100644 --- a/modules/dnn/src/op_inf_engine.hpp +++ b/modules/dnn/src/op_inf_engine.hpp @@ -112,6 +112,8 @@ public: void addBlobs(const std::vector >& ptrs); + void reset(); + private: InferenceEngine::Builder::Network netBuilder; diff --git a/modules/dnn/test/test_darknet_importer.cpp b/modules/dnn/test/test_darknet_importer.cpp index 052027e210..04cb55e309 100644 --- a/modules/dnn/test/test_darknet_importer.cpp +++ b/modules/dnn/test/test_darknet_importer.cpp @@ -556,6 +556,10 @@ TEST_P(Test_Darknet_layers, avgpool_softmax) TEST_P(Test_Darknet_layers, region) { +#if defined(INF_ENGINE_RELEASE) + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && INF_ENGINE_VER_MAJOR_GE(2020020000)) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION); +#endif testDarknetLayer("region"); } diff --git a/modules/dnn/test/test_misc.cpp b/modules/dnn/test/test_misc.cpp index 36c5bc4721..a1480b0e8b 100644 --- a/modules/dnn/test/test_misc.cpp +++ b/modules/dnn/test/test_misc.cpp @@ -764,6 +764,48 @@ TEST_P(Test_Model_Optimizer, readFromBuffer) normAssert(ref, actual, "", 0, 0); } +TEST_P(Test_Model_Optimizer, flexible_inputs) +{ + const Backend backendId = get<0>(GetParam()); + const Target targetId = get<1>(GetParam()); + + const std::string& model = findDataFile("dnn/layers/layer_convolution_fp16.bin"); + const std::string& proto = findDataFile("dnn/layers/layer_convolution_fp16.xml"); + + if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API); + else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) + setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH); + else + FAIL() << "Unknown backendId"; + + Net net0 = readNet(model, proto); + net0.setPreferableTarget(targetId); + + Net net1 = readNet(model, proto); + net1.setPreferableTarget(targetId); + + // Generate inputs. + int blobSize0[] = {2, 6, 75, 113}; + Mat input0(4, &blobSize0[0], CV_32F); + randu(input0, 0, 255); + + net0.setInput(input0); + Mat ref = net0.forward().clone(); + + int blobSize1[] = {1, 6, 10, 9}; + Mat input1(4, &blobSize1[0], CV_32F); + randu(input1, 0, 255); + + net1.setInput(input1); + Mat out = net1.forward(); + EXPECT_NE(out.size, ref.size); + + net1.setInput(input0); + out = net1.forward(); + normAssert(ref, out, 0, 0); +} + INSTANTIATE_TEST_CASE_P(/**/, Test_Model_Optimizer, dnnBackendsAndTargetsIE() ); diff --git a/modules/dnn/test/test_onnx_importer.cpp b/modules/dnn/test/test_onnx_importer.cpp index df38b23140..593b8c074f 100644 --- a/modules/dnn/test/test_onnx_importer.cpp +++ b/modules/dnn/test/test_onnx_importer.cpp @@ -393,6 +393,7 @@ TEST_P(Test_ONNX_layers, ResizeUnfused) testONNXModels("upsample_unfused_opset9_torch1.4"); testONNXModels("resize_nearest_unfused_opset11_torch1.4"); testONNXModels("resize_nearest_unfused_opset11_torch1.3"); + testONNXModels("resize_bilinear_unfused_opset11_torch1.4"); } TEST_P(Test_ONNX_layers, MultyInputs) diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index e7ccf28450..ecad666e40 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -230,7 +230,7 @@ enum MorphTypes{ enum MorphShapes { MORPH_RECT = 0, //!< a rectangular structuring element: \f[E_{ij}=1\f] MORPH_CROSS = 1, //!< a cross-shaped structuring element: - //!< \f[E_{ij} = \fork{1}{if i=\texttt{anchor.y} or j=\texttt{anchor.x}}{0}{otherwise}\f] + //!< \f[E_{ij} = \begin{cases} 1 & \texttt{if } {i=\texttt{anchor.y } {or } {j=\texttt{anchor.x}}} \\0 & \texttt{otherwise} \end{cases}\f] MORPH_ELLIPSE = 2 //!< an elliptic structuring element, that is, a filled ellipse inscribed //!< into the rectangle Rect(0, 0, esize.width, 0.esize.height) }; @@ -1495,7 +1495,7 @@ The function smooths an image using the kernel: where -\f[\alpha = \fork{\frac{1}{\texttt{ksize.width*ksize.height}}}{when \texttt{normalize=true}}{1}{otherwise}\f] +\f[\alpha = \begin{cases} \frac{1}{\texttt{ksize.width*ksize.height}} & \texttt{when } \texttt{normalize=true} \\1 & \texttt{otherwise}\end{cases}\f] Unnormalized box filter is useful for computing various integral characteristics over each pixel neighborhood, such as covariance matrices of image derivatives (used in dense optical flow @@ -1569,7 +1569,7 @@ according to the specified border mode. The function does actually compute correlation, not the convolution: -\f[\texttt{dst} (x,y) = \sum _{ \stackrel{0\leq x' < \texttt{kernel.cols},}{0\leq y' < \texttt{kernel.rows}} } \texttt{kernel} (x',y')* \texttt{src} (x+x'- \texttt{anchor.x} ,y+y'- \texttt{anchor.y} )\f] +\f[\texttt{dst} (x,y) = \sum _{ \substack{0\leq x' < \texttt{kernel.cols}\\{0\leq y' < \texttt{kernel.rows}}}} \texttt{kernel} (x',y')* \texttt{src} (x+x'- \texttt{anchor.x} ,y+y'- \texttt{anchor.y} )\f] That is, the kernel is not mirrored around the anchor point. If you need a real convolution, flip the kernel using #flip and set the new anchor to `(kernel.cols - anchor.x - 1, kernel.rows - diff --git a/modules/java/CMakeLists.txt b/modules/java/CMakeLists.txt index a477490d14..33eca05988 100644 --- a/modules/java/CMakeLists.txt +++ b/modules/java/CMakeLists.txt @@ -19,7 +19,7 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/common.cmake) macro(glob_more_specific_sources _type _root _output) unset(_masks) if(${_type} STREQUAL "H") - set(_masks "${_root}/cpp/*.h" "${root}/cpp/*.hpp") + set(_masks "${_root}/cpp/*.h" "${_root}/cpp/*.hpp") elseif(${_type} STREQUAL "CPP") set(_masks "${_root}/cpp/*.cpp") elseif(${_type} STREQUAL "JAVA") diff --git a/modules/objdetect/perf/perf_qrcode_pipeline.cpp b/modules/objdetect/perf/perf_qrcode_pipeline.cpp index 44ab54f4b2..716eb2d779 100644 --- a/modules/objdetect/perf/perf_qrcode_pipeline.cpp +++ b/modules/objdetect/perf/perf_qrcode_pipeline.cpp @@ -114,7 +114,7 @@ INSTANTIATE_TEST_CASE_P(/*nothing*/, Perf_Objdetect_QRCode, INSTANTIATE_TEST_CASE_P(/*nothing*/, Perf_Objdetect_QRCode_Multi, ::testing::Values( "2_qrcodes.png", "3_close_qrcodes.png", "3_qrcodes.png", "4_qrcodes.png", - "5_qrcodes.png", "6_qrcodes.png", "7_qrcodes.png", "8_close_qrcodes.png" + "5_qrcodes.png", "6_qrcodes.png", "7_qrcodes.png", "8_close_qrcodes.png" ) ); diff --git a/modules/objdetect/src/qrcode.cpp b/modules/objdetect/src/qrcode.cpp index 5ba433aeb4..01abeb01ff 100644 --- a/modules/objdetect/src/qrcode.cpp +++ b/modules/objdetect/src/qrcode.cpp @@ -1937,8 +1937,9 @@ bool QRDetectMulti::checkSets(vector >& true_points_group, vecto vector set_size(true_points_group.size()); for (size_t i = 0; i < true_points_group.size(); i++) { - set_size[i] = int(0.5 * (true_points_group[i].size() - 2 ) * (true_points_group[i].size() - 1)); + set_size[i] = int( (true_points_group[i].size() - 2 ) * (true_points_group[i].size() - 1) * true_points_group[i].size()) / 6; } + vector< vector< Vec3i > > all_points(true_points_group.size()); for (size_t i = 0; i < true_points_group.size(); i++) all_points[i].resize(set_size[i]); @@ -1946,14 +1947,15 @@ bool QRDetectMulti::checkSets(vector >& true_points_group, vecto for (size_t i = 0; i < true_points_group.size(); i++) { cur_cluster = 0; - for (size_t j = 1; j < true_points_group[i].size() - 1; j++) - for (size_t k = j + 1; k < true_points_group[i].size(); k++) - { - all_points[i][cur_cluster][0] = 0; - all_points[i][cur_cluster][1] = int(j); - all_points[i][cur_cluster][2] = int(k); - cur_cluster++; - } + for (size_t l = 0; l < true_points_group[i].size() - 2; l++) + for (size_t j = l + 1; j < true_points_group[i].size() - 1; j++) + for (size_t k = j + 1; k < true_points_group[i].size(); k++) + { + all_points[i][cur_cluster][0] = int(l); + all_points[i][cur_cluster][1] = int(j); + all_points[i][cur_cluster][2] = int(k); + cur_cluster++; + } } for (size_t i = 0; i < true_points_group.size(); i++) diff --git a/modules/objdetect/test/test_qrcode.cpp b/modules/objdetect/test/test_qrcode.cpp index 79a060db0e..a716c837ee 100644 --- a/modules/objdetect/test/test_qrcode.cpp +++ b/modules/objdetect/test/test_qrcode.cpp @@ -23,7 +23,7 @@ std::string qrcode_images_monitor[] = { }; std::string qrcode_images_multiple[] = { "2_qrcodes.png", "3_close_qrcodes.png", "3_qrcodes.png", "4_qrcodes.png", - "5_qrcodes.png", "6_qrcodes.png", "7_qrcodes.png", "8_close_qrcodes.png" + "5_qrcodes.png", "6_qrcodes.png", "7_qrcodes.png", "8_close_qrcodes.png" }; //#define UPDATE_QRCODE_TEST_DATA #ifdef UPDATE_QRCODE_TEST_DATA @@ -138,7 +138,6 @@ TEST(Objdetect_QRCode_Monitor, generate_test_data) file_config.release(); } - TEST(Objdetect_QRCode_Multi, generate_test_data) { const std::string root = "qrcode/multiple/"; @@ -155,11 +154,12 @@ TEST(Objdetect_QRCode_Multi, generate_test_data) ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path; std::vector corners; - EXPECT_TRUE(detectQRCodeMulti(src, corners)); + QRCodeDetector qrcode; + EXPECT_TRUE(qrcode.detectMulti(src, corners)); #ifdef HAVE_QUIRC std::vector decoded_info; std::vector straight_barcode; - EXPECT_TRUE(decodeQRCodeMulti(src, corners, decoded_info, straight_barcode)); + EXPECT_TRUE(qrcode.decodeMulti(src, corners, decoded_info, straight_barcode)); #endif file_config << "x" << "[:"; for(size_t j = 0; j < corners.size(); j += 4) @@ -475,7 +475,6 @@ TEST_P(Objdetect_QRCode_Multi, regression) } } - INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode, testing::ValuesIn(qrcode_images_name)); INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode_Close, testing::ValuesIn(qrcode_images_close)); INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode_Monitor, testing::ValuesIn(qrcode_images_monitor)); @@ -501,6 +500,23 @@ TEST(Objdetect_QRCode_decodeMulti, decode_regression_16491) #endif } +TEST(Objdetect_QRCode_detectMulti, detect_regression_16961) +{ + const std::string name_current_image = "9_qrcodes.jpg"; + const std::string root = "qrcode/multiple/"; + + std::string image_path = findDataFile(root + name_current_image); + Mat src = imread(image_path); + ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path; + + QRCodeDetector qrcode; + std::vector corners; + EXPECT_TRUE(qrcode.detectMulti(src, corners)); + ASSERT_FALSE(corners.empty()); + size_t expect_corners_size = 36; + EXPECT_EQ(corners.size(), expect_corners_size); +} + TEST(Objdetect_QRCode_basic, not_found_qrcode) { std::vector corners; diff --git a/modules/video/include/opencv2/video/tracking.hpp b/modules/video/include/opencv2/video/tracking.hpp index e9788863a8..e5852eb190 100644 --- a/modules/video/include/opencv2/video/tracking.hpp +++ b/modules/video/include/opencv2/video/tracking.hpp @@ -308,7 +308,7 @@ Default values are shown in the declaration above. The function estimates the optimum transformation (warpMatrix) with respect to ECC criterion (@cite EP08), that is -\f[\texttt{warpMatrix} = \texttt{warpMatrix} = \arg\max_{W} \texttt{ECC}(\texttt{templateImage}(x,y),\texttt{inputImage}(x',y'))\f] +\f[\texttt{warpMatrix} = \arg\max_{W} \texttt{ECC}(\texttt{templateImage}(x,y),\texttt{inputImage}(x',y'))\f] where diff --git a/samples/cpp/tutorial_code/snippets/core_various.cpp b/samples/cpp/tutorial_code/snippets/core_various.cpp index 6e220788ed..4639940856 100644 --- a/samples/cpp/tutorial_code/snippets/core_various.cpp +++ b/samples/cpp/tutorial_code/snippets/core_various.cpp @@ -2,6 +2,7 @@ #include #include #include +#include using namespace std; using namespace cv; @@ -52,5 +53,32 @@ int main() imshow("rectangles", test_image); waitKey(0); //! [RotatedRect_demo] + + { + //! [TickMeter_total] + TickMeter tm; + tm.start(); + // do something ... + tm.stop(); + cout << "Total time: " << tm.getTimeSec() << endl; + //! [TickMeter_total] + } + + { + const int COUNT = 100; + //! [TickMeter_average] + TickMeter tm; + for (int i = 0; i < COUNT; i++) + { + tm.start(); + // do something ... + tm.stop(); + } + cout << "Average time per iteration in seconds: " << tm.getAvgTimeSec() << endl; + cout << "Average FPS: " << tm.getFPS() << endl; + //! [TickMeter_average] + } + + return 0; } diff --git a/samples/python/qrcode.py b/samples/python/qrcode.py new file mode 100644 index 0000000000..b3253f96c6 --- /dev/null +++ b/samples/python/qrcode.py @@ -0,0 +1,248 @@ +#!/usr/bin/env python + +''' +This program detects the QR-codes using OpenCV Library. + +Usage: + qrcode.py +''' + + +# Python 2/3 compatibility +from __future__ import print_function + +import numpy as np +import cv2 as cv + +import argparse +import sys + +PY3 = sys.version_info[0] == 3 +if PY3: + xrange = range + + +class QrSample: + def __init__(self, args): + self.fname = '' + self.fext = '' + self.fsaveid = 0 + self.input = args.input + self.detect = args.detect + self.out = args.out + self.multi = args.multi + self.saveDetections = args.save_detections + self.saveAll = args.save_all + + def getQRModeString(self): + msg1 = "multi " if self.multi else "" + msg2 = "detector" if self.detect else "decoder" + msg = "QR {:s}{:s}".format(msg1, msg2) + return msg + + def drawFPS(self, result, fps): + message = '{:.2f} FPS({:s})'.format(fps, self.getQRModeString()) + cv.putText(result, message, (20, 20), 1, + cv.FONT_HERSHEY_DUPLEX, (0, 0, 255)) + + def drawQRCodeContours(self, image, cnt): + if cnt.size != 0: + rows, cols, _ = image.shape + show_radius = 2.813 * ((rows / cols) if rows > cols else (cols / rows)) + contour_radius = show_radius * 0.4 + cv.drawContours(image, [cnt], 0, (0, 255, 0), int(round(contour_radius))) + tpl = cnt.reshape((-1, 2)) + for x in tuple(tpl.tolist()): + color = (255, 0, 0) + cv.circle(image, tuple(x), int(round(contour_radius)), color, -1) + + def drawQRCodeResults(self, result, points, decode_info, fps): + n = len(points) + if isinstance(decode_info, str): + decode_info = [decode_info] + if n > 0: + for i in range(n): + cnt = np.array(points[i]).reshape((-1, 1, 2)).astype(np.int32) + self.drawQRCodeContours(result, cnt) + msg = 'QR[{:d}]@{} : '.format(i, *(cnt.reshape(1, -1).tolist())) + print(msg, end="") + if len(decode_info) > i: + if decode_info[i]: + print("'", decode_info[i], "'") + else: + print("Can't decode QR code") + else: + print("Decode information is not available (disabled)") + else: + print("QRCode not detected!") + self.drawFPS(result, fps) + + def runQR(self, qrCode, inputimg): + if not self.multi: + if not self.detect: + decode_info, points, _ = qrCode.detectAndDecode(inputimg) + dec_info = decode_info + else: + _, points = qrCode.detect(inputimg) + dec_info = [] + else: + if not self.detect: + _, decode_info, points, _ = qrCode.detectAndDecodeMulti( + inputimg) + dec_info = decode_info + else: + _, points = qrCode.detectMulti(inputimg) + dec_info = [] + if points is None: + points = [] + return points, dec_info + + def DetectQRFrmImage(self, inputfile): + inputimg = cv.imread(inputfile, cv.IMREAD_COLOR) + if inputimg is None: + print('ERROR: Can not read image: {}'.format(inputfile)) + return + print('Run {:s} on image [{:d}x{:d}]'.format( + self.getQRModeString(), inputimg.shape[1], inputimg.shape[0])) + qrCode = cv.QRCodeDetector() + count = 10 + timer = cv.TickMeter() + for _ in range(count): + timer.start() + points, decode_info = self.runQR(qrCode, inputimg) + timer.stop() + fps = count / timer.getTimeSec() + print('FPS: {}'.format(fps)) + result = inputimg + self.drawQRCodeResults(result, points, decode_info, fps) + cv.imshow("QR", result) + cv.waitKey(1) + if self.out != '': + outfile = self.fname + self.fext + print("Saving Result: {}".format(outfile)) + cv.imwrite(outfile, result) + + print("Press any key to exit ...") + cv.waitKey(0) + print("Exit") + + def processQRCodeDetection(self, qrcode, frame): + if len(frame.shape) == 2: + result = cv.cvtColor(frame, cv.COLOR_GRAY2BGR) + else: + result = frame + print('Run {:s} on video frame [{:d}x{:d}]'.format( + self.getQRModeString(), frame.shape[1], frame.shape[0])) + timer = cv.TickMeter() + timer.start() + points, decode_info = self.runQR(qrcode, frame) + timer.stop() + + fps = 1 / timer.getTimeSec() + self.drawQRCodeResults(result, points, decode_info, fps) + return fps, result, points + + def DetectQRFrmCamera(self): + cap = cv.VideoCapture(0) + if not cap.isOpened(): + print("Cannot open the camera") + return + print("Press 'm' to switch between detectAndDecode and detectAndDecodeMulti") + print("Press 'd' to switch between decoder and detector") + print("Press ' ' (space) to save result into images") + print("Press 'ESC' to exit") + + qrcode = cv.QRCodeDetector() + + while True: + ret, frame = cap.read() + if not ret: + print("End of video stream") + break + forcesave = self.saveAll + result = frame + try: + fps, result, corners = self.processQRCodeDetection(qrcode, frame) + print('FPS: {:.2f}'.format(fps)) + forcesave |= self.saveDetections and (len(corners) != 0) + except cv.error as e: + print("Error exception: ", e) + forcesave = True + cv.imshow("QR code", result) + code = cv.waitKey(1) + if code < 0 and (not forcesave): + continue + if code == ord(' ') or forcesave: + fsuffix = '-{:05d}'.format(self.fsaveid) + self.fsaveid += 1 + fname_in = self.fname + fsuffix + "_input.png" + print("Saving QR code detection result: '{}' ...".format(fname_in)) + cv.imwrite(fname_in, frame) + print("Saved") + if code == ord('m'): + self.multi = not self.multi + msg = 'Switching QR code mode ==> {:s}'.format( + "detectAndDecodeMulti" if self.multi else "detectAndDecode") + print(msg) + if code == ord('d'): + self.detect = not self.detect + msg = 'Switching QR code mode ==> {:s}'.format( + "detect" if self.detect else "decode") + print(msg) + if code == 27: + print("'ESC' is pressed. Exiting...") + break + print("Exit.") + + +def main(): + parser = argparse.ArgumentParser( + description='This program detects the QR-codes input images using OpenCV Library.') + parser.add_argument( + '-i', + '--input', + help="input image path (for example, 'opencv_extra/testdata/cv/qrcode/multiple/*_qrcodes.png)", + default="", + metavar="") + parser.add_argument( + '-d', + '--detect', + help="detect QR code only (skip decoding) (default: False)", + action='store_true') + parser.add_argument( + '-m', + '--multi', + help="enable multiple qr-codes detection", + action='store_true') + parser.add_argument( + '-o', + '--out', + help="path to result file (default: qr_code.png)", + default="qr_code.png", + metavar="") + parser.add_argument( + '--save_detections', + help="save all QR detections (video mode only)", + action='store_true') + parser.add_argument( + '--save_all', + help="save all processed frames (video mode only)", + action='store_true') + args = parser.parse_args() + qrinst = QrSample(args) + if args.out != '': + index = args.out.rfind('.') + if index != -1: + qrinst.fname = args.out[:index] + qrinst.fext = args.out[index:] + else: + qrinst.fname = args.out + qrinst.fext = ".png" + if args.input != '': + qrinst.DetectQRFrmImage(args.input) + else: + qrinst.DetectQRFrmCamera() + + +if __name__ == '__main__': + main() diff --git a/samples/python/tutorial_code/ShapeDescriptors/point_polygon_test/pointPolygonTest_demo.py b/samples/python/tutorial_code/ShapeDescriptors/point_polygon_test/pointPolygonTest_demo.py index 0819551271..3b50a5b774 100644 --- a/samples/python/tutorial_code/ShapeDescriptors/point_polygon_test/pointPolygonTest_demo.py +++ b/samples/python/tutorial_code/ShapeDescriptors/point_polygon_test/pointPolygonTest_demo.py @@ -46,7 +46,7 @@ for i in range(src.shape[0]): drawing[i,j,1] = 255 drawing[i,j,2] = 255 -cv.circle(drawing,maxDistPt, int(maxVal),tuple(255,255,255), 1, cv.LINE_8, 0) +cv.circle(drawing,maxDistPt, int(maxVal),(255,255,255), 1, cv.LINE_8, 0) cv.imshow('Source', src) cv.imshow('Distance and inscribed circle', drawing) cv.waitKey()