diff --git a/doc/js_tutorials/js_setup/js_setup/js_setup.markdown b/doc/js_tutorials/js_setup/js_setup/js_setup.markdown index 87167cd219f3079be4cf067a030f0a1e5d41cd5b..435f06fe026d3c2154cfec4350c843a44128081e 100644 --- a/doc/js_tutorials/js_setup/js_setup/js_setup.markdown +++ b/doc/js_tutorials/js_setup/js_setup/js_setup.markdown @@ -32,6 +32,15 @@ source ./emsdk_env.sh echo ${EMSCRIPTEN} @endcode +The version 1.39.16 of emscripten is verified for latest WebAssembly. Please check the version of emscripten to use the newest features of WebAssembly. + +For example: +@code{.bash} +./emsdk update +./emsdk install 1.39.16 +./emsdk activate 1.39.16 +@endcode + Obtaining OpenCV Source Code -------------------------- @@ -76,6 +85,31 @@ Building OpenCV.js from Source python ./platforms/js/build_js.py build_wasm --build_wasm @endcode +-# [Optional] To build the OpenCV.js loader, append `--build_loader`. + + For example: + @code{.bash} + python ./platforms/js/build_js.py build_js --build_loader + @endcode + + @note + The loader is implemented as a js file in the path `/bin/loader.js`. The loader utilizes the [WebAssembly Feature Detection](https://github.com/GoogleChromeLabs/wasm-feature-detect) to detect the features of the broswer and load corresponding OpenCV.js automatically. To use it, you need to use the UMD version of [WebAssembly Feature Detection](https://github.com/GoogleChromeLabs/wasm-feature-detect) and introduce the `loader.js` in your Web application. + + Example Code: + @code{.javascipt} + // Set paths configuration + let pathsConfig = { + wasm: "../../build_wasm/opencv.js", + threads: "../../build_mt/opencv.js", + simd: "../../build_simd/opencv.js", + threadsSimd: "../../build_mtSIMD/opencv.js", + } + + // Load OpenCV.js and use the pathsConfiguration and main function as the params. + loadOpenCV(pathsConfig, main); + @endcode + + -# [optional] To build documents, append `--build_doc` option. For example: diff --git a/modules/core/include/opencv2/core/hal/intrin_wasm.hpp b/modules/core/include/opencv2/core/hal/intrin_wasm.hpp index d1bfb6da6dc98dc89f1f39e5161f18ac3eb7bbd2..ef928f6a5c7f69b7509cc8b5110d79c29d47a280 100644 --- a/modules/core/include/opencv2/core/hal/intrin_wasm.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_wasm.hpp @@ -207,13 +207,7 @@ struct v_uint64x2 uint64 get0() const { -#ifdef __wasm_unimplemented_simd128__ return (uint64)wasm_i64x2_extract_lane(val, 0); -#else - uint64 des[2]; - wasm_v128_store(des, val); - return des[0]; -#endif } v128_t val; @@ -235,13 +229,7 @@ struct v_int64x2 int64 get0() const { -#ifdef __wasm_unimplemented_simd128__ return wasm_i64x2_extract_lane(val, 0); -#else - int64 des[2]; - wasm_v128_store(des, val); - return des[0]; -#endif } v128_t val; @@ -263,13 +251,7 @@ struct v_float64x2 double get0() const { -#ifdef __wasm_unimplemented_simd128__ return wasm_f64x2_extract_lane(val, 0); -#else - double des[2]; - wasm_v128_store(des, val); - return des[0]; -#endif } v128_t val; @@ -1797,22 +1779,9 @@ OPENCV_HAL_IMPL_WASM_INITVEC(v_int16x8, short, s16, i16x8, short) OPENCV_HAL_IMPL_WASM_INITVEC(v_uint32x4, unsigned, u32, i32x4, int) OPENCV_HAL_IMPL_WASM_INITVEC(v_int32x4, int, s32, i32x4, int) OPENCV_HAL_IMPL_WASM_INITVEC(v_float32x4, float, f32, f32x4, float) - -#ifdef __wasm_unimplemented_simd128__ OPENCV_HAL_IMPL_WASM_INITVEC(v_uint64x2, uint64, u64, i64x2, int64) OPENCV_HAL_IMPL_WASM_INITVEC(v_int64x2, int64, s64, i64x2, int64) OPENCV_HAL_IMPL_WASM_INITVEC(v_float64x2, double, f64, f64x2, double) -#else -#define OPENCV_HAL_IMPL_FALLBACK_INITVEC(_Tpvec, _Tp, suffix, _Tps) \ -inline _Tpvec v_setzero_##suffix() { return _Tpvec((_Tps)0, (_Tps)0); } \ -inline _Tpvec v_setall_##suffix(_Tp v) { return _Tpvec((_Tps)v, (_Tps)v); } \ -template inline _Tpvec v_reinterpret_as_##suffix(const _Tpvec0& a) \ -{ return _Tpvec(a.val); } - -OPENCV_HAL_IMPL_FALLBACK_INITVEC(v_uint64x2, uint64, u64, int64) -OPENCV_HAL_IMPL_FALLBACK_INITVEC(v_int64x2, int64, s64, int64) -OPENCV_HAL_IMPL_FALLBACK_INITVEC(v_float64x2, double, f64, double) -#endif //////////////// PACK /////////////// inline v_uint8x16 v_pack(const v_uint16x8& a, const v_uint16x8& b) @@ -1931,28 +1900,18 @@ inline v_int16x8 v_rshr_pack(const v_int32x4& a, const v_int32x4& b) template inline v_uint32x4 v_rshr_pack(const v_uint64x2& a, const v_uint64x2& b) { -#ifdef __wasm_unimplemented_simd128__ v128_t delta = wasm_i64x2_splat(((int64)1 << (n-1))); v128_t a1 = wasm_u64x2_shr(wasm_i64x2_add(a.val, delta), n); v128_t b1 = wasm_u64x2_shr(wasm_i64x2_add(b.val, delta), n); return v_uint32x4(wasm_v8x16_shuffle(a1, b1, 0,1,2,3,8,9,10,11,16,17,18,19,24,25,26,27)); -#else - fallback::v_uint64x2 a_(a), b_(b); - return fallback::v_rshr_pack(a_, b_); -#endif } template inline v_int32x4 v_rshr_pack(const v_int64x2& a, const v_int64x2& b) { -#ifdef __wasm_unimplemented_simd128__ v128_t delta = wasm_i64x2_splat(((int64)1 << (n-1))); v128_t a1 = wasm_i64x2_shr(wasm_i64x2_add(a.val, delta), n); v128_t b1 = wasm_i64x2_shr(wasm_i64x2_add(b.val, delta), n); return v_int32x4(wasm_v8x16_shuffle(a1, b1, 0,1,2,3,8,9,10,11,16,17,18,19,24,25,26,27)); -#else - fallback::v_int64x2 a_(a), b_(b); - return fallback::v_rshr_pack(a_, b_); -#endif } template inline v_uint8x16 v_rshr_pack_u(const v_int16x8& a, const v_int16x8& b) @@ -2139,7 +2098,6 @@ inline void v_rshr_pack_store(short* ptr, const v_int32x4& a) template inline void v_rshr_pack_store(unsigned* ptr, const v_uint64x2& a) { -#ifdef __wasm_unimplemented_simd128__ v128_t delta = wasm_i64x2_splat(((int64)1 << (n-1))); v128_t a1 = wasm_u64x2_shr(wasm_i64x2_add(a.val, delta), n); v128_t r = wasm_v8x16_shuffle(a1, a1, 0,1,2,3,8,9,10,11,0,1,2,3,8,9,10,11); @@ -2148,15 +2106,10 @@ inline void v_rshr_pack_store(unsigned* ptr, const v_uint64x2& a) for (int i=0; i<2; ++i) { ptr[i] = t_ptr[i]; } -#else - fallback::v_uint64x2 _a(a); - fallback::v_rshr_pack_store(ptr, _a); -#endif } template inline void v_rshr_pack_store(int* ptr, const v_int64x2& a) { -#ifdef __wasm_unimplemented_simd128__ v128_t delta = wasm_i64x2_splat(((int64)1 << (n-1))); v128_t a1 = wasm_i64x2_shr(wasm_i64x2_add(a.val, delta), n); v128_t r = wasm_v8x16_shuffle(a1, a1, 0,1,2,3,8,9,10,11,0,1,2,3,8,9,10,11); @@ -2165,10 +2118,6 @@ inline void v_rshr_pack_store(int* ptr, const v_int64x2& a) for (int i=0; i<2; ++i) { ptr[i] = t_ptr[i]; } -#else - fallback::v_int64x2 _a(a); - fallback::v_rshr_pack_store(ptr, _a); -#endif } template inline void v_rshr_pack_u_store(uchar* ptr, const v_int16x8& a) @@ -2228,7 +2177,6 @@ inline v_uint8x16 v_pack_b(const v_uint64x2& a, const v_uint64x2& b, const v_uin const v_uint64x2& d, const v_uint64x2& e, const v_uint64x2& f, const v_uint64x2& g, const v_uint64x2& h) { -#ifdef __wasm_unimplemented_simd128__ v128_t maxval = wasm_i32x4_splat(255); v128_t a1 = wasm_v128_bitselect(maxval, a.val, ((__u64x2)(a.val) > (__u64x2)maxval)); v128_t b1 = wasm_v128_bitselect(maxval, b.val, ((__u64x2)(b.val) > (__u64x2)maxval)); @@ -2245,10 +2193,6 @@ inline v_uint8x16 v_pack_b(const v_uint64x2& a, const v_uint64x2& b, const v_uin v128_t abcd = wasm_v8x16_shuffle(ab, cd, 0,1,2,3,16,17,18,19,0,1,2,3,16,17,18,19); v128_t efgh = wasm_v8x16_shuffle(ef, gh, 0,1,2,3,16,17,18,19,0,1,2,3,16,17,18,19); return v_uint8x16(wasm_v8x16_shuffle(abcd, efgh, 0,1,2,3,4,5,6,7,16,17,18,19,20,21,22,23)); -#else - fallback::v_uint64x2 a_(a), b_(b), c_(c), d_(d), e_(e), f_(f), g_(g), h_(h); - return fallback::v_pack_b(a_, b_, c_, d_, e_, f_, g_, h_); -#endif } inline v_float32x4 v_matmul(const v_float32x4& v, const v_float32x4& m0, @@ -2310,8 +2254,6 @@ OPENCV_HAL_IMPL_WASM_BIN_OP(+, v_float32x4, wasm_f32x4_add) OPENCV_HAL_IMPL_WASM_BIN_OP(-, v_float32x4, wasm_f32x4_sub) OPENCV_HAL_IMPL_WASM_BIN_OP(*, v_float32x4, wasm_f32x4_mul) OPENCV_HAL_IMPL_WASM_BIN_OP(/, v_float32x4, wasm_f32x4_div) - -#ifdef __wasm_unimplemented_simd128__ OPENCV_HAL_IMPL_WASM_BIN_OP(+, v_uint64x2, wasm_i64x2_add) OPENCV_HAL_IMPL_WASM_BIN_OP(-, v_uint64x2, wasm_i64x2_sub) OPENCV_HAL_IMPL_WASM_BIN_OP(+, v_int64x2, wasm_i64x2_add) @@ -2320,30 +2262,6 @@ OPENCV_HAL_IMPL_WASM_BIN_OP(+, v_float64x2, wasm_f64x2_add) OPENCV_HAL_IMPL_WASM_BIN_OP(-, v_float64x2, wasm_f64x2_sub) OPENCV_HAL_IMPL_WASM_BIN_OP(*, v_float64x2, wasm_f64x2_mul) OPENCV_HAL_IMPL_WASM_BIN_OP(/, v_float64x2, wasm_f64x2_div) -#else -#define OPENCV_HAL_IMPL_FALLBACK_BIN_OP(bin_op, _Tpvec) \ -inline _Tpvec operator bin_op (const _Tpvec& a, const _Tpvec& b) \ -{ \ - fallback::_Tpvec a_(a), b_(b); \ - return _Tpvec((a_) bin_op (b_)); \ -} \ -inline _Tpvec& operator bin_op##= (_Tpvec& a, const _Tpvec& b) \ -{ \ - fallback::_Tpvec a_(a), b_(b); \ - a_ bin_op##= b_; \ - a = _Tpvec(a_); \ - return a; \ -} - -OPENCV_HAL_IMPL_FALLBACK_BIN_OP(+, v_uint64x2) -OPENCV_HAL_IMPL_FALLBACK_BIN_OP(-, v_uint64x2) -OPENCV_HAL_IMPL_FALLBACK_BIN_OP(+, v_int64x2) -OPENCV_HAL_IMPL_FALLBACK_BIN_OP(-, v_int64x2) -OPENCV_HAL_IMPL_FALLBACK_BIN_OP(+, v_float64x2) -OPENCV_HAL_IMPL_FALLBACK_BIN_OP(-, v_float64x2) -OPENCV_HAL_IMPL_FALLBACK_BIN_OP(*, v_float64x2) -OPENCV_HAL_IMPL_FALLBACK_BIN_OP(/, v_float64x2) -#endif // saturating multiply 8-bit, 16-bit #define OPENCV_HAL_IMPL_WASM_MUL_SAT(_Tpvec, _Tpwvec) \ @@ -2405,19 +2323,11 @@ inline void v_mul_expand(const v_uint16x8& a, const v_uint16x8& b, inline void v_mul_expand(const v_uint32x4& a, const v_uint32x4& b, v_uint64x2& c, v_uint64x2& d) { -#ifdef __wasm_unimplemented_simd128__ v_uint64x2 a0, a1, b0, b1; v_expand(a, a0, a1); v_expand(b, b0, b1); c.val = ((__u64x2)(a0.val) * (__u64x2)(b0.val)); d.val = ((__u64x2)(a1.val) * (__u64x2)(b1.val)); -#else - fallback::v_uint32x4 a_(a), b_(b); - fallback::v_uint64x2 c_, d_; - fallback::v_mul_expand(a_, b_, c_, d_); - c = v_uint64x2(c_); - d = v_uint64x2(d_); -#endif } inline v_int16x8 v_mul_hi(const v_int16x8& a, const v_int16x8& b) @@ -2457,7 +2367,6 @@ inline v_int32x4 v_dotprod(const v_int16x8& a, const v_int16x8& b, const v_int32 inline v_int64x2 v_dotprod(const v_int32x4& a, const v_int32x4& b) { -#ifdef __wasm_unimplemented_simd128__ v128_t a0 = wasm_i64x2_shr(wasm_i64x2_shl(a.val, 32), 32); v128_t a1 = wasm_i64x2_shr(a.val, 32); v128_t b0 = wasm_i64x2_shr(wasm_i64x2_shl(b.val, 32), 32); @@ -2465,22 +2374,10 @@ inline v_int64x2 v_dotprod(const v_int32x4& a, const v_int32x4& b) v128_t c = (v128_t)((__i64x2)a0 * (__i64x2)b0); v128_t d = (v128_t)((__i64x2)a1 * (__i64x2)b1); return v_int64x2(wasm_i64x2_add(c, d)); -#else - fallback::v_int32x4 a_(a); - fallback::v_int32x4 b_(b); - return fallback::v_dotprod(a_, b_); -#endif } inline v_int64x2 v_dotprod(const v_int32x4& a, const v_int32x4& b, const v_int64x2& c) { -#ifdef __wasm_unimplemented_simd128__ return v_dotprod(a, b) + c; -#else - fallback::v_int32x4 a_(a); - fallback::v_int32x4 b_(b); - fallback::v_int64x2 c_(c); - return fallback::v_dotprod(a_, b_, c_); -#endif } // 8 >> 32 @@ -2515,32 +2412,32 @@ inline v_int32x4 v_dotprod_expand(const v_int8x16& a, const v_int8x16& b, const // 16 >> 64 inline v_uint64x2 v_dotprod_expand(const v_uint16x8& a, const v_uint16x8& b) { - fallback::v_uint16x8 a_(a); - fallback::v_uint16x8 b_(b); - return fallback::v_dotprod_expand(a_, b_); + v128_t a0 = wasm_u32x4_shr(wasm_i32x4_shl(a.val, 16), 16); + v128_t a1 = wasm_u32x4_shr(a.val, 16); + v128_t b0 = wasm_u32x4_shr(wasm_i32x4_shl(b.val, 16), 16); + v128_t b1 = wasm_u32x4_shr(b.val, 16); + return v_uint64x2(( + v_dotprod(v_int32x4(a0), v_int32x4(b0)) + + v_dotprod(v_int32x4(a1), v_int32x4(b1))).val + ); } inline v_uint64x2 v_dotprod_expand(const v_uint16x8& a, const v_uint16x8& b, const v_uint64x2& c) -{ - fallback::v_uint16x8 a_(a); - fallback::v_uint16x8 b_(b); - fallback::v_uint64x2 c_(c); - return fallback::v_dotprod_expand(a_, b_, c_); -} +{ return v_dotprod_expand(a, b) + c; } inline v_int64x2 v_dotprod_expand(const v_int16x8& a, const v_int16x8& b) { - fallback::v_int16x8 a_(a); - fallback::v_int16x8 b_(b); - return fallback::v_dotprod_expand(a_, b_); + v128_t a0 = wasm_i32x4_shr(wasm_i32x4_shl(a.val, 16), 16); + v128_t a1 = wasm_i32x4_shr(a.val, 16); + v128_t b0 = wasm_i32x4_shr(wasm_i32x4_shl(b.val, 16), 16); + v128_t b1 = wasm_i32x4_shr(b.val, 16); + return v_int64x2(( + v_dotprod(v_int32x4(a0), v_int32x4(b0)) + + v_dotprod(v_int32x4(a1), v_int32x4(b1))) + ); } inline v_int64x2 v_dotprod_expand(const v_int16x8& a, const v_int16x8& b, const v_int64x2& c) -{ - fallback::v_int16x8 a_(a); - fallback::v_int16x8 b_(b); - fallback::v_int64x2 c_(c); - return fallback::v_dotprod_expand(a_, b_, c_); -} +{ return v_dotprod_expand(a, b) + c; } // 32 >> 64f inline v_float64x2 v_dotprod_expand(const v_int32x4& a, const v_int32x4& b) @@ -2610,44 +2507,24 @@ OPENCV_HAL_IMPL_WASM_LOGIC_OP(v_float64x2) inline v_float32x4 v_sqrt(const v_float32x4& x) { -#ifdef __wasm_unimplemented_simd128__ return v_float32x4(wasm_f32x4_sqrt(x.val)); -#else - fallback::v_float32x4 x_(x); - return fallback::v_sqrt(x_); -#endif } inline v_float32x4 v_invsqrt(const v_float32x4& x) { -#ifdef __wasm_unimplemented_simd128__ const v128_t _1_0 = wasm_f32x4_splat(1.0); return v_float32x4(wasm_f32x4_div(_1_0, wasm_f32x4_sqrt(x.val))); -#else - fallback::v_float32x4 x_(x); - return fallback::v_invsqrt(x_); -#endif } inline v_float64x2 v_sqrt(const v_float64x2& x) { -#ifdef __wasm_unimplemented_simd128__ return v_float64x2(wasm_f64x2_sqrt(x.val)); -#else - fallback::v_float64x2 x_(x); - return fallback::v_sqrt(x_); -#endif } inline v_float64x2 v_invsqrt(const v_float64x2& x) { -#ifdef __wasm_unimplemented_simd128__ const v128_t _1_0 = wasm_f64x2_splat(1.0); return v_float64x2(wasm_f64x2_div(_1_0, wasm_f64x2_sqrt(x.val))); -#else - fallback::v_float64x2 x_(x); - return fallback::v_invsqrt(x_); -#endif } #define OPENCV_HAL_IMPL_WASM_ABS_INT_FUNC(_Tpuvec, _Tpsvec, suffix, zsuffix, shiftWidth) \ @@ -2666,12 +2543,7 @@ inline v_float32x4 v_abs(const v_float32x4& x) { return v_float32x4(wasm_f32x4_abs(x.val)); } inline v_float64x2 v_abs(const v_float64x2& x) { -#ifdef __wasm_unimplemented_simd128__ return v_float64x2(wasm_f64x2_abs(x.val)); -#else - fallback::v_float64x2 x_(x); - return fallback::v_abs(x_); -#endif } // TODO: exp, log, sin, cos @@ -2684,21 +2556,8 @@ inline _Tpvec func(const _Tpvec& a, const _Tpvec& b) \ OPENCV_HAL_IMPL_WASM_BIN_FUNC(v_float32x4, v_min, wasm_f32x4_min) OPENCV_HAL_IMPL_WASM_BIN_FUNC(v_float32x4, v_max, wasm_f32x4_max) - -#ifdef __wasm_unimplemented_simd128__ OPENCV_HAL_IMPL_WASM_BIN_FUNC(v_float64x2, v_min, wasm_f64x2_min) OPENCV_HAL_IMPL_WASM_BIN_FUNC(v_float64x2, v_max, wasm_f64x2_max) -#else -#define OPENCV_HAL_IMPL_WASM_MINMAX_64f_FUNC(func) \ -inline v_float64x2 func(const v_float64x2& a, const v_float64x2& b) \ -{ \ - fallback::v_float64x2 a_(a), b_(b); \ - return fallback::func(a_, b_); \ -} - -OPENCV_HAL_IMPL_WASM_MINMAX_64f_FUNC(v_min) -OPENCV_HAL_IMPL_WASM_MINMAX_64f_FUNC(v_max) -#endif #define OPENCV_HAL_IMPL_WASM_MINMAX_S_INIT_FUNC(_Tpvec, suffix) \ inline _Tpvec v_min(const _Tpvec& a, const _Tpvec& b) \ @@ -2753,24 +2612,7 @@ OPENCV_HAL_IMPL_WASM_INIT_CMP_OP(v_int16x8, i16x8, i16x8) OPENCV_HAL_IMPL_WASM_INIT_CMP_OP(v_uint32x4, u32x4, i32x4) OPENCV_HAL_IMPL_WASM_INIT_CMP_OP(v_int32x4, i32x4, i32x4) OPENCV_HAL_IMPL_WASM_INIT_CMP_OP(v_float32x4, f32x4, f32x4) - -#ifdef __wasm_unimplemented_simd128__ OPENCV_HAL_IMPL_WASM_INIT_CMP_OP(v_float64x2, f64x2, f64x2) -#else -#define OPENCV_HAL_IMPL_INIT_FALLBACK_CMP_OP(_Tpvec, bin_op) \ -inline _Tpvec operator bin_op (const _Tpvec& a, const _Tpvec& b) \ -{ \ - fallback::_Tpvec a_(a), b_(b); \ - return _Tpvec((a_) bin_op (b_));\ -} \ - -OPENCV_HAL_IMPL_INIT_FALLBACK_CMP_OP(v_float64x2, ==) -OPENCV_HAL_IMPL_INIT_FALLBACK_CMP_OP(v_float64x2, !=) -OPENCV_HAL_IMPL_INIT_FALLBACK_CMP_OP(v_float64x2, <) -OPENCV_HAL_IMPL_INIT_FALLBACK_CMP_OP(v_float64x2, >) -OPENCV_HAL_IMPL_INIT_FALLBACK_CMP_OP(v_float64x2, <=) -OPENCV_HAL_IMPL_INIT_FALLBACK_CMP_OP(v_float64x2, >=) -#endif #define OPENCV_HAL_IMPL_WASM_64BIT_CMP_OP(_Tpvec, cast) \ inline _Tpvec operator == (const _Tpvec& a, const _Tpvec& b) \ @@ -2789,14 +2631,9 @@ inline v_float32x4 v_not_nan(const v_float32x4& a) } inline v_float64x2 v_not_nan(const v_float64x2& a) { -#ifdef __wasm_unimplemented_simd128__ v128_t z = wasm_i64x2_splat(0x7fffffffffffffff); v128_t t = wasm_i64x2_splat(0x7ff0000000000000); return v_float64x2((__u64x2)(wasm_v128_and(a.val, z)) < (__u64x2)t); -#else - fallback::v_float64x2 a_(a); - return fallback::v_not_nan(a_); -#endif } OPENCV_HAL_IMPL_WASM_BIN_FUNC(v_uint8x16, v_add_wrap, wasm_i8x16_add) @@ -2877,32 +2714,30 @@ inline v_float32x4 v_absdiff(const v_float32x4& a, const v_float32x4& b) } inline v_float64x2 v_absdiff(const v_float64x2& a, const v_float64x2& b) { -#ifdef __wasm_unimplemented_simd128__ v128_t absmask_vec = wasm_u64x2_shr(wasm_i32x4_splat(-1), 1); return v_float64x2(wasm_v128_and(wasm_f64x2_sub(a.val, b.val), absmask_vec)); -#else - fallback::v_float64x2 a_(a), b_(b); - return fallback::v_absdiff(a_, b_); -#endif } -#define OPENCV_HAL_IMPL_WASM_MISC_FLT_OP(_Tpvec) \ +#define OPENCV_HAL_IMPL_WASM_MISC_FLT_OP(_Tpvec, suffix) \ inline _Tpvec v_magnitude(const _Tpvec& a, const _Tpvec& b) \ { \ - fallback::_Tpvec a_(a), b_(b); \ - return fallback::v_magnitude(a_, b_); \ + v128_t a_Square = wasm_##suffix##_mul(a.val, a.val); \ + v128_t b_Square = wasm_##suffix##_mul(b.val, b.val); \ + return _Tpvec(wasm_##suffix##_sqrt(wasm_##suffix##_add(a_Square, b_Square))); \ } \ inline _Tpvec v_sqr_magnitude(const _Tpvec& a, const _Tpvec& b) \ { \ - return v_fma(a, a, b*b); \ + v128_t a_Square = wasm_##suffix##_mul(a.val, a.val); \ + v128_t b_Square = wasm_##suffix##_mul(b.val, b.val); \ + return _Tpvec(wasm_##suffix##_add(a_Square, b_Square)); \ } \ inline _Tpvec v_muladd(const _Tpvec& a, const _Tpvec& b, const _Tpvec& c) \ { \ - return v_fma(a, b, c); \ + return _Tpvec(wasm_##suffix##_add(wasm_##suffix##_mul(a.val, b.val), c.val)); \ } -OPENCV_HAL_IMPL_WASM_MISC_FLT_OP(v_float32x4) -OPENCV_HAL_IMPL_WASM_MISC_FLT_OP(v_float64x2) +OPENCV_HAL_IMPL_WASM_MISC_FLT_OP(v_float32x4, f32x4) +OPENCV_HAL_IMPL_WASM_MISC_FLT_OP(v_float64x2, f64x2) #define OPENCV_HAL_IMPL_WASM_SHIFT_OP(_Tpuvec, _Tpsvec, suffix, ssuffix) \ inline _Tpuvec operator << (const _Tpuvec& a, int imm) \ @@ -2945,37 +2780,7 @@ inline _Tpsvec v_shr(const _Tpsvec& a) \ OPENCV_HAL_IMPL_WASM_SHIFT_OP(v_uint8x16, v_int8x16, i8x16, u8x16) OPENCV_HAL_IMPL_WASM_SHIFT_OP(v_uint16x8, v_int16x8, i16x8, u16x8) OPENCV_HAL_IMPL_WASM_SHIFT_OP(v_uint32x4, v_int32x4, i32x4, u32x4) - -#ifdef __wasm_unimplemented_simd128__ OPENCV_HAL_IMPL_WASM_SHIFT_OP(v_uint64x2, v_int64x2, i64x2, u64x2) -#else -#define OPENCV_HAL_IMPL_FALLBACK_SHIFT_OP(_Tpvec) \ -inline _Tpvec operator << (const _Tpvec& a, int imm) \ -{ \ - fallback::_Tpvec a_(a); \ - return a_ << imm; \ -} \ -inline _Tpvec operator >> (const _Tpvec& a, int imm) \ -{ \ - fallback::_Tpvec a_(a); \ - return a_ >> imm; \ -} \ -template \ -inline _Tpvec v_shl(const _Tpvec& a) \ -{ \ - fallback::_Tpvec a_(a); \ - return fallback::v_shl(a_); \ -} \ -template \ -inline _Tpvec v_shr(const _Tpvec& a) \ -{ \ - fallback::_Tpvec a_(a); \ - return fallback::v_shr(a_); \ -} \ - -OPENCV_HAL_IMPL_FALLBACK_SHIFT_OP(v_uint64x2) -OPENCV_HAL_IMPL_FALLBACK_SHIFT_OP(v_int64x2) -#endif namespace hal_wasm_internal { @@ -3180,9 +2985,18 @@ OPENCV_HAL_IMPL_FALLBACK_REDUCE_OP_SUM(v_uint8x16, unsigned) OPENCV_HAL_IMPL_FALLBACK_REDUCE_OP_SUM(v_int8x16, int) OPENCV_HAL_IMPL_FALLBACK_REDUCE_OP_SUM(v_uint16x8, unsigned) OPENCV_HAL_IMPL_FALLBACK_REDUCE_OP_SUM(v_int16x8, int) -OPENCV_HAL_IMPL_FALLBACK_REDUCE_OP_SUM(v_uint64x2, uint64) -OPENCV_HAL_IMPL_FALLBACK_REDUCE_OP_SUM(v_int64x2, int64) -OPENCV_HAL_IMPL_FALLBACK_REDUCE_OP_SUM(v_float64x2, double) + + +#define OPENCV_HAL_IMPL_WASM_REDUCE_OP_2_SUM(_Tpvec, scalartype, regtype, suffix, esuffix) \ +inline scalartype v_reduce_sum(const _Tpvec& a) \ +{ \ + regtype val = a.val; \ + val = wasm_##suffix##_add(val, wasm_v8x16_shuffle(val, val, 8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7)); \ + return (scalartype)wasm_##esuffix##_extract_lane(val, 0); \ +} +OPENCV_HAL_IMPL_WASM_REDUCE_OP_2_SUM(v_uint64x2, uint64, v128_t, i64x2, i64x2) +OPENCV_HAL_IMPL_WASM_REDUCE_OP_2_SUM(v_int64x2, int64, v128_t, i64x2, i64x2) +OPENCV_HAL_IMPL_WASM_REDUCE_OP_2_SUM(v_float64x2, double, v128_t, f64x2,f64x2) inline v_float32x4 v_reduce_sum4(const v_float32x4& a, const v_float32x4& b, const v_float32x4& c, const v_float32x4& d) @@ -3318,30 +3132,27 @@ OPENCV_HAL_IMPL_WASM_CHECK_SIGNS(v_int16x8, i16x8, short) OPENCV_HAL_IMPL_WASM_CHECK_SIGNS(v_uint32x4, i32x4, int) OPENCV_HAL_IMPL_WASM_CHECK_SIGNS(v_int32x4, i32x4, int) OPENCV_HAL_IMPL_WASM_CHECK_SIGNS(v_float32x4, i32x4, float) +OPENCV_HAL_IMPL_WASM_CHECK_SIGNS(v_float64x2, f64x2, double) + +#define OPENCV_HAL_IMPL_WASM_CHECK_ALL_ANY(_Tpvec, suffix, esuffix) \ +inline bool v_check_all(const _Tpvec& a) \ +{ \ + v128_t masked = v_reinterpret_as_##esuffix(a).val; \ + masked = wasm_i32x4_replace_lane(masked, 0, 0xffffffff); \ + masked = wasm_i32x4_replace_lane(masked, 2, 0xffffffff); \ + return wasm_i8x16_all_true(wasm_##suffix##_lt(masked, wasm_##suffix##_splat(0))); \ +} \ +inline bool v_check_any(const _Tpvec& a) \ +{ \ + v128_t masked = v_reinterpret_as_##esuffix(a).val; \ + masked = wasm_i32x4_replace_lane(masked, 0, 0x0); \ + masked = wasm_i32x4_replace_lane(masked, 2, 0x0); \ + return wasm_i8x16_any_true(wasm_##suffix##_lt(masked, wasm_##suffix##_splat(0))); \ +} \ + +OPENCV_HAL_IMPL_WASM_CHECK_ALL_ANY(v_int64x2, i32x4, s32) +OPENCV_HAL_IMPL_WASM_CHECK_ALL_ANY(v_uint64x2, i32x4, u32) -inline int v_signmask(const v_float64x2& a) -{ - fallback::v_float64x2 a_(a); - return fallback::v_signmask(a_); -} -inline bool v_check_all(const v_float64x2& a) -{ -#ifdef __wasm_unimplemented_simd128__ - return wasm_i8x16_all_true((__i64x2)(a.val) < (__i64x2)(wasm_i64x2_splat(0))); -#else - fallback::v_float64x2 a_(a); - return fallback::v_check_all(a_); -#endif -} -inline bool v_check_any(const v_float64x2& a) -{ -#ifdef __wasm_unimplemented_simd128__ - return wasm_i8x16_any_true((__i64x2)(a.val) < (__i64x2)(wasm_i64x2_splat(0)));; -#else - fallback::v_float64x2 a_(a); - return fallback::v_check_any(a_); -#endif -} inline int v_scan_forward(const v_int8x16& a) { return trailingZeros32(v_signmask(v_reinterpret_as_s8(a))); } inline int v_scan_forward(const v_uint8x16& a) { return trailingZeros32(v_signmask(v_reinterpret_as_s8(a))); } @@ -3366,8 +3177,8 @@ OPENCV_HAL_IMPL_WASM_SELECT(v_uint16x8) OPENCV_HAL_IMPL_WASM_SELECT(v_int16x8) OPENCV_HAL_IMPL_WASM_SELECT(v_uint32x4) OPENCV_HAL_IMPL_WASM_SELECT(v_int32x4) -// OPENCV_HAL_IMPL_WASM_SELECT(v_uint64x2) -// OPENCV_HAL_IMPL_WASM_SELECT(v_int64x2) +OPENCV_HAL_IMPL_WASM_SELECT(v_uint64x2) +OPENCV_HAL_IMPL_WASM_SELECT(v_int64x2) OPENCV_HAL_IMPL_WASM_SELECT(v_float32x4) OPENCV_HAL_IMPL_WASM_SELECT(v_float64x2) diff --git a/modules/js/CMakeLists.txt b/modules/js/CMakeLists.txt index 62fd1bac9fea94f956fe692b649659bc0def378a..f3a625b37e65c4fe309e0c6d01f1ce3c8605c32f 100644 --- a/modules/js/CMakeLists.txt +++ b/modules/js/CMakeLists.txt @@ -175,3 +175,22 @@ endforeach() add_custom_target(${PROJECT_NAME}_perf ALL DEPENDS ${OCV_JS_PATH} ${opencv_perf_js_file_deps}) + +#loader +set(opencv_loader_js_bin_dir "${EXECUTABLE_OUTPUT_PATH}") +set(loader_dir ${CMAKE_CURRENT_SOURCE_DIR}/src) + +set(opencv_loader_js_file_deps "") + +# make sure the build directory exists +file(MAKE_DIRECTORY "${opencv_loader_js_bin_dir}") + +add_custom_command( + TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${loader_dir}/loader.js + ${opencv_loader_js_bin_dir}/loader.js) +list(APPEND opencv_loader_js_file_deps "${loader_dir}/loader.js" "${opencv_loader_js_bin_dir}/loader.js") + +add_custom_target(${PROJECT_NAME}_loader ALL + DEPENDS ${OCV_JS_PATH} ${opencv_loader_js_file_deps}) \ No newline at end of file diff --git a/modules/js/perf/base.js b/modules/js/perf/base.js index 6c2e772e30a04ed16e95a41a6f2efa565340d60d..3948f21254e179c971ba08ec3abcc1474ebf4baf 100644 --- a/modules/js/perf/base.js +++ b/modules/js/perf/base.js @@ -2,17 +2,28 @@ if (typeof window === 'undefined') { var cv = require("../opencv"); } -const cvSize = { - szODD: new cv.Size(127, 61), - szQVGA: new cv.Size(320, 240), - szVGA: new cv.Size(640, 480), - szqHD: new cv.Size(960, 540), - sz720p: new cv.Size(1280, 720), - sz1080p: new cv.Size(1920, 1080), - sz130x60: new cv.Size(130, 60), - sz213x120: new cv.Size(120 * 1280 / 720, 120), +let gCvSize; + +function getCvSize() { + if (gCvSize === undefined) { + gCvSize = { + szODD: new cv.Size(127, 61), + szQVGA: new cv.Size(320, 240), + szVGA: new cv.Size(640, 480), + szSVGA: new cv.Size(800, 600), + szqHD: new cv.Size(960, 540), + szXGA: new cv.Size(1024, 768), + sz720p: new cv.Size(1280, 720), + szSXGA: new cv.Size(1280, 1024), + sz1080p: new cv.Size(1920, 1080), + sz130x60: new cv.Size(130, 60), + sz213x120: new cv.Size(120 * 1280 / 720, 120), + }; + } + + return gCvSize; } if (typeof window === 'undefined') { - exports.cvSize = cvSize; + exports.getCvSize = getCvSize; } \ No newline at end of file diff --git a/modules/js/perf/perf_64bits.html b/modules/js/perf/perf_64bits.html new file mode 100644 index 0000000000000000000000000000000000000000..efbe808fbdc6c97a95aedc003bab3d4031b5cf7f --- /dev/null +++ b/modules/js/perf/perf_64bits.html @@ -0,0 +1,67 @@ + + + + + OpenCV.js Performance Test + + + + +
+
+
+

OpenCV.js Performance Test

+
+

Functions for 64-bit Perf

+ CountnonZero, Mat::dot, Split, Merge +
+
+

Mat Shape

+ for example: (1000x1000) +
+
+
+
+
+ + (It will take several minutes)
+
+
+
+

+          
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/modules/js/perf/perf_64bits.js b/modules/js/perf/perf_64bits.js new file mode 100644 index 0000000000000000000000000000000000000000..dc4e234d4cbead39c7554d530f1cab7641ef7324 --- /dev/null +++ b/modules/js/perf/perf_64bits.js @@ -0,0 +1,180 @@ +const isNodeJs = (typeof window) === 'undefined'? true : false; + +if (isNodeJs) { + var Benchmark = require('benchmark'); + var cv = require('../../opencv'); +} else { + var paramsElement = document.getElementById('params'); + var runButton = document.getElementById('runButton'); + var logElement = document.getElementById('log'); +} + +function perf() { + + console.log('opencv.js loaded'); + if (isNodeJs) { + global.cv = cv; + } else { + runButton.removeAttribute('disabled'); + runButton.setAttribute('class', 'btn btn-primary'); + runButton.innerHTML = 'Run'; + } + let totalCaseNum, currentCaseId; + + + function addCountNonZeroCase(suite) { + suite.add('countNonZero', function() { + cv.countNonZero(mat); + }, { + 'setup': function() { + let size = this.params.size; + let mat = cv.Mat.eye(size[0], size[1], cv.CV_64F); + }, 'teardown': function() { + mat.delete(); + } + }); + } + + function addMatDotCase(suite) { + suite.add('Mat::dot', function() { + mat.dot(matT); + }, { + 'setup': function() { + let size = this.params.size; + let mat = cv.Mat.ones(size[0], size[1], cv.CV_64FC1); + let matT = mat.t(); + }, 'teardown': function() { + mat.delete(); + matT.delete(); + } + }); + } + + function addSplitCase(suite) { + suite.add('Split', function() { + cv.split(mat, planes); + }, { + 'setup': function() { + let size = this.params.size; + let mat = cv.Mat.ones(size[0], size[1], cv.CV_64FC3); + let planes = new cv.MatVector(); + }, 'teardown': function() { + mat.delete(); + planes.delete(); + } + }); + } + + function addMergeCase(suite) { + suite.add('Merge', function() { + cv.merge(planes, mat); + }, { + 'setup': function() { + let size = this.params.size; + let mat = new cv.Mat(); + let mat1 = cv.Mat.ones(size[0], size[1], cv.CV_64FC3); + let planes = new cv.MatVector(); + cv.split(mat1, planes); + }, 'teardown': function() { + mat.delete(); + mat1.delete(); + planes.delete(); + } + }); + } + + function setInitParams(suite, sizeArray) { + for( let i =0; i < suite.length; i++) { + suite[i].params = { + size: sizeArray + }; + } + } + + function log(message) { + console.log(message); + if (!isNodeJs) { + logElement.innerHTML += `\n${'\t' + message}`; + } + } + + function setBenchmarkSuite(suite) { + suite + // add listeners + .on('cycle', function(event) { + ++currentCaseId; + let size = event.target.params.size; + log(`=== ${event.target.name} ${currentCaseId} ===`); + log(`params: (${parseInt(size[0])}x${parseInt(size[1])})`); + log('elapsed time:' +String(event.target.times.elapsed*1000)+' ms'); + log('mean time:' +String(event.target.stats.mean*1000)+' ms'); + log('stddev time:' +String(event.target.stats.deviation*1000)+' ms'); + log(String(event.target)); + }) + .on('error', function(event) { log(`test case ${event.target.name} failed`); }) + .on('complete', function(event) { + log(`\n ###################################`) + log(`Finished testing ${event.currentTarget.length} cases \n`); + if (!isNodeJs) { + runButton.removeAttribute('disabled'); + runButton.setAttribute('class', 'btn btn-primary'); + runButton.innerHTML = 'Run'; + } + }); + } + + function genBenchmarkCase(paramsContent) { + let suite = new Benchmark.Suite; + var sizeArray; + totalCaseNum = 4; + currentCaseId = 0; + if (/\([0-9]+x[0-9]+\)/g.test(paramsContent.toString())) { + let params = paramsContent.toString().match(/\([0-9]+x[0-9]+\)/g)[0]; + let sizeStrs = (params.match(/[0-9]+/g) || []).slice(0, 2).toString().split(","); + sizeArray = sizeStrs.map(Number); + } else { + log("no getting invalid params, run all the cases with Mat of shape (1000 x 1000)"); + sizeArray = [1000, 1000]; + } + addCountNonZeroCase(suite); + addMatDotCase(suite); + addSplitCase(suite); + addMergeCase(suite); + setInitParams(suite, sizeArray) + setBenchmarkSuite(suite); + log(`Running ${totalCaseNum} tests from 64-bit intrinsics`); + suite.run({ 'async': true }); // run the benchmark + } + + + // set test filter params + if (isNodeJs) { + const args = process.argv.slice(2); + let paramsContent = ''; + if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*\w+\)/g.test(args.toString())) { + paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+\)/g)[0]; + } + genBenchmarkCase(paramsContent); + } else { + runButton.onclick = function() { + let paramsContent = paramsElement.value; + genBenchmarkCase(paramsContent); + if (totalCaseNum !== 0) { + runButton.setAttribute("disabled", "disabled"); + runButton.setAttribute('class', 'btn btn-primary disabled'); + runButton.innerHTML = "Running"; + } + } + } +}; + +async function main() { + if (cv instanceof Promise) { + cv = await cv; + perf(); + } else { + cv.onRuntimeInitialized = perf; + } +} + +main(); \ No newline at end of file diff --git a/modules/js/perf/perf_helpfunc.js b/modules/js/perf/perf_helpfunc.js index e07e3a297ed4a07f09b1f3519ce45f6aab0d26c4..e42f4ad8071add13a358ddb0ff6faeec98380c1f 100644 --- a/modules/js/perf/perf_helpfunc.js +++ b/modules/js/perf/perf_helpfunc.js @@ -16,14 +16,57 @@ var fillGradient = function(cv, img, delta=5) { } } +var smoothBorder = function(cv, img, color, delta=5) { + let ch = img.channels(); + console.assert(!img.empty() && img.depth() == cv.CV_8U && ch <= 4); + + let n = 100/delta; + let nR = Math.min(n, (img.rows+1)/2); + let nC = Math.min(n, (img.cols+1)/2); + let s = new cv.Scalar(); + + for (let r = 0; r < nR; r++) { + let k1 = r*delta/100.0, k2 = 1-k1; + for(let c = 0; c < img.cols; c++) { + let view = img.ptr(r, c); + for(let i = 0; i < ch; i++) s[i] = view[i]; + for(let i = 0; i < ch; i++) view[i] = s[i]*k1 + color[i] * k2; + } + for(let c=0; c < img.cols; c++) { + let view = img.ptr(img.rows-r-1, c); + for(let i = 0; i < ch; i++) s[i] = view[i]; + for(let i = 0; i < ch; i++) view[i] = s[i]*k1 + color[i] * k2; + } + } + for (let r = 0; r < img.rows; r++) { + for(let c = 0; c < nC; c++) { + let k1 = c*delta/100.0, k2 = 1-k1; + let view = img.ptr(r, c); + for(let i = 0; i < ch; i++) s[i] = view[i]; + for(let i = 0; i < ch; i++) view[i] = s[i]*k1 + color[i] * k2; + } + for(let c = 0; c < n; c++) { + let k1 = c*delta/100.0, k2 = 1-k1; + let view = img.ptr(r, img.cols-c-1); + for(let i = 0; i < ch; i++) s[i] = view[i]; + for(let i = 0; i < ch; i++) view[i] = s[i]*k1 + color[i] * k2; + } + } +} + var cvtStr2cvSize = function(strSize) { let size; + + let cvSize = getCvSize(); switch(strSize) { case "127,61": size = cvSize.szODD;break; case '320,240': size = cvSize.szQVGA;break; case '640,480': size = cvSize.szVGA;break; + case '800,600': size = cvSize.szSVGA;break; case '960,540': size = cvSize.szqHD;break; + case '1024,768': size = cvSize.szXGA;break; case '1280,720': size = cvSize.sz720p;break; + case '1280,1024': size = cvSize.szSXGA;break; case '1920,1080': size = cvSize.sz1080p;break; case "130,60": size = cvSize.sz130x60;break; case '213,120': size = cvSize.sz213x120;break; @@ -52,8 +95,209 @@ function permute (source, target) { return result; } +var constructMode = function (startStr, sChannel, dChannel) { + let modeList = [] + for (let j in dChannel) { + modeList.push(startStr+sChannel+"2"+dChannel[j]) + } + return modeList; +} + +var enableButton = function () { + runButton.removeAttribute('disabled'); + runButton.setAttribute('class', 'btn btn-primary'); + runButton.innerHTML = 'Run'; +} + +var disableButton = function () { + runButton.setAttribute("disabled", "disabled"); + runButton.setAttribute('class', 'btn btn-primary disabled'); + runButton.innerHTML = "Running"; +} + +var log = function (message) { + console.log(message); + if (!isNodeJs) { + logElement.innerHTML += `\n${'\t' + message}`; + } +} + +var addKernelCase = function (suite, params, type, kernelFunc) { + kernelFunc(suite, type); + let index = suite.length - 1; + suite[index].params = params; +} + +function constructParamLog(params, kernel) { + let paramLog = ''; + if (kernel == "cvtcolor") { + let mode = params.mode; + let size = params.size; + paramLog = `params: (${parseInt(size[0])}x${parseInt(size[1])}, ${mode})`; + } else if (kernel == "resize") { + let matType = params.matType; + let size1 = params.from; + let size2 = params.to; + paramLog = `params: (${matType},${parseInt(size1.width)}x${parseInt(size1.height)},`+ + `${parseInt(size2.width)}x${parseInt(size2.height)})`; + } else if (kernel == "threshold") { + let matSize = params.matSize; + let matType = params.matType; + let threshType = params.threshType; + paramLog = `params: (${parseInt(matSize.width)}x${parseInt(matSize.height)},`+ + `${matType},${threshType})`; + } else if (kernel == "sobel") { + let size = params.size; + let ddepth = params.ddepth; + let dxdy = params.dxdy; + let ksize = params.ksize; + let borderType = params.borderType; + paramLog = `params: (${parseInt(size[0])}x${parseInt(size[1])},`+ + `${ddepth},${dxdy},${borderType}, ksize:${ksize})`; + } else if (kernel == "filter2d") { + let size = params.size; + let ksize = params.ksize; + let borderMode = params.borderMode; + paramLog = `params: (${parseInt(size.width)}x${parseInt(size.height)},`+ + `${ksize},${borderMode})`; + } else if (kernel == "scharr") { + let size = params.size; + let ddepth = params.ddepth; + let dxdy = params.dxdy; + let borderType = params.borderType; + paramLog = `params: (${parseInt(size[0])}x${parseInt(size[1])},`+ + `${ddepth},${dxdy},${borderType})`; + } else if (kernel == "gaussianBlur" || kernel == "blur") { + let size = params.size; + let matType = params.matType; + let borderType = params.borderType; + let ksize = params.ksize; + paramLog = `params: (${parseInt(size.width)}x${parseInt(size.height)},`+ + `${matType},${borderType}, ksize: (${ksize}x${ksize}))`; + } else if (kernel == "medianBlur") { + let size = params.size; + let matType = params.matType; + let ksize = params.ksize; + paramLog = `params: (${parseInt(size.width)}x${parseInt(size.height)},`+ + `${matType}, ksize: ${ksize})`; + } else if (kernel == "erode" || kernel == "dilate" || kernel == "pyrDown") { + let size = params.size; + let matType = params.matType; + paramLog = `params: (${parseInt(size.width)}x${parseInt(size.height)},`+ + `${matType})`; + } else if (kernel == "remap") { + let size = params.size; + let matType = params.matType; + let mapType = params.mapType; + let interType = params.interType; + paramLog = `params: (${parseInt(size.width)}x${parseInt(size.height)},`+ + `${matType}, ${mapType}, ${interType})`; + } else if (kernel == "warpAffine" || kernel == "warpPerspective") { + let size = params.size; + let interType = params.interType; + let borderMode = params.borderMode; + paramLog = `params: (${parseInt(size.width)}x${parseInt(size.height)},`+ + `${interType}, ${borderMode})`; + } + return paramLog; +} + +var setBenchmarkSuite = function (suite, kernel, currentCaseId) { + suite + // add listeners + .on('cycle', function(event) { + ++currentCaseId; + let params = event.target.params; + paramLog = constructParamLog(params, kernel); + + log(`=== ${event.target.name} ${currentCaseId} ===`); + log(paramLog); + log('elapsed time:' +String(event.target.times.elapsed*1000)+' ms'); + log('mean time:' +String(event.target.stats.mean*1000)+' ms'); + log('stddev time:' +String(event.target.stats.deviation*1000)+' ms'); + log(String(event.target)); + }) + .on('error', function(event) { log(`test case ${event.target.name} failed`); }) + .on('complete', function(event) { + log(`\n ###################################`) + log(`Finished testing ${event.currentTarget.length} cases \n`); + if (!isNodeJs) { + runButton.removeAttribute('disabled'); + runButton.setAttribute('class', 'btn btn-primary'); + runButton.innerHTML = 'Run'; + } + }); +} + +var decodeParams2Case = function(paramContent, paramsList, combinations) { + let sizeString = (paramContent.match(/[0-9]+x[0-9]+/g) || []).toString(); + let sizes = (sizeString.match(/[0-9]+/g) || []); + let paramSize = paramsList.length; + let paramObjs = [] + let sizeCount = 0; + for (let i = 0; i < paramSize; i++) { + let param = paramsList[i]; + let paramName = param.name; + let paramValue = param.value; + let paramReg = param.reg; + let paramIndex = param.index; + + if(paramValue != "") { + paramObjs.push({name: paramName, value: paramValue, index: paramIndex}); + } else if (paramName.startsWith('size')) { + let sizeStr = sizes.slice(sizeCount, sizeCount+2).toString(); + paramValue = cvtStr2cvSize(sizeStr); + sizeCount += 2; + paramObjs.push({name: paramName, value: paramValue, index: paramIndex}); + } else { + for (let index in paramReg) { + let reg = eval(paramReg[index]); + if ('loc' in param) { + paramValue = (paramContent.match(reg) || [])[param.loc].toString(); + } else { + paramValue = (paramContent.match(reg) || []).toString(); + } + + if (paramValue != "") { + paramObjs.push({name: paramName, value: paramValue, index: paramIndex}); + break; + } + } + } + } + + let location = []; + for (let i = 0; i < combinations.length; ++i) { + let combination = combinations[i]; + for (let j = 0; j < combination.length; ++j) { + if (judgeCombin(combination[j], paramObjs)) { + location.push([i,j]); + } + } + } + return location; +} + +function judgeCombin(combination, paramObjs) { + for (let i =0; i < paramObjs.length; i++) { + if (paramObjs[i].value != combination[paramObjs[i].index]){ + return false; + } + } + return true; +} + + if (typeof window === 'undefined') { + exports.enableButton = enableButton; + exports.disableButton = disableButton; exports.fillGradient = fillGradient; + exports.smoothBorder = smoothBorder; exports.cvtStr2cvSize = cvtStr2cvSize; exports.combine = combine; + exports.constructMode = constructMode; + exports.log = log; + exports.decodeParams2Case = decodeParams2Case; + exports.setBenchmarkSuite = setBenchmarkSuite; + exports.addKernelCase = addKernelCase; } \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_blur.html b/modules/js/perf/perf_imgproc/perf_blur.html new file mode 100644 index 0000000000000000000000000000000000000000..c6fae45db0cb264c0f2b53b850ee4dc4acfca607 --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_blur.html @@ -0,0 +1,73 @@ + + + + + OpenCV.js Performance Test + + + + +
+
+
+

OpenCV.js Performance Test

+
+

Modules

+ Image Processing +
+
+

Kernels

+ Blur +
+
+

Parameters Filter

+ for example: (1280x720, CV_8UC1, BORDER_REPLICATE) +
+
+
+
+
+ + (It will take several minutes)
+
+
+
+

+          
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_blur.js b/modules/js/perf/perf_imgproc/perf_blur.js new file mode 100644 index 0000000000000000000000000000000000000000..59712fb478f3befc876597103cf04952ca4b8459 --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_blur.js @@ -0,0 +1,130 @@ +const isNodeJs = (typeof window) === 'undefined'? true : false; + +if (isNodeJs) { + var Benchmark = require('benchmark'); + var cv = require('../../opencv'); + var HelpFunc = require('../perf_helpfunc'); + var Base = require('../base'); +} else { + var paramsElement = document.getElementById('params'); + var runButton = document.getElementById('runButton'); + var logElement = document.getElementById('log'); +} + +function perf() { + + console.log('opencv.js loaded'); + if (isNodeJs) { + global.cv = cv; + global.combine = HelpFunc.combine; + global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize; + global.cvSize = Base.getCvSize(); + } else { + enableButton(); + cvSize = getCvSize(); + } + let totalCaseNum, currentCaseId; + + const BlurSize = [cvSize.szODD, cvSize.szQVGA, cvSize.szVGA, cvSize.sz720p]; + const Blur5x16Size = [cvSize.szVGA, cvSize.sz720p]; + const BlurType = ["CV_8UC1", "CV_8UC4", "CV_16UC1", "CV_16SC1", "CV_32FC1"]; + const BlurType5x5 = ["CV_8UC1", "CV_8UC4", "CV_16UC1", "CV_16SC1", "CV_32FC1", "CV_32FC3"]; + const BorderType3x3 = ["BORDER_REPLICATE", "BORDER_CONSTANT"]; + const BorderTypeAll = ["BORDER_REPLICATE", "BORDER_CONSTANT", "BORDER_REFLECT", "BORDER_REFLECT101"]; + + const combiBlur3x3 = combine(BlurSize, BlurType, BorderType3x3); + const combiBlur16x16 = combine(Blur5x16Size, BlurType, BorderTypeAll); + const combiBlur5x5 = combine(Blur5x16Size, BlurType5x5, BorderTypeAll); + + function addBlurCase(suite, type) { + suite.add('blur', function() { + cv.blur(src, dst, ksize, new cv.Point(-1,-1), borderType); + }, { + 'setup': function() { + let size = this.params.size; + let matType = cv[this.params.matType]; + let borderType = cv[this.params.borderType]; + let ksizeNum = this.params.ksize; + let ksize = new cv.Size(ksizeNum, ksizeNum); + let src = new cv.Mat(size, matType); + let dst = new cv.Mat(size, matType); + }, + 'teardown': function() { + src.delete(); + dst.delete(); + } + }); + } + + function addBlurModeCase(suite, combination, type) { + totalCaseNum += combination.length; + for (let i = 0; i < combination.length; ++i) { + let size = combination[i][0]; + let matType = combination[i][1]; + let borderType = combination[i][2]; + let ksizeArray = [3, 16, 5]; + + let params = {size: size, matType:matType, ksize: ksizeArray[type], borderType:borderType}; + addKernelCase(suite, params, type, addBlurCase); + } + } + + function genBenchmarkCase(paramsContent) { + let suite = new Benchmark.Suite; + totalCaseNum = 0; + currentCaseId = 0; + + if (/\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*BORDER\_\w+\)/g.test(paramsContent.toString())) { + let params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*BORDER\_\w+\)/g)[0]; + let paramObjs = []; + paramObjs.push({name:"size", value:"", reg:[""], index:0}); + paramObjs.push({name:"matType", value:"", reg:["/CV\_[0-9]+[FSUfsu]C[0-9]/"], index:1}); + paramObjs.push({name:"borderMode", value: "", reg:["/BORDER\_\\w+/"], index:2}); + let locationList = decodeParams2Case(params, paramObjs,blurCombinations); + + for (let i = 0; i < locationList.length; i++){ + let first = locationList[i][0]; + let second = locationList[i][1]; + addBlurModeCase(suite, [blurCombinations[first][second]], first); + } + } else { + log("no filter or getting invalid params, run all the cases"); + addBlurModeCase(suite, combiBlur3x3, 0); + addBlurModeCase(suite, combiBlur16x16, 1); + addBlurModeCase(suite, combiBlur5x5, 2); + } + setBenchmarkSuite(suite, "blur", currentCaseId); + log(`Running ${totalCaseNum} tests from blur`); + suite.run({ 'async': true }); // run the benchmark + } + + let blurCombinations = [combiBlur3x3, combiBlur16x16, combiBlur5x5]; + + if (isNodeJs) { + const args = process.argv.slice(2); + let paramsContent = ''; + if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*BORDER\_\w+\)/g.test(args.toString())) { + paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*BORDER\_\w+\)/g)[0]; + } + genBenchmarkCase(paramsContent); + } else { + runButton.onclick = function() { + let paramsContent = paramsElement.value; + genBenchmarkCase(paramsContent); + if (totalCaseNum !== 0) { + disableButton(); + } + } + } +}; + +async function main() { + if (cv instanceof Promise) { + cv = await cv; + perf(); + } else { + cv.onRuntimeInitialized = perf; + } +} + +main(); \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_cvtcolor.js b/modules/js/perf/perf_imgproc/perf_cvtcolor.js index 752691ef77aab91a0902d91c6dedcb4e987bf48c..b5007985cc2664b6b8c66fe8b797231387572423 100644 --- a/modules/js/perf/perf_imgproc/perf_cvtcolor.js +++ b/modules/js/perf/perf_imgproc/perf_cvtcolor.js @@ -11,17 +11,17 @@ if (isNodeJs) { var logElement = document.getElementById('log'); } -cv.onRuntimeInitialized = () => { +function perf() { + console.log('opencv.js loaded'); if (isNodeJs) { global.cv = cv; global.combine = HelpFunc.combine; global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize; - global.cvSize = Base.cvSize; + global.cvSize = Base.getCvSize(); } else { - runButton.removeAttribute('disabled'); - runButton.setAttribute('class', 'btn btn-primary'); - runButton.innerHTML = 'Run'; + enableButton(); + cvSize = getCvSize(); } let totalCaseNum, currentCaseId; @@ -73,126 +73,77 @@ cv.onRuntimeInitialized = () => { cv.CX_YUV2RGBA = cv.COLOR_COLORCVT_MAX + cv.COLOR_YUV2RGB }; - const CvtMode = [ - "COLOR_BGR2BGR555", "COLOR_BGR2BGR565", "COLOR_BGR2BGRA", "COLOR_BGR2GRAY", - "COLOR_BGR2HLS", "COLOR_BGR2HLS_FULL", "COLOR_BGR2HSV", "COLOR_BGR2HSV_FULL", - "COLOR_BGR2Lab", "COLOR_BGR2Luv", "COLOR_BGR2RGB", "COLOR_BGR2RGBA", "COLOR_BGR2XYZ", - "COLOR_BGR2YCrCb", "COLOR_BGR2YUV", "COLOR_BGR5552BGR", "COLOR_BGR5552BGRA", - - "COLOR_BGR5552GRAY", "COLOR_BGR5552RGB", "COLOR_BGR5552RGBA", "COLOR_BGR5652BGR", - "COLOR_BGR5652BGRA", "COLOR_BGR5652GRAY", "COLOR_BGR5652RGB", "COLOR_BGR5652RGBA", - - "COLOR_BGRA2BGR", "COLOR_BGRA2BGR555", "COLOR_BGRA2BGR565", "COLOR_BGRA2GRAY", "COLOR_BGRA2RGBA", - "CX_BGRA2HLS", "CX_BGRA2HLS_FULL", "CX_BGRA2HSV", "CX_BGRA2HSV_FULL", - "CX_BGRA2Lab", "CX_BGRA2Luv", "CX_BGRA2XYZ", - "CX_BGRA2YCrCb", "CX_BGRA2YUV", - - "COLOR_GRAY2BGR", "COLOR_GRAY2BGR555", "COLOR_GRAY2BGR565", "COLOR_GRAY2BGRA", - - "COLOR_HLS2BGR", "COLOR_HLS2BGR_FULL", "COLOR_HLS2RGB", "COLOR_HLS2RGB_FULL", - "CX_HLS2BGRA", "CX_HLS2BGRA_FULL", "CX_HLS2RGBA", "CX_HLS2RGBA_FULL", - - "COLOR_HSV2BGR", "COLOR_HSV2BGR_FULL", "COLOR_HSV2RGB", "COLOR_HSV2RGB_FULL", - "CX_HSV2BGRA", "CX_HSV2BGRA_FULL", "CX_HSV2RGBA", "CX_HSV2RGBA_FULL", - - "COLOR_Lab2BGR", "COLOR_Lab2LBGR", "COLOR_Lab2LRGB", "COLOR_Lab2RGB", - "CX_Lab2BGRA", "CX_Lab2LBGRA", "CX_Lab2LRGBA", "CX_Lab2RGBA", - - "COLOR_LBGR2Lab", "COLOR_LBGR2Luv", "COLOR_LRGB2Lab", "COLOR_LRGB2Luv", - "CX_LBGRA2Lab", "CX_LBGRA2Luv", "CX_LRGBA2Lab", "CX_LRGBA2Luv", - - "COLOR_Luv2BGR", "COLOR_Luv2LBGR", "COLOR_Luv2LRGB", "COLOR_Luv2RGB", - "CX_Luv2BGRA", "CX_Luv2LBGRA", "CX_Luv2LRGBA", "CX_Luv2RGBA", - - "COLOR_RGB2BGR555", "COLOR_RGB2BGR565", "COLOR_RGB2GRAY", - "COLOR_RGB2HLS", "COLOR_RGB2HLS_FULL", "COLOR_RGB2HSV", "COLOR_RGB2HSV_FULL", - "COLOR_RGB2Lab", "COLOR_RGB2Luv", "COLOR_RGB2XYZ", "COLOR_RGB2YCrCb", "COLOR_RGB2YUV", - - "COLOR_RGBA2BGR", "COLOR_RGBA2BGR555", "COLOR_RGBA2BGR565", "COLOR_RGBA2GRAY", - "CX_RGBA2HLS", "CX_RGBA2HLS_FULL", "CX_RGBA2HSV", "CX_RGBA2HSV_FULL", - "CX_RGBA2Lab", "CX_RGBA2Luv", "CX_RGBA2XYZ", - "CX_RGBA2YCrCb", "CX_RGBA2YUV", - - "COLOR_XYZ2BGR", "COLOR_XYZ2RGB", "CX_XYZ2BGRA", "CX_XYZ2RGBA", - - "COLOR_YCrCb2BGR", "COLOR_YCrCb2RGB", "CX_YCrCb2BGRA", "CX_YCrCb2RGBA", - "COLOR_YUV2BGR", "COLOR_YUV2RGB", "CX_YUV2BGRA", "CX_YUV2RGBA" - ]; - const CvtModeSize = [cvSize.szODD, cvSize.szVGA, cvSize.sz1080p]; - const combiCvtMode = combine(CvtModeSize, CvtMode); - // didn't support 16u and 32f perf tests according to // https://github.com/opencv/opencv/commit/4e679e1cc5b075ec006b29a58b4fe117523fba1d - const CvtMode16U = [ - "COLOR_BGR2BGRA", "COLOR_BGR2GRAY", - "COLOR_BGR2RGB", "COLOR_BGR2RGBA", "COLOR_BGR2XYZ", - "COLOR_BGR2YCrCb", "COLOR_BGR2YUV", - - "COLOR_BGRA2BGR", "COLOR_BGRA2GRAY", "COLOR_BGRA2RGBA", - "CX_BGRA2XYZ", - "CX_BGRA2YCrCb", "CX_BGRA2YUV", - - "COLOR_GRAY2BGR", "COLOR_GRAY2BGRA", - - "COLOR_RGB2GRAY", - "COLOR_RGB2XYZ", "COLOR_RGB2YCrCb", "COLOR_RGB2YUV", - - "COLOR_RGBA2BGR", "COLOR_RGBA2GRAY", - "CX_RGBA2XYZ", - "CX_RGBA2YCrCb", "CX_RGBA2YUV", + function constructCvtMode16U() { + let cvtMode16U = []; + cvtMode16U = cvtMode16U.concat(constructMode("COLOR_", "BGR", ["BGRA", "GRAY", "RGB", "RGBA", "XYZ", "YCrCb", "YUV"])); + cvtMode16U = cvtMode16U.concat(constructMode("COLOR_", "BGRA", ["BGR", "GRAY", "RGBA"])); + cvtMode16U = cvtMode16U.concat(constructMode("CX_", "BGRA", ["XYZ", "YCrCb", "YUV"])); + cvtMode16U = cvtMode16U.concat(constructMode("COLOR_", "GRAY", ["BGR", "BGRA"])); + cvtMode16U = cvtMode16U.concat(constructMode("COLOR_", "RGB", ["GRAY", "XYZ", "YCrCb", "YUV"])); + cvtMode16U = cvtMode16U.concat(constructMode("COLOR_", "RGBA", ["BGR", "GRAY"])); + cvtMode16U = cvtMode16U.concat(constructMode("CX_", "RGBA", ["XYZ", "YCrCb", "YUV"])); + cvtMode16U = cvtMode16U.concat(constructMode("COLOR_", "XYZ", ["BGR", "RGB"])); + cvtMode16U = cvtMode16U.concat(constructMode("CX_", "XYZ", ["BGRA", "RGBA"])); + cvtMode16U = cvtMode16U.concat(constructMode("COLOR_", "YCrCb", ["BGR", "RGB"])); + cvtMode16U = cvtMode16U.concat(constructMode("CX_", "YCrCb", ["BGRA", "RGBA"])); + cvtMode16U = cvtMode16U.concat(constructMode("COLOR_", "YUV", ["BGR", "RGB"])); + cvtMode16U = cvtMode16U.concat(constructMode("CX_", "YUV", ["BGRA", "RGBA"])); + + return cvtMode16U; + } - "COLOR_XYZ2BGR", "COLOR_XYZ2RGB", "CX_XYZ2BGRA", "CX_XYZ2RGBA", + const CvtMode16U = constructCvtMode16U(); - "COLOR_YCrCb2BGR", "COLOR_YCrCb2RGB", "CX_YCrCb2BGRA", "CX_YCrCb2RGBA", - "COLOR_YUV2BGR", "COLOR_YUV2RGB", "CX_YUV2BGRA", "CX_YUV2RGBA" - ]; const CvtMode16USize = [cvSize.szODD, cvSize.szVGA, cvSize.sz1080p]; const combiCvtMode16U = combine(CvtMode16USize, CvtMode16U); - const CvtMode32F = [ - "COLOR_BGR2BGRA", "COLOR_BGR2GRAY", - "COLOR_BGR2HLS", "COLOR_BGR2HLS_FULL", "COLOR_BGR2HSV", "COLOR_BGR2HSV_FULL", - "COLOR_BGR2Lab", "COLOR_BGR2Luv", "COLOR_BGR2RGB", "COLOR_BGR2RGBA", "COLOR_BGR2XYZ", - "COLOR_BGR2YCrCb", "COLOR_BGR2YUV", - - "COLOR_BGRA2BGR", "COLOR_BGRA2GRAY", "COLOR_BGRA2RGBA", - "CX_BGRA2HLS", "CX_BGRA2HLS_FULL", "CX_BGRA2HSV", "CX_BGRA2HSV_FULL", - "CX_BGRA2Lab", "CX_BGRA2Luv", "CX_BGRA2XYZ", - "CX_BGRA2YCrCb", "CX_BGRA2YUV", - - "COLOR_GRAY2BGR", "COLOR_GRAY2BGRA", - - "COLOR_HLS2BGR", "COLOR_HLS2BGR_FULL", "COLOR_HLS2RGB", "COLOR_HLS2RGB_FULL", - "CX_HLS2BGRA", "CX_HLS2BGRA_FULL", "CX_HLS2RGBA", "CX_HLS2RGBA_FULL", - - "COLOR_HSV2BGR", "COLOR_HSV2BGR_FULL", "COLOR_HSV2RGB", "COLOR_HSV2RGB_FULL", - "CX_HSV2BGRA", "CX_HSV2BGRA_FULL", "CX_HSV2RGBA", "CX_HSV2RGBA_FULL", - - "COLOR_Lab2BGR", "COLOR_Lab2LBGR", "COLOR_Lab2LRGB", "COLOR_Lab2RGB", - "CX_Lab2BGRA", "CX_Lab2LBGRA", "CX_Lab2LRGBA", "CX_Lab2RGBA", - - "COLOR_LBGR2Lab", "COLOR_LBGR2Luv", "COLOR_LRGB2Lab", "COLOR_LRGB2Luv", - "CX_LBGRA2Lab", "CX_LBGRA2Luv", "CX_LRGBA2Lab", "CX_LRGBA2Luv", + function constructCvtMode32F(source) { + let cvtMode32F = source; + cvtMode32F = cvtMode32F.concat(constructMode("COLOR_", "BGR", ["HLS", "HLS_FULL", "HSV", "HSV_FULL", "Lab", "Luv"])); + cvtMode32F = cvtMode32F.concat(constructMode("CX_", "BGRA", ["HLS", "HLS_FULL", "HSV", "HSV_FULL", "Lab", "Luv"])); + cvtMode32F = cvtMode32F.concat(constructMode("COLOR_", "HLS", ["BGR", "BGR_FULL", "RGB", "RGB_FULL"])); + cvtMode32F = cvtMode32F.concat(constructMode("CX_", "HLS", ["BGRA", "BGRA_FULL", "RGBA", "RGBA_FULL"])); + cvtMode32F = cvtMode32F.concat(constructMode("COLOR_", "HSV", ["BGR", "BGR_FULL", "RGB", "RGB_FULL"])); + cvtMode32F = cvtMode32F.concat(constructMode("CX_", "HSV", ["BGRA", "BGRA_FULL", "RGBA", "RGBA_FULL"])); + cvtMode32F = cvtMode32F.concat(constructMode("COLOR_", "Lab", ["BGR", "LBGR", "RGB", "LRGB"])); + cvtMode32F = cvtMode32F.concat(constructMode("CX_", "Lab", ["BGRA", "LBGRA", "RGBA", "LRGBA"])); + cvtMode32F = cvtMode32F.concat(constructMode("COLOR_", "Luv", ["BGR", "LBGR", "RGB", "LRGB"])); + cvtMode32F = cvtMode32F.concat(constructMode("CX_", "Luv", ["BGRA", "LBGRA", "RGBA", "LRGBA"])); + cvtMode32F = cvtMode32F.concat(constructMode("COLOR_", "LBGR", ["Lab", "Luv"])); + cvtMode32F = cvtMode32F.concat(constructMode("CX_", "LBGRA", ["Lab", "Luv"])); + cvtMode32F = cvtMode32F.concat(constructMode("COLOR_", "LRGB", ["Lab", "Luv"])); + cvtMode32F = cvtMode32F.concat(constructMode("CX_", "LRGBA", ["Lab", "Luv"])); + cvtMode32F = cvtMode32F.concat(constructMode("COLOR_", "RGB", ["HLS", "HLS_FULL", "HSV", "HSV_FULL", "Lab", "Luv"])); + cvtMode32F = cvtMode32F.concat(constructMode("CX_", "RGBA", ["HLS", "HLS_FULL", "HSV", "HSV_FULL", "Lab", "Luv"])); + + return cvtMode32F; + } - "COLOR_Luv2BGR", "COLOR_Luv2LBGR", "COLOR_Luv2LRGB", "COLOR_Luv2RGB", - "CX_Luv2BGRA", "CX_Luv2LBGRA", "CX_Luv2LRGBA", "CX_Luv2RGBA", + const CvtMode32F = constructCvtMode32F(CvtMode16U); - "COLOR_RGB2GRAY", - "COLOR_RGB2HLS", "COLOR_RGB2HLS_FULL", "COLOR_RGB2HSV", "COLOR_RGB2HSV_FULL", - "COLOR_RGB2Lab", "COLOR_RGB2Luv", "COLOR_RGB2XYZ", "COLOR_RGB2YCrCb", "COLOR_RGB2YUV", + const CvtMode32FSize = [cvSize.szODD, cvSize.szVGA, cvSize.sz1080p]; + const combiCvtMode32F = combine(CvtMode32FSize, CvtMode32F); - "COLOR_RGBA2BGR", "COLOR_RGBA2GRAY", - "CX_RGBA2HLS", "CX_RGBA2HLS_FULL", "CX_RGBA2HSV", "CX_RGBA2HSV_FULL", - "CX_RGBA2Lab", "CX_RGBA2Luv", "CX_RGBA2XYZ", - "CX_RGBA2YCrCb", "CX_RGBA2YUV", + function constructeCvtMode(source) { + let cvtMode = source + cvtMode = cvtMode.concat(constructMode("COLOR_", "BGR", ["BGR555", "BGR565"])); + cvtMode = cvtMode.concat(constructMode("COLOR_", "BGR555", ["BGR", "BGRA", "GRAY", "RGB", "RGBA"])); + cvtMode = cvtMode.concat(constructMode("COLOR_", "BGR565", ["BGR", "BGRA", "GRAY", "RGB", "RGBA"])); + cvtMode = cvtMode.concat(constructMode("COLOR_", "BGRA", ["BGR555", "BGR565"])); + cvtMode = cvtMode.concat(constructMode("COLOR_", "GRAY", ["BGR555", "BGR565"])); + cvtMode = cvtMode.concat(constructMode("COLOR_", "RGB", ["BGR555", "BGR565"])); + cvtMode = cvtMode.concat(constructMode("COLOR_", "RGBA", ["BGR555", "BGR565"])); + + return cvtMode; + } - "COLOR_XYZ2BGR", "COLOR_XYZ2RGB", "CX_XYZ2BGRA", "CX_XYZ2RGBA", + const CvtMode = constructeCvtMode(CvtMode32F); - "COLOR_YCrCb2BGR", "COLOR_YCrCb2RGB", "CX_YCrCb2BGRA", "CX_YCrCb2RGBA", - "COLOR_YUV2BGR", "COLOR_YUV2RGB", "CX_YUV2BGRA", "CX_YUV2RGBA" - ]; - const CvtMode32FSize = [cvSize.szODD, cvSize.szVGA, cvSize.sz1080p]; - const combiCvtMode32F = combine(CvtMode32FSize, CvtMode32F); + const CvtModeSize = [cvSize.szODD, cvSize.szVGA, cvSize.sz1080p]; + // combiCvtMode permute size and mode + const combiCvtMode = combine(CvtModeSize, CvtMode); const CvtModeBayer = [ "COLOR_BayerBG2BGR", "COLOR_BayerBG2BGRA", "COLOR_BayerBG2BGR_VNG", "COLOR_BayerBG2GRAY", @@ -357,7 +308,7 @@ cv.onRuntimeInitialized = () => { return [mat1Type, mat2Type]; } - function addCvtColorCase(suite) { + function addCvtColorCase(suite, type) { suite.add('cvtColor', function() { cv.cvtColor(mat1, mat2, mode, 0); }, { @@ -375,154 +326,22 @@ cv.onRuntimeInitialized = () => { }); } - function addCvtModeCase(suite, combination) { + function addCvtModeCase(suite, combination, type) { totalCaseNum += combination.length; for(let i = 0; i < combination.length; ++i) { let size = combination[i][0]; let mode = combination[i][1]; let chPair = getConversionInfo(mode); let matType = getMatType(chPair); - let sizeArray = [size.width, size.height]; - - addCvtColorCase(suite); - // set init params - let index = suite.length - 1; - suite[index].params = { - size: sizeArray, - matType: matType, - mode: mode - }; - }; - } - - function addCvtModeBayerCase(suite, combination) { - totalCaseNum += combination.length; - for(let i = 0; i < combination.length; ++i) { - let size = combination[i][0]; - let mode = combination[i][1]; - let chPair = getConversionInfo(mode); - let matType = getMatType(chPair); - let sizeArray = [size.width, size.height]; - - addCvtColorCase(suite); - // set init params - let index = suite.length - 1; - suite[index].params = { - size: sizeArray, - matType: matType, - mode: mode - }; - }; - } - - function addCvtMode2Case(suite, combination) { - totalCaseNum += combination.length; - for(let i = 0; i < combination.length; ++i) { - let size = combination[i][0]; - let mode = combination[i][1]; - let chPair = getConversionInfo(mode); - let matType = getMatType(chPair); - let sizeArray = [size.width, size.height+size.height/2]; - - addCvtColorCase(suite); - // set init params - let index = suite.length - 1; - suite[index].params = { - size: sizeArray, - matType: matType, - mode: mode - }; - }; - } - - function addCvtMode3Case(suite, combination) { - totalCaseNum += combination.length; - for(let i = 0; i < combination.length; ++i) { - let size = combination[i][0]; - let mode = combination[i][1]; - let chPair = getConversionInfo(mode); - let matType = getMatType(chPair); - let sizeArray = [size.width, size.height+size.height/2]; - - addCvtColorCase(suite); - // set init params - let index = suite.length - 1; - suite[index].params = { - size: sizeArray, - matType: matType, - mode: mode - }; - }; - } - - function addEdgeAwareBayerModeCase(suite, combination) { - totalCaseNum += combination.length; - for(let i = 0; i < combination.length; ++i) { - let size = combination[i][0]; - let mode = combination[i][1]; - let chPair = getConversionInfo(mode); - let matType = getMatType(chPair); - let sizeArray = [size.width, size.height]; - - addCvtColorCase(suite); - // set init params - let index = suite.length - 1; - suite[index].params = { - size: sizeArray, - matType: matType, - mode: mode - }; - }; - } - - function decodeParams2Case(suite, params) { - let sizeStr = (params.match(/[0-9]+/g) || []).slice(0, 2).toString(); - let mode = (params.match(/CX\_[A-z]+2[A-z]+/) || params.match(/COLOR\_[A-z]+2[A-z]+/) || []).toString(); - let size = cvtStr2cvSize(sizeStr); - - // check if the params match and add case - for (let i = 0; i < combinations.length; ++i) { - let combination = combinations[i]; - for (let j = 0; j < combination.length; ++j) { - if (size === combination[j][0] && mode === combination[j][1]) { - cvtFunc[i](suite, [combination[j]]); - } - } - } - } - - function log(message) { - console.log(message); - if (!isNodeJs) { - logElement.innerHTML += `\n${'\t' + message}`; - } - } - - function setBenchmarkSuite(suite) { - suite - // add listeners - .on('cycle', function(event) { - ++currentCaseId; - let params = event.target.params; - let mode = params.mode; - let size = params.size; - log(`=== ${event.target.name} ${currentCaseId} ===`); - log(`params: (${parseInt(size[0])}x${parseInt(size[1])}, ${mode})`); - log('elapsed time:' +String(event.target.times.elapsed*1000)+' ms'); - log('mean time:' +String(event.target.stats.mean*1000)+' ms'); - log('stddev time:' +String(event.target.stats.deviation*1000)+' ms'); - log(String(event.target)); - }) - .on('error', function(event) { log(`test case ${event.target.name} failed`); }) - .on('complete', function(event) { - log(`\n ###################################`) - log(`Finished testing ${event.currentTarget.length} cases \n`); - if (!isNodeJs) { - runButton.removeAttribute('disabled'); - runButton.setAttribute('class', 'btn btn-primary'); - runButton.innerHTML = 'Run'; + let sizeArray; + if (type == 0) { + sizeArray = [size.width, size.height]; + } else { + sizeArray = [size.width, size.height+size.height/2]; } - }); + let params = {size:sizeArray, matType: matType, mode: mode}; + addKernelCase(suite, params, type, addCvtColorCase); + }; } function genBenchmarkCase(paramsContent) { @@ -531,23 +350,33 @@ cv.onRuntimeInitialized = () => { currentCaseId = 0; if (/\([0-9]+x[0-9]+,[\ ]*\w+\)/g.test(paramsContent.toString())) { let params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+\)/g)[0]; - decodeParams2Case(suite, params); + let paramObjs = []; + paramObjs.push({name:"mode", value:"", reg:["/CX\_[A-z]+2[A-z]+/", "/COLOR\_[A-z]+2[A-z]+/"], index:1}); + paramObjs.push({name:"size", value:"", reg:[""], index:0}); + + let locationList = decodeParams2Case(params, paramObjs,combinations); + for (let i = 0; i < locationList.length; i++){ + let first = locationList[i][0]; + let second = locationList[i][1]; + if (first < 2) { + addCvtModeCase(suite, [combinations[first][second]], 0); + } else { + addCvtModeCase(suite, [combinations[first][second]], 1); + } + } } else { log("no filter or getting invalid params, run all the cases"); - addCvtModeCase(suite, combiCvtMode); - addCvtModeBayerCase(suite, combiCvtModeBayer); - addCvtMode2Case(suite, combiCvtMode2); - addCvtMode3Case(suite, combiCvtMode3); + addCvtModeCase(suite, combiCvtMode, 0); + addCvtModeCase(suite, combiCvtModeBayer, 0); + addCvtModeCase(suite, combiCvtMode2, 1); + addCvtModeCase(suite, combiCvtMode3, 1); } - setBenchmarkSuite(suite); + setBenchmarkSuite(suite, "cvtcolor", currentCaseId); log(`Running ${totalCaseNum} tests from CvtColor`); suite.run({ 'async': true }); // run the benchmark } - - // init - let cvtFunc = [addCvtModeCase, addCvtModeBayerCase, addCvtMode2Case, addCvtMode3Case];//, addEdgeAwareBayerModeCase]; let combinations = [combiCvtMode, combiCvtModeBayer, combiCvtMode2, combiCvtMode3];//, combiEdgeAwareBayer]; // set test filter params @@ -563,10 +392,19 @@ cv.onRuntimeInitialized = () => { let paramsContent = paramsElement.value; genBenchmarkCase(paramsContent); if (totalCaseNum !== 0) { - runButton.setAttribute("disabled", "disabled"); - runButton.setAttribute('class', 'btn btn-primary disabled'); - runButton.innerHTML = "Running"; + disableButton(); } } } -}; \ No newline at end of file +}; + +async function main() { + if (cv instanceof Promise) { + cv = await cv; + perf(); + } else { + cv.onRuntimeInitialized = perf; + } +} + +main(); \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_dilate.html b/modules/js/perf/perf_imgproc/perf_dilate.html new file mode 100644 index 0000000000000000000000000000000000000000..49c61f4be39e468a152ec8ccc6c6a9e5ec301bcd --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_dilate.html @@ -0,0 +1,73 @@ + + + + + OpenCV.js Performance Test + + + + +
+
+
+

OpenCV.js Performance Test

+
+

Modules

+ Image Processing +
+
+

Kernels

+ Dilate +
+
+

Parameters Filter

+ for example: (1024x768, CV_8UC1) +
+
+
+
+
+ + (It will take several minutes)
+
+
+
+

+          
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_dilate.js b/modules/js/perf/perf_imgproc/perf_dilate.js new file mode 100644 index 0000000000000000000000000000000000000000..c4e14c7be2a6dc203d52ea2c0d64c0cc3695c80b --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_dilate.js @@ -0,0 +1,117 @@ +const isNodeJs = (typeof window) === 'undefined'? true : false; + +if (isNodeJs) { + var Benchmark = require('benchmark'); + var cv = require('../../opencv'); + var HelpFunc = require('../perf_helpfunc'); + var Base = require('../base'); +} else { + var paramsElement = document.getElementById('params'); + var runButton = document.getElementById('runButton'); + var logElement = document.getElementById('log'); +} + +function perf() { + + console.log('opencv.js loaded'); + if (isNodeJs) { + global.cv = cv; + global.combine = HelpFunc.combine; + global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize; + global.cvSize = Base.getCvSize(); + } else { + enableButton(); + cvSize = getCvSize(); + } + let totalCaseNum, currentCaseId; + + const DilateSize = [cvSize.szQVGA, cvSize.szVGA, cvSize.szSVGA, cvSize.szXGA, cvSize.szSXGA]; + const DilateType = ["CV_8UC1", "CV_8UC4"]; + const combiDilate = combine(DilateSize, DilateType); + + function addDialteCase(suite, type) { + suite.add('dilate', function() { + cv.dilate(src, dst, kernel); + }, { + 'setup': function() { + let size = this.params.size; + let matType = cv[this.params.matType]; + let src = new cv.Mat(size, matType); + let dst = new cv.Mat(size, matType); + let kernel = new cv.Mat(); + }, + 'teardown': function() { + src.delete(); + dst.delete(); + kernel.delete(); + } + }); + } + + function addDilateModeCase(suite, combination, type) { + totalCaseNum += combination.length; + for (let i = 0; i < combination.length; ++i) { + let size = combination[i][0]; + let matType = combination[i][1]; + + let params = {size: size, matType:matType}; + addKernelCase(suite, params, type, addDialteCase); + } + } + + function genBenchmarkCase(paramsContent) { + let suite = new Benchmark.Suite; + totalCaseNum = 0; + currentCaseId = 0; + + if (/\([0-9]+x[0-9]+,[\ ]*CV\_\w+\)/g.test(paramsContent.toString())) { + let params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*CV\_\w+\)/g)[0]; + let paramObjs = []; + paramObjs.push({name:"size", value:"", reg:[""], index:0}); + paramObjs.push({name:"matType", value:"", reg:["/CV\_[0-9]+[FSUfsu]C[0-9]/"], index:1}); + let locationList = decodeParams2Case(params, paramObjs, dilateCombinations); + + for (let i = 0; i < locationList.length; i++){ + let first = locationList[i][0]; + let second = locationList[i][1]; + addDilateModeCase(suite, [dilateCombinations[first][second]], first); + } + } else { + log("no filter or getting invalid params, run all the cases"); + addDilateModeCase(suite, combiDilate, 0); + } + setBenchmarkSuite(suite, "dilate", currentCaseId); + log(`Running ${totalCaseNum} tests from dilate`); + suite.run({ 'async': true }); // run the benchmark + } + + let dilateCombinations = [combiDilate]; + + if (isNodeJs) { + const args = process.argv.slice(2); + let paramsContent = ''; + if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*CV\_\w+\)/g.test(args.toString())) { + paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*CV\_\w+\)/g)[0]; + } + genBenchmarkCase(paramsContent); + } else { + runButton.onclick = function() { + let paramsContent = paramsElement.value; + genBenchmarkCase(paramsContent); + if (totalCaseNum !== 0) { + disableButton(); + } + } + } +}; + +async function main() { + if (cv instanceof Promise) { + cv = await cv; + perf(); + } else { + cv.onRuntimeInitialized = perf; + } +} + +main(); \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_erode.html b/modules/js/perf/perf_imgproc/perf_erode.html new file mode 100644 index 0000000000000000000000000000000000000000..2db653bd7a2d96989874e350582ff155a8f9e0a2 --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_erode.html @@ -0,0 +1,73 @@ + + + + + OpenCV.js Performance Test + + + + +
+
+
+

OpenCV.js Performance Test

+
+

Modules

+ Image Processing +
+
+

Kernels

+ Erode +
+
+

Parameters Filter

+ for example: (1024x768, CV_8UC1) +
+
+
+
+
+ + (It will take several minutes)
+
+
+
+

+          
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_erode.js b/modules/js/perf/perf_imgproc/perf_erode.js new file mode 100644 index 0000000000000000000000000000000000000000..95aba6fa218d2cac32ee8f9fb51fd8d58ad108c0 --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_erode.js @@ -0,0 +1,117 @@ +const isNodeJs = (typeof window) === 'undefined'? true : false; + +if (isNodeJs) { + var Benchmark = require('benchmark'); + var cv = require('../../opencv'); + var HelpFunc = require('../perf_helpfunc'); + var Base = require('../base'); +} else { + var paramsElement = document.getElementById('params'); + var runButton = document.getElementById('runButton'); + var logElement = document.getElementById('log'); +} + +function perf() { + + console.log('opencv.js loaded'); + if (isNodeJs) { + global.cv = cv; + global.combine = HelpFunc.combine; + global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize; + global.cvSize = Base.getCvSize(); + } else { + enableButton(); + cvSize = getCvSize(); + } + let totalCaseNum, currentCaseId; + + const ErodeSize = [cvSize.szQVGA, cvSize.szVGA, cvSize.szSVGA, cvSize.szXGA, cvSize.szSXGA]; + const ErodeType = ["CV_8UC1", "CV_8UC4"]; + const combiErode = combine(ErodeSize, ErodeType); + + function addErodeCase(suite, type) { + suite.add('erode', function() { + cv.erode(src, dst, kernel); + }, { + 'setup': function() { + let size = this.params.size; + let matType = cv[this.params.matType]; + let src = new cv.Mat(size, matType); + let dst = new cv.Mat(size, matType); + let kernel = new cv.Mat(); + }, + 'teardown': function() { + src.delete(); + dst.delete(); + kernel.delete(); + } + }); + } + + function addErodeModeCase(suite, combination, type) { + totalCaseNum += combination.length; + for (let i = 0; i < combination.length; ++i) { + let size = combination[i][0]; + let matType = combination[i][1]; + + let params = {size: size, matType:matType}; + addKernelCase(suite, params, type, addErodeCase); + } + } + + function genBenchmarkCase(paramsContent) { + let suite = new Benchmark.Suite; + totalCaseNum = 0; + currentCaseId = 0; + + if (/\([0-9]+x[0-9]+,[\ ]*CV\_\w+\)/g.test(paramsContent.toString())) { + let params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*CV\_\w+\)/g)[0]; + let paramObjs = []; + paramObjs.push({name:"size", value:"", reg:[""], index:0}); + paramObjs.push({name:"matType", value:"", reg:["/CV\_[0-9]+[FSUfsu]C[0-9]/"], index:1}); + let locationList = decodeParams2Case(params, paramObjs, erodeCombinations); + + for (let i = 0; i < locationList.length; i++){ + let first = locationList[i][0]; + let second = locationList[i][1]; + addErodeModeCase(suite, [erodeCombinations[first][second]], first); + } + } else { + log("no filter or getting invalid params, run all the cases"); + addErodeModeCase(suite, combiErode, 0); + } + setBenchmarkSuite(suite, "erode", currentCaseId); + log(`Running ${totalCaseNum} tests from erode`); + suite.run({ 'async': true }); // run the benchmark + } + + let erodeCombinations = [combiErode]; + + if (isNodeJs) { + const args = process.argv.slice(2); + let paramsContent = ''; + if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*CV\_\w+\)/g.test(args.toString())) { + paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*CV\_\w+\)/g)[0]; + } + genBenchmarkCase(paramsContent); + } else { + runButton.onclick = function() { + let paramsContent = paramsElement.value; + genBenchmarkCase(paramsContent); + if (totalCaseNum !== 0) { + disableButton(); + } + } + } +}; + +async function main() { + if (cv instanceof Promise) { + cv = await cv; + perf(); + } else { + cv.onRuntimeInitialized = perf; + } +} + +main(); \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_filter2D.html b/modules/js/perf/perf_imgproc/perf_filter2D.html new file mode 100644 index 0000000000000000000000000000000000000000..347fa8076dcd55d614224329e0a067efc099fa1c --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_filter2D.html @@ -0,0 +1,73 @@ + + + + + OpenCV.js Performance Test + + + + +
+
+
+

OpenCV.js Performance Test

+
+

Modules

+ Image Processing +
+
+

Kernels

+ Filter2D +
+
+

Parameters Filter

+ for example: (320x240, 3, BORDER_CONSTANT) +
+
+
+
+
+ + (It will take several minutes)
+
+
+
+

+          
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_filter2D.js b/modules/js/perf/perf_imgproc/perf_filter2D.js new file mode 100644 index 0000000000000000000000000000000000000000..d92dc2b55af76db82b3d776200297e2f46e8e90b --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_filter2D.js @@ -0,0 +1,127 @@ +const isNodeJs = (typeof window) === 'undefined'? true : false; + +if (isNodeJs) { + var Benchmark = require('benchmark'); + var cv = require('../../opencv'); + var HelpFunc = require('../perf_helpfunc'); + var Base = require('../base'); +} else { + var paramsElement = document.getElementById('params'); + var runButton = document.getElementById('runButton'); + var logElement = document.getElementById('log'); +} + +function perf() { + + console.log('opencv.js loaded'); + if (isNodeJs) { + global.cv = cv; + global.combine = HelpFunc.combine; + global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize; + global.cvSize = Base.getCvSize(); + } else { + enableButton(); + cvSize = getCvSize(); + } + let totalCaseNum, currentCaseId; + + const Filter2dSize = [cvSize.szQVGA, cvSize.sz1080p]; + const Filter2dKsize = ["3", "5"]; + const Filter2dBorderMode = ["BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT_101"]; + const DISABLED_Filter2dBorderMode = ["BORDER_CONSTANT", "BORDER_REPLICATE"]; + const combiFilter2dCase = combine(Filter2dSize, Filter2dKsize, Filter2dBorderMode); + const combiDISABLEDFilter2dCase = combine(Filter2dSize, Filter2dKsize, DISABLED_Filter2dBorderMode); + + function addFilter2dCase(suite, type) { + suite.add('filter2d', function() { + cv.filter2D(src, dst, cv.CV_8UC4, kernel, new cv.Point(1, 1), 0.0, borderMode); + }, { + 'setup': function() { + let size = this.params.size; + let ksize = parseInt(this.params.ksize); + let borderMode = cv[this.params.borderMode]; + + let src = new cv.Mat(size, cv.CV_8UC4); + let dst = new cv.Mat(size, cv.CV_8UC4); + let kernelElement = []; + for (let i = 0; i < ksize*ksize; i++) { + let randNum = Math.random(); + kernelElement.push(-3.0+randNum*13.0); + } + let kernel = cv.matFromArray(ksize, ksize, cv.CV_32FC1, kernelElement); + }, + 'teardown': function() { + src.delete(); + dst.delete(); + } + }); + } + + function addFilter2dModeCase(suite, combination, type) { + totalCaseNum += combination.length; + for (let i = 0; i < combination.length; ++i) { + let size = combination[i][0]; + let ksize = combination[i][1]; + let borderMode = combination[i][2]; + let params = {size: size, ksize: ksize, borderMode:borderMode}; + addKernelCase(suite, params, type, addFilter2dCase); + } + } + + function genBenchmarkCase(paramsContent) { + let suite = new Benchmark.Suite; + totalCaseNum = 0; + currentCaseId = 0; + + if (/\([0-9]+x[0-9]+,[\ ]*[0-9],[\ ]*BORDER\_\w+\)/g.test(paramsContent.toString())) { + let params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*[0-9],[\ ]*BORDER\_\w+\)/g)[0]; + let paramObjs = []; + paramObjs.push({name:"size", value:"", reg:[""], index:0}); + paramObjs.push({name:"ksize", value:"", reg:["/\\b[0-9]\\b/"], index:1}); + paramObjs.push({name:"borderMode", value: "", reg:["/BORDER\_\\w+/"], index:2}); + let locationList = decodeParams2Case(params, paramObjs,filter2dCombinations); + + for (let i = 0; i < locationList.length; i++){ + let first = locationList[i][0]; + let second = locationList[i][1]; + addFilter2dModeCase(suite, [filter2dCombinations[first][second]], 0); + } + } else { + log("no filter or getting invalid params, run all the cases"); + addFilter2dModeCase(suite, combiFilter2dCase, 0); + } + setBenchmarkSuite(suite, "filter2d", currentCaseId); + log(`Running ${totalCaseNum} tests from Filter2d`); + suite.run({ 'async': true }); // run the benchmark + } + + let filter2dCombinations = [combiFilter2dCase];//,combiDISABLEDFilter2dCase]; + + if (isNodeJs) { + const args = process.argv.slice(2); + let paramsContent = ''; + if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*[0-9],[\ ]*BORDER\_\w+\)/g.test(args.toString())) { + paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*[0-9],[\ ]*BORDER\_\w+\)/g)[0]; + } + genBenchmarkCase(paramsContent); + } else { + runButton.onclick = function() { + let paramsContent = paramsElement.value; + genBenchmarkCase(paramsContent); + if (totalCaseNum !== 0) { + disableButton(); + } + } + } +}; + +async function main() { + if (cv instanceof Promise) { + cv = await cv; + perf(); + } else { + cv.onRuntimeInitialized = perf; + } +} + +main(); \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_gaussianBlur.html b/modules/js/perf/perf_imgproc/perf_gaussianBlur.html new file mode 100644 index 0000000000000000000000000000000000000000..3f56c22f7ddefefbe545d04dac1e4f7042790d3d --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_gaussianBlur.html @@ -0,0 +1,73 @@ + + + + + OpenCV.js Performance Test + + + + +
+
+
+

OpenCV.js Performance Test

+
+

Modules

+ Image Processing +
+
+

Kernels

+ gaussianBlur +
+
+

Parameters Filter

+ for example: (1280x720, CV_8UC1, BORDER_REPLICATE) +
+
+
+
+
+ + (It will take several minutes)
+
+
+
+

+          
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_gaussianBlur.js b/modules/js/perf/perf_imgproc/perf_gaussianBlur.js new file mode 100644 index 0000000000000000000000000000000000000000..33c5401a7ed091584623cec51e2fab8dae103ace --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_gaussianBlur.js @@ -0,0 +1,126 @@ +const isNodeJs = (typeof window) === 'undefined'? true : false; + +if (isNodeJs) { + var Benchmark = require('benchmark'); + var cv = require('../../opencv'); + var HelpFunc = require('../perf_helpfunc'); + var Base = require('../base'); +} else { + var paramsElement = document.getElementById('params'); + var runButton = document.getElementById('runButton'); + var logElement = document.getElementById('log'); +} + +function perf() { + + console.log('opencv.js loaded'); + if (isNodeJs) { + global.cv = cv; + global.combine = HelpFunc.combine; + global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize; + global.cvSize = Base.getCvSize(); + } else { + enableButton(); + cvSize = getCvSize(); + } + let totalCaseNum, currentCaseId; + + const GaussianBlurSize = [cvSize.szODD, cvSize.szQVGA, cvSize.szVGA, cvSize.sz720p]; + const GaussianBlurType = ["CV_8UC1", "CV_8UC4", "CV_16UC1", "CV_16SC1", "CV_32FC1"]; + const BorderType3x3 = ["BORDER_REPLICATE", "BORDER_CONSTANT"]; + const BorderType3x3ROI = ["BORDER_REPLICATE", "BORDER_CONSTANT", "BORDER_REFLECT", "BORDER_REFLECT101"]; + + const combiGaussianBlurBorder3x3 = combine(GaussianBlurSize, GaussianBlurType, BorderType3x3); + const combiGaussianBlurBorder3x3ROI = combine(GaussianBlurSize, GaussianBlurType, BorderType3x3ROI); + + function addGaussianBlurCase(suite, type) { + suite.add('gaussianBlur', function() { + cv.GaussianBlur(src, dst, ksize, 1, 0, borderType); + }, { + 'setup': function() { + let size = this.params.size; + let matType = cv[this.params.matType]; + let borderType = cv[this.params.borderType]; + let type = this.params.type; + let src = new cv.Mat(size, matType); + let dst = new cv.Mat(size, matType); + let ksizeNum = this.params.ksize; + let ksize = new cv.Size(ksizeNum, ksizeNum); + }, + 'teardown': function() { + src.delete(); + dst.delete(); + } + }); + } + + function addGaussianBlurModeCase(suite, combination, type) { + totalCaseNum += combination.length; + for (let i = 0; i < combination.length; ++i) { + let size = combination[i][0]; + let matType = combination[i][1]; + let borderType = combination[i][2]; + let ksizeArray = [3, 5]; + let params = {size: size, matType:matType, ksize: ksizeArray[type], borderType:borderType}; + addKernelCase(suite, params, type, addGaussianBlurCase); + } + } + + function genBenchmarkCase(paramsContent) { + let suite = new Benchmark.Suite; + totalCaseNum = 0; + currentCaseId = 0; + + if (/\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*BORDER\_\w+\)/g.test(paramsContent.toString())) { + let params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*BORDER\_\w+\)/g)[0]; + let paramObjs = []; + paramObjs.push({name:"size", value:"", reg:[""], index:0}); + paramObjs.push({name:"matType", value:"", reg:["/CV\_[0-9]+[FSUfsu]C[0-9]/"], index:1}); + paramObjs.push({name:"borderMode", value: "", reg:["/BORDER\_\\w+/"], index:2}); + let locationList = decodeParams2Case(params, paramObjs,gaussianBlurCombinations); + + for (let i = 0; i < locationList.length; i++){ + let first = locationList[i][0]; + let second = locationList[i][1]; + addGaussianBlurModeCase(suite, [gaussianBlurCombinations[first][second]], first); + } + } else { + log("no filter or getting invalid params, run all the cases"); + addGaussianBlurModeCase(suite, combiGaussianBlurBorder3x3, 0); + addGaussianBlurModeCase(suite, combiGaussianBlurBorder3x3ROI, 1); + } + setBenchmarkSuite(suite, "gaussianBlur", currentCaseId); + log(`Running ${totalCaseNum} tests from gaussianBlur`); + suite.run({ 'async': true }); // run the benchmark + } + + let gaussianBlurCombinations = [combiGaussianBlurBorder3x3, combiGaussianBlurBorder3x3ROI]; + + if (isNodeJs) { + const args = process.argv.slice(2); + let paramsContent = ''; + if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*BORDER\_\w+\)/g.test(args.toString())) { + paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*BORDER\_\w+\)/g)[0]; + } + genBenchmarkCase(paramsContent); + } else { + runButton.onclick = function() { + let paramsContent = paramsElement.value; + genBenchmarkCase(paramsContent); + if (totalCaseNum !== 0) { + disableButton(); + } + } + } +}; + +async function main() { + if (cv instanceof Promise) { + cv = await cv; + perf(); + } else { + cv.onRuntimeInitialized = perf; + } +} + +main(); \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_medianBlur.html b/modules/js/perf/perf_imgproc/perf_medianBlur.html new file mode 100644 index 0000000000000000000000000000000000000000..6e390beec26be042a259113f73e27d49395c5a33 --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_medianBlur.html @@ -0,0 +1,73 @@ + + + + + OpenCV.js Performance Test + + + + +
+
+
+

OpenCV.js Performance Test

+
+

Modules

+ Image Processing +
+
+

Kernels

+ MedianBlur +
+
+

Parameters Filter

+ for example: (1280x720, CV_8UC1, 3) +
+
+
+
+
+ + (It will take several minutes)
+
+
+
+

+          
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_medianBlur.js b/modules/js/perf/perf_imgproc/perf_medianBlur.js new file mode 100644 index 0000000000000000000000000000000000000000..69b7ba3ead0d51d2b1fbc2d8f920fb49b6471492 --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_medianBlur.js @@ -0,0 +1,118 @@ +const isNodeJs = (typeof window) === 'undefined'? true : false; + +if (isNodeJs) { + var Benchmark = require('benchmark'); + var cv = require('../../opencv'); + var HelpFunc = require('../perf_helpfunc'); + var Base = require('../base'); +} else { + var paramsElement = document.getElementById('params'); + var runButton = document.getElementById('runButton'); + var logElement = document.getElementById('log'); +} + +function perf() { + + console.log('opencv.js loaded'); + if (isNodeJs) { + global.cv = cv; + global.combine = HelpFunc.combine; + global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize; + global.cvSize = Base.getCvSize(); + } else { + enableButton(); + cvSize = getCvSize(); + } + let totalCaseNum, currentCaseId; + + const MedianBlurSize = [cvSize.szODD, cvSize.szQVGA, cvSize.szVGA, cvSize.sz720p]; + const MedianBlurType = ["CV_8UC1", "CV_8UC4", "CV_16UC1", "CV_16SC1", "CV_32FC1"]; + const combiMedianBlur = combine(MedianBlurSize, MedianBlurType, [3,5]); + + function addMedianBlurCase(suite, type) { + suite.add('medianBlur', function() { + cv.medianBlur(src, dst, ksize); + }, { + 'setup': function() { + let size = this.params.size; + let matType = cv[this.params.matType]; + let ksize = this.params.ksize; + let src = new cv.Mat(size, matType); + let dst = new cv.Mat(size, matType); + }, + 'teardown': function() { + src.delete(); + dst.delete(); + } + }); + } + + function addMedianBlurModeCase(suite, combination, type) { + totalCaseNum += combination.length; + for (let i = 0; i < combination.length; ++i) { + let size = combination[i][0]; + let matType = combination[i][1]; + let ksize = combination[i][2]; + + let params = {size: size, matType:matType, ksize: ksize}; + addKernelCase(suite, params, type, addMedianBlurCase); + } + } + + function genBenchmarkCase(paramsContent) { + let suite = new Benchmark.Suite; + totalCaseNum = 0; + currentCaseId = 0; + + if (/\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*(3|5)\)/g.test(paramsContent.toString())) { + let params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*(3|5)\)/g)[0]; + let paramObjs = []; + paramObjs.push({name:"size", value:"", reg:[""], index:0}); + paramObjs.push({name:"matType", value:"", reg:["/CV\_[0-9]+[FSUfsu]C[0-9]/"], index:1}); + paramObjs.push({name:"ksize", value: "", reg:["/\\b[0-9]\\b/"], index:2}); + let locationList = decodeParams2Case(params, paramObjs, medianBlurCombinations); + + for (let i = 0; i < locationList.length; i++){ + let first = locationList[i][0]; + let second = locationList[i][1]; + addMedianBlurModeCase(suite, [medianBlurCombinations[first][second]], first); + } + } else { + log("no filter or getting invalid params, run all the cases"); + addMedianBlurModeCase(suite, combiMedianBlur, 0); + } + setBenchmarkSuite(suite, "medianBlur", currentCaseId); + log(`Running ${totalCaseNum} tests from medianBlur`); + suite.run({ 'async': true }); // run the benchmark + } + + let medianBlurCombinations = [combiMedianBlur]; + + if (isNodeJs) { + const args = process.argv.slice(2); + let paramsContent = ''; + if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*(3|5)\)/g.test(args.toString())) { + paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*(3|5)\)/g)[0]; + } + genBenchmarkCase(paramsContent); + } else { + runButton.onclick = function() { + let paramsContent = paramsElement.value; + genBenchmarkCase(paramsContent); + if (totalCaseNum !== 0) { + disableButton(); + } + } + } +}; + +async function main() { + if (cv instanceof Promise) { + cv = await cv; + perf(); + } else { + cv.onRuntimeInitialized = perf; + } +} + +main(); \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_pyrDown.html b/modules/js/perf/perf_imgproc/perf_pyrDown.html new file mode 100644 index 0000000000000000000000000000000000000000..f90ac5f55e515b034383da7b862c8b819a79207c --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_pyrDown.html @@ -0,0 +1,73 @@ + + + + + OpenCV.js Performance Test + + + + +
+
+
+

OpenCV.js Performance Test

+
+

Modules

+ Image Processing +
+
+

Kernels

+ pyrDown +
+
+

Parameters Filter

+ for example: (1920x1080, CV_8UC3) +
+
+
+
+
+ + (It will take several minutes)
+
+
+
+

+          
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_pyrDown.js b/modules/js/perf/perf_imgproc/perf_pyrDown.js new file mode 100644 index 0000000000000000000000000000000000000000..a98b109ade70415a623797a711108b529fc6c6a5 --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_pyrDown.js @@ -0,0 +1,116 @@ +const isNodeJs = (typeof window) === 'undefined'? true : false; + +if (isNodeJs) { + var Benchmark = require('benchmark'); + var cv = require('../../opencv'); + var HelpFunc = require('../perf_helpfunc'); + var Base = require('../base'); +} else { + var paramsElement = document.getElementById('params'); + var runButton = document.getElementById('runButton'); + var logElement = document.getElementById('log'); +} + +function perf() { + + console.log('opencv.js loaded'); + if (isNodeJs) { + global.cv = cv; + global.combine = HelpFunc.combine; + global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize; + global.cvSize = Base.getCvSize(); + } else { + enableButton(); + cvSize = getCvSize(); + } + let totalCaseNum, currentCaseId; + + const PyrDownSize = [cvSize.sz1080p, cvSize.sz720p, cvSize.szVGA, cvSize.szQVGA, cvSize.szODD]; + const PyrDownType = ["CV_8UC1", "CV_8UC3", "CV_8UC4", "CV_16SC1", "CV_16SC3", "CV_16SC4", "CV_32FC1", "CV_32FC3", "CV_32FC4"]; + + const combiPyrDown = combine(PyrDownSize, PyrDownType); + + function addPryDownCase(suite, type) { + suite.add('pyrDown', function() { + cv.pyrDown(src, dst); + }, { + 'setup': function() { + let size = this.params.size; + let matType = cv[this.params.matType]; + let src = new cv.Mat(size, matType); + let dst = new cv.Mat((size.height + 1)/2, (size.height + 1)/2, matType) + }, + 'teardown': function() { + src.delete(); + dst.delete(); + } + }); + } + + function addPyrDownModeCase(suite, combination, type) { + totalCaseNum += combination.length; + for (let i = 0; i < combination.length; ++i) { + let size = combination[i][0]; + let matType = combination[i][1]; + + let params = {size: size, matType:matType}; + addKernelCase(suite, params, type, addPryDownCase); + } + } + + function genBenchmarkCase(paramsContent) { + let suite = new Benchmark.Suite; + totalCaseNum = 0; + currentCaseId = 0; + + if (/\([0-9]+x[0-9]+,[\ ]*CV\_\w+\)/g.test(paramsContent.toString())) { + let params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*CV\_\w+\)/g)[0]; + let paramObjs = []; + paramObjs.push({name:"size", value:"", reg:[""], index:0}); + paramObjs.push({name:"matType", value:"", reg:["/CV\_[0-9]+[FSUfsu]C[0-9]/"], index:1}); + let locationList = decodeParams2Case(params, paramObjs, pyrDownCombinations); + + for (let i = 0; i < locationList.length; i++){ + let first = locationList[i][0]; + let second = locationList[i][1]; + addPyrDownModeCase(suite, [pyrDownCombinations[first][second]], first); + } + } else { + log("no filter or getting invalid params, run all the cases"); + addPyrDownModeCase(suite, combiPyrDown, 0); + } + setBenchmarkSuite(suite, "pyrDown", currentCaseId); + log(`Running ${totalCaseNum} tests from pyrDown`); + suite.run({ 'async': true }); // run the benchmark + } + + let pyrDownCombinations = [combiPyrDown]; + + if (isNodeJs) { + const args = process.argv.slice(2); + let paramsContent = ''; + if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*CV\_\w+\)/g.test(args.toString())) { + paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*CV\_\w+\)/g)[0]; + } + genBenchmarkCase(paramsContent); + } else { + runButton.onclick = function() { + let paramsContent = paramsElement.value; + genBenchmarkCase(paramsContent); + if (totalCaseNum !== 0) { + disableButton(); + } + } + } +}; + +async function main() { + if (cv instanceof Promise) { + cv = await cv; + perf(); + } else { + cv.onRuntimeInitialized = perf; + } +} + +main(); \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_remap.html b/modules/js/perf/perf_imgproc/perf_remap.html new file mode 100644 index 0000000000000000000000000000000000000000..6812adb0a0a31337ce8105e155315cd19cbe2487 --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_remap.html @@ -0,0 +1,73 @@ + + + + + OpenCV.js Performance Test + + + + +
+
+
+

OpenCV.js Performance Test

+
+

Modules

+ Image Processing +
+
+

Kernels

+ Remap +
+
+

Parameters Filter

+ for example: (640x480, CV_16UC1, CV_16SC2, INTER_NEAREST) +
+
+
+
+
+ + (It will take several minutes)
+
+
+
+

+          
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_remap.js b/modules/js/perf/perf_imgproc/perf_remap.js new file mode 100644 index 0000000000000000000000000000000000000000..fe2e5d75411b088068d39e76df2a903834189267 --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_remap.js @@ -0,0 +1,182 @@ +const isNodeJs = (typeof window) === 'undefined'? true : false; + +if (isNodeJs) { + var Benchmark = require('benchmark'); + var cv = require('../../opencv'); + var HelpFunc = require('../perf_helpfunc'); + var Base = require('../base'); +} else { + var paramsElement = document.getElementById('params'); + var runButton = document.getElementById('runButton'); + var logElement = document.getElementById('log'); +} + +function perf() { + + console.log('opencv.js loaded'); + if (isNodeJs) { + global.cv = cv; + global.combine = HelpFunc.combine; + global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize; + global.cvSize = Base.getCvSize(); + } else { + enableButton(); + cvSize = getCvSize(); + } + let totalCaseNum, currentCaseId; + + const RemapSize = [cvSize.szVGA, cvSize.sz1080p]; + const RemapSrcType = ["CV_16UC1", "CV_16SC1", "CV_32FC1"]; + const RemapType = ["CV_16SC2", "CV_32FC1", "CV_32FC2"]; + const InterType = ["INTER_NEAREST", "INTER_LINEAR", "INTER_CUBIC", "INTER_LANCZOS4"]; + const combiRemap = combine(RemapSize, RemapSrcType, RemapType, InterType); + + function addRemapCase(suite, type) { + suite.add('remap', function() { + cv.remap(src, dst, map1, map2, interType); + }, { + 'setup': function() { + let size = this.params.size; + let matType = cv[this.params.matType]; + let mapType = cv[this.params.mapType]; + let interType = cv[this.params.interType]; + + + let src = new cv.Mat(size, matType); + let dst = new cv.Mat(size, matType); + let map1 = new cv.Mat(size, mapType); + let map2; + if (mapType == cv.CV_32FC1) { + map2 = new cv.Mat(size, mapType); + } else if (interType != cv.INTER_NEAREST && mapType == cv.CV_16SC2) { + map2 = new cv.Mat.zeros(size, cv.CV_16UC1); + } else { + map2 = new cv.Mat(); + } + + for (let j = 0; j < map1.rows; j++) { + for (let i = 0; i < map1.cols; i++) { + let randNum = Math.random(); + let view, view1; + switch(matType) { + case cv.CV_16UC1: + view = src.ushortPtr(j,i); + view[0] = Math.floor(randNum*256); + break; + case cv.CV_16SC1: + view = src.shortPtr(j,i); + view[0] = Math.floor(randNum*256); + break; + case cv.CV_32FC1: + view = src.floatPtr(j,i); + view[0] = randNum*256; + break; + default: + console.error("Unknown conversion type 1"); + break; + } + + switch(mapType) { + case cv.CV_32FC1: + view1 = map1.floatPtr(j,i); + let view2 = map2.floatPtr(j,i); + view1[0] = src.cols - i - 1; + view2[0] = j; + break; + case cv.CV_32FC2: + view1 = map1.floatPtr(j,i); + view1[0] = src.cols - i - 1; + view1[1] = j; + break; + case cv.CV_16SC2: + view1 = map1.shortPtr(j,i); + view1[0] = src.cols - i - 1; + view1[1] = j; + break; + default: + console.error("Unknown conversion type 2"); + break; + } + } + } + }, + 'teardown': function() { + src.delete(); + dst.delete(); + map1.delete(); + map2.delete(); + } + }); + } + + function addRemapModeCase(suite, combination, type) { + totalCaseNum += combination.length; + for (let i = 0; i < combination.length; ++i) { + let size = combination[i][0]; + let matType = combination[i][1]; + let mapType = combination[i][2]; + let interType = combination[i][3]; + + let params = {size: size, matType:matType, mapType:mapType, interType:interType}; + addKernelCase(suite, params, type, addRemapCase); + } + } + + function genBenchmarkCase(paramsContent) { + let suite = new Benchmark.Suite; + totalCaseNum = 0; + currentCaseId = 0; + + if (/\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*CV\_\w+,[\ ]*INTER\_\w+\)/g.test(paramsContent.toString())) { + let params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*CV\_\w+,[\ ]*INTER\_\w+\)/g)[0]; + let paramObjs = []; + paramObjs.push({name:"size", value:"", reg:[""], index:0}); + paramObjs.push({name:"matType", value:"", reg:["/CV\_[0-9]+[FSUfsu]C[0-9]/"], index:1}); + paramObjs.push({name:"mapType", value:"", reg:["/CV\_[0-9]+[FSUfsu]C[0-9]/g"], index:2, loc:1}); + paramObjs.push({name:"interType", value: "", reg:["/INTER\_\\w+/"], index:3}); + let locationList = decodeParams2Case(params, paramObjs, remapCombinations); + + for (let i = 0; i < locationList.length; i++){ + let first = locationList[i][0]; + let second = locationList[i][1]; + addRemapModeCase(suite, [remapCombinations[first][second]], first); + } + } else { + log("no filter or getting invalid params, run all the cases"); + addRemapModeCase(suite, combiRemap, 0); + } + setBenchmarkSuite(suite, "remap", currentCaseId); + log(`Running ${totalCaseNum} tests from remap`); + suite.run({ 'async': true }); // run the benchmark + } + + let remapCombinations = [combiRemap]; + + if (isNodeJs) { + const args = process.argv.slice(2); + let paramsContent = ''; + if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*CV\_\w+,[\ ]*INTER\_\w+\)/g.test(args.toString())) { + paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*CV\_\w+,[\ ]*INTER\_\w+\)/g)[0]; + } + genBenchmarkCase(paramsContent); + } else { + runButton.onclick = function() { + let paramsContent = paramsElement.value; + genBenchmarkCase(paramsContent); + if (totalCaseNum !== 0) { + disableButton(); + } + } + } +}; + +async function main() { + if (cv instanceof Promise) { + cv = await cv; + perf(); + } else { + cv.onRuntimeInitialized = perf; + } +} + +main(); \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_resize.js b/modules/js/perf/perf_imgproc/perf_resize.js index 4e71db3806fc0a675d1d055a99add008552f6d3a..3eef30f0e3f890336a9fe66d41036ab3fc1d6505 100644 --- a/modules/js/perf/perf_imgproc/perf_resize.js +++ b/modules/js/perf/perf_imgproc/perf_resize.js @@ -11,18 +11,17 @@ if (isNodeJs) { var logElement = document.getElementById('log'); } -cv.onRuntimeInitialized = () => { +function perf() { + console.log('opencv.js loaded'); if (isNodeJs) { global.cv = cv; global.combine = HelpFunc.combine; - global.fillGradient = HelpFunc.fillGradient; global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize; - global.cvSize = Base.cvSize; + global.cvSize = Base.getCvSize(); } else { - runButton.removeAttribute('disabled'); - runButton.setAttribute('class', 'btn btn-primary'); - runButton.innerHTML = 'Run'; + enableButton(); + cvSize = getCvSize(); } let totalCaseNum, currentCaseId; @@ -59,185 +58,80 @@ cv.onRuntimeInitialized = () => { const scalesAreaFast = [2]; const combiAreaFast = combine(matTypesAreaFast, sizesAreaFast, scalesAreaFast); - function addResizeUpLinearCase(suite, combination) { - totalCaseNum += combination.length; - for (let i = 0; i < combination.length; ++i) { - let matType = combination[i][0]; - let from = combination[i][1]; - let to = combination[i][2]; - - suite.add('resize', function() { - cv.resize(src, dst, to, 0, 0, cv.INTER_LINEAR_EXACT); - }, { - 'setup': function() { - let from = this.params.from; - let to = this.params.to; - let matType = cv[this.params.matType]; - let src = new cv.Mat(from, matType); - let dst = new cv.Mat(to, matType); - fillGradient(cv, src); - }, - 'teardown': function() { - src.delete(); - dst.delete(); - } - }); - - // set init params - let index = suite.length - 1; - suite[index].params = { - from: from, - to: to, - matType: matType - }; - } - } - - function addResizeDownLinearCase(suite, combination) { - totalCaseNum += combination.length; - for (let i = 0; i < combination.length; ++i) { - let matType = combination[i][0]; - let from = combination[i][1]; - let to = combination[i][2]; - - suite.add('resize', function() { + function addResizeCase(suite, type) { + suite.add('resize', function() { + if (type == "area") { + cv.resize(src, dst, dst.size(), 0, 0, cv.INTER_AREA); + } else { cv.resize(src, dst, to, 0, 0, cv.INTER_LINEAR_EXACT); - }, { - 'setup': function() { - let from = this.params.from; - let to = this.params.to; - let matType = cv[this.params.matType]; - let src = new cv.Mat(from, matType); - let dst = new cv.Mat(to, matType); + } + }, { + 'setup': function() { + let from = this.params.from; + let to = this.params.to; + let matType = cv[this.params.matType]; + let src = new cv.Mat(from, matType); + let type = this.params.modeType; + let dst; + if (type == "area") { + dst = new cv.Mat(from.height/scale, from.width/scale, matType); + } else { + dst = new cv.Mat(to, matType); fillGradient(cv, src); - }, - 'teardown': function() { - src.delete(); - dst.delete(); } - }); - - // set init params - let index = suite.length - 1; - suite[index].params = { - from: from, - to: to, - matType: matType - }; - } + }, + 'teardown': function() { + src.delete(); + dst.delete(); + } + }); } - function addResizeAreaFastCase(suite, combination) { + function addResizeModeCase(suite, combination, type) { totalCaseNum += combination.length; for (let i = 0; i < combination.length; ++i) { let matType = combination[i][0]; let from = combination[i][1]; - let scale = combination[i][2]; - from.width = (Math.floor(from.width/scale))*scale; - from.height = (Math.floor(from.height/scale))*scale; - let to = { - width: from.width/scale, - height: from.height/scale}; // for params print - - suite.add('resize', function() { - cv.resize(src, dst, dst.size(), 0, 0, cv.INTER_AREA); - }, { - 'setup': function() { - let from = this.params.from; - let scale = this.params.scale; - let matType = cv[this.params.matType]; - let src = new cv.Mat(from, matType); - let dst = new cv.Mat(from.height/scale, from.width/scale, matType); - }, - 'teardown': function() { - src.delete(); - dst.delete(); - } - }); - // set init params - let index = suite.length - 1; - suite[index].params = { - from: from, - scale: scale, - matType: matType - }; - } - } - - function decodeParams2Case(suite, params) { - let sizeString = (params.match(/[0-9]+x[0-9]+/g) || []).slice(0, 2).toString(); - let sizes = (sizeString.match(/[0-9]+/g) || []); - let size1Str = sizes.slice(0, 2).toString(); - let size2Str = sizes.slice(2, 5).toString(); - let matType = (params.match(/CV\_[0-9]+[A-z][A-z][0-9]/) || []).toString(); - let size1 = cvtStr2cvSize(size1Str); - let size2 = cvtStr2cvSize(size2Str); - // check if the params match and add case - for (let i = 0; i < combinations.length; ++i) { - let combination = combinations[i]; - for (let j = 0; j < combination.length; ++j) { - if (matType === combination[j][0] && size1 === combination[j][1] && size2 === combination[j][2]) { - resizeFunc[i](suite, [combination[j]]); - } + let params; + if (type == "area") { + let scale = combination[i][2]; + params = { from: from, scale: scale, matType: matType, modeType: type }; + } else { + let to = combination[i][2]; + params = { from: from, to: to, matType: matType, modeType: type}; } + addKernelCase(suite, params, type, addResizeCase) } } - function log(message) { - console.log(message); - if (!isNodeJs) { - logElement.innerHTML += `\n${'\t'.repeat(1) + message}`; - } - } - - function setBenchmarkSuite(suite) { - suite - // add listeners - .on('cycle', function(event) { - ++currentCaseId; - let params = event.target.params; - let matType = params.matType; - let size1 = params.from; - let size2 = params.to; - log(`=== ${event.target.name} ${currentCaseId} ===`); - log(`params: (${matType},${parseInt(size1.width)}x${parseInt(size1.height)},`+ - `${parseInt(size2.width)}x${parseInt(size2.height)})`); - log('elapsed time:' +String(event.target.times.elapsed*1000)+' ms'); - log('mean time:' +String(event.target.stats.mean*1000)+' ms'); - log('stddev time:' +String(event.target.stats.deviation*1000)+' ms'); - log(String(event.target)); - }) - .on('error', function(event) { log(`test case ${event.target.name} failed`); }) - .on('complete', function(event) { - log(`\n ###################################`) - log(`Finished testing ${event.currentTarget.length} cases \n`); - if (!isNodeJs) { - runButton.removeAttribute('disabled'); - runButton.setAttribute('class', 'btn btn-primary'); - runButton.innerHTML = 'Run'; - } - }); - } - function genBenchmarkCase(paramsContent) { let suite = new Benchmark.Suite; totalCaseNum = 0; currentCaseId = 0; if (/\(\w+,[\ ]*[0-9]+x[0-9]+,[\ ]*[0-9]+x[0-9]+\)/g.test(paramsContent.toString())) { let params = paramsContent.toString().match(/\(\w+,[\ ]*[0-9]+x[0-9]+,[\ ]*[0-9]+x[0-9]+\)/g)[0]; - decodeParams2Case(suite, params); + let paramObjs = []; + paramObjs.push({name:"matType", value:"", reg:["/CV\_[0-9]+[A-z][A-z][0-9]/"], index:0}); + paramObjs.push({name:"size1", value:"", reg:[""], index:1}); + paramObjs.push({name:"size2", value:"", reg:[""], index:2}); + let locationList = decodeParams2Case(params, paramObjs,combinations); + + for (let i = 0; i < locationList.length; i++){ + let first = locationList[i][0]; + let second = locationList[i][1]; + addResizeModeCase(suite, [combinations[first][second]], "linear"); + } } else { log("no filter or getting invalid params, run all the cases"); - addResizeUpLinearCase(suite, combiUpLinear); - addResizeDownLinearCase(suite, combiDownLinear); + addResizeModeCase(suite, combiUpLinear, "linear"); + addResizeModeCase(suite, combiDownLinear, "linear"); } - setBenchmarkSuite(suite); + setBenchmarkSuite(suite, "resize", currentCaseId); log(`Running ${totalCaseNum} tests from Resize`); suite.run({ 'async': true }); // run the benchmark } // init - let resizeFunc = [addResizeUpLinearCase, addResizeDownLinearCase];//, addResizeAreaFastCase]; let combinations = [combiUpLinear, combiDownLinear];//, combiAreaFast]; // set test filter params @@ -253,10 +147,19 @@ cv.onRuntimeInitialized = () => { let paramsContent = paramsElement.value; genBenchmarkCase(paramsContent); if (totalCaseNum !== 0) { - runButton.setAttribute("disabled", "disabled"); - runButton.setAttribute('class', 'btn btn-primary disabled'); - runButton.innerHTML = "Running"; + disableButton(); } } } -}; \ No newline at end of file +}; + +async function main() { + if (cv instanceof Promise) { + cv = await cv; + perf(); + } else { + cv.onRuntimeInitialized = perf; + } +} + +main(); \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_scharr.html b/modules/js/perf/perf_imgproc/perf_scharr.html new file mode 100644 index 0000000000000000000000000000000000000000..720ca741eba0ae6eae60d714249368971fe5cec4 --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_scharr.html @@ -0,0 +1,73 @@ + + + + + OpenCV.js Performance Test + + + + +
+
+
+

OpenCV.js Performance Test

+
+

Modules

+ Image Processing +
+
+

Kernels

+ Scharr +
+
+

Parameters Filter

+ for example: (640x480, CV_16SC1, (0,1), BORDER_REPLICATE) +
+
+
+
+
+ + (It will take several minutes)
+
+
+
+

+          
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_scharr.js b/modules/js/perf/perf_imgproc/perf_scharr.js new file mode 100644 index 0000000000000000000000000000000000000000..a76a93078c2b1946755bcaf4a5c0c904c074c8fe --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_scharr.js @@ -0,0 +1,156 @@ +const isNodeJs = (typeof window) === 'undefined'? true : false; + +if (isNodeJs) { + var Benchmark = require('benchmark'); + var cv = require('../../opencv'); + var HelpFunc = require('../perf_helpfunc'); + var Base = require('../base'); +} else { + var paramsElement = document.getElementById('params'); + var runButton = document.getElementById('runButton'); + var logElement = document.getElementById('log'); +} + +function perf() { + + console.log('opencv.js loaded'); + if (isNodeJs) { + global.cv = cv; + global.combine = HelpFunc.combine; + global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize; + global.cvSize = Base.getCvSize(); + } else { + enableButton(); + cvSize = getCvSize(); + } + let totalCaseNum, currentCaseId; + + const ScharrSize = [cvSize.szODD, cvSize.szQVGA, cvSize.szVGA]; + const Scharrdxdy = ["(1,0)", "(0,1)"]; + const BorderType3x3 = ["BORDER_REPLICATE", "BORDER_CONSTANT"]; + const BorderType3x3ROI = ["BORDER_DEFAULT", "BORDER_REPLICATE|BORDER_ISOLATED", "BORDER_CONSTANT|BORDER_ISOLATED"]; + + const combiScharrBorder3x3 = combine(ScharrSize, ["CV_16SC1", "CV_32FC1"], Scharrdxdy, BorderType3x3); + const combiScharrBorder3x3ROI = combine(ScharrSize, ["CV_16SC1", "CV_32FC1"], Scharrdxdy, BorderType3x3ROI); + + function addScharrCase(suite, type) { + suite.add('scharr', function() { + cv.Scharr(src, dst, ddepth, dx, dy, 1, 0, borderType); + }, { + 'setup': function() { + let size = this.params.size; + let ddepth = cv[this.params.ddepth]; + let dxdy = this.params.dxdy; + let type = this.params.type; + let src, dst; + if (type == 0) { + src = new cv.Mat(size[1], size[0], cv.CV_8U); + dst = new cv.Mat(size[1], size[0], ddepth); + } else { + src = new cv.Mat(size[1]+10, size[0]+10, cv.CV_8U); + dst = new cv.Mat(size[1]+10, size[0]+10, ddepth); + src = src.colRange(5, size[0]+5); + src = src.rowRange(5, size[1]+5); + dst = dst.colRange(5, size[0]+5); + dst = dst.rowRange(5, size[1]+5); + } + + let dx = parseInt(dxdy[1]); + let dy = parseInt(dxdy[3]); + let borderTypeArray = this.params.borderType; + let borderType; + if (borderTypeArray.length == 1) { + borderType = cv[borderTypeArray[0]]; + } else { + borderType = cv[borderTypeArray[0]] | cv[borderTypeArray[1]]; + } + }, + 'teardown': function() { + src.delete(); + dst.delete(); + } + }); + } + + function addScharrModeCase(suite, combination, type) { + totalCaseNum += combination.length; + for (let i = 0; i < combination.length; ++i) { + let size = combination[i][0]; + let ddepth = combination[i][1]; + let dxdy = combination[i][2]; + let borderType = combination[i][3]; + let sizeArray = [size.width, size.height]; + + let borderTypeArray = borderType.split("|"); + let params = {size: sizeArray, ddepth: ddepth, dxdy: dxdy, borderType:borderTypeArray, type:type}; + addKernelCase(suite, params, type, addScharrCase); + } + } + + function genBenchmarkCase(paramsContent) { + let suite = new Benchmark.Suite; + totalCaseNum = 0; + currentCaseId = 0; + let params = ""; + let paramObjs = []; + paramObjs.push({name:"size", value:"", reg:[""], index:0}); + paramObjs.push({name:"ddepth", value:"", reg:["/CV\_[0-9]+[FSUfsu]C1/g"], index:1}); + paramObjs.push({name:"dxdy", value:"", reg:["/\\([0-2],[0-2]\\)/"], index:2}); + + if (/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\([0-2],[0-2]\),[\ ]*\w+\)/g.test(paramsContent.toString())) { + params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\([0-2],[0-2]\),[\ ]*\w+\)/g)[0]; + paramObjs.push({name:"boderType", value:"", reg:["/BORDER\_\\w+/"], index:3}); + } else if (/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\([0-2],[0-2]\),[\ ]*\w+\|\w+\)/g.test(paramsContent.toString())) { + params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\([0-2],[0-2]\),[\ ]*\w+\|\w+\)/g)[0]; + paramObjs.push({name:"boderType", value:"", reg:["/BORDER\_\\w+\\|BORDER\_\\w+/"], index:3}); + } + + if (params != ""){ + let locationList = decodeParams2Case(params, paramObjs,scharrCombinations); + for (let i = 0; i < locationList.length; i++){ + let first = locationList[i][0]; + let second = locationList[i][1]; + addScharrModeCase(suite, [scharrCombinations[first][second]], first); + } + } else { + log("no filter or getting invalid params, run all the cases"); + addScharrModeCase(suite, combiScharrBorder3x3, 0); + addScharrModeCase(suite, combiScharrBorder3x3ROI, 1); + } + setBenchmarkSuite(suite, "scharr", currentCaseId); + log(`Running ${totalCaseNum} tests from Scharr`); + suite.run({ 'async': true }); // run the benchmark + } + + let scharrCombinations = [combiScharrBorder3x3, combiScharrBorder3x3ROI]; + + if (isNodeJs) { + const args = process.argv.slice(2); + let paramsContent = ''; + if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\([0-2],[0-2]\),[\ ]*\w+\)/g.test(args.toString())) { + paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\([0-2],[0-2]\),[\ ]*\w+\)/g)[0]; + } else if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\([0-2],[0-2]\),[\ ]*\w+\|\w+\)/g.test(args.toString())) { + paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\([0-2],[0-2]\),[\ ]*\w+\|\w+\)/g)[0]; + } + genBenchmarkCase(paramsContent); + } else { + runButton.onclick = function() { + let paramsContent = paramsElement.value; + genBenchmarkCase(paramsContent); + if (totalCaseNum !== 0) { + disableButton(); + } + } + } +}; + +async function main() { + if (cv instanceof Promise) { + cv = await cv; + perf(); + } else { + cv.onRuntimeInitialized = perf; + } +} + +main(); \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_sobel.html b/modules/js/perf/perf_imgproc/perf_sobel.html new file mode 100644 index 0000000000000000000000000000000000000000..b41c940a2353f73a496b197c6cdd09cf83c98929 --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_sobel.html @@ -0,0 +1,73 @@ + + + + + OpenCV.js Performance Test + + + + +
+
+
+

OpenCV.js Performance Test

+
+

Modules

+ Image Processing +
+
+

Kernels

+ Sobel +
+
+

Parameters Filter

+ for example: (640x480, CV_16SC1, (0,1), BORDER_REPLICATE) +
+
+
+
+
+ + (It will take several minutes)
+
+
+
+

+          
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_sobel.js b/modules/js/perf/perf_imgproc/perf_sobel.js new file mode 100644 index 0000000000000000000000000000000000000000..b7064e852ad8a59b7a17ac69b109e4dc003ed73b --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_sobel.js @@ -0,0 +1,170 @@ +const isNodeJs = (typeof window) === 'undefined'? true : false; + +if (isNodeJs) { + var Benchmark = require('benchmark'); + var cv = require('../../opencv'); + var HelpFunc = require('../perf_helpfunc'); + var Base = require('../base'); +} else { + var paramsElement = document.getElementById('params'); + var runButton = document.getElementById('runButton'); + var logElement = document.getElementById('log'); +} + +function perf() { + + console.log('opencv.js loaded'); + if (isNodeJs) { + global.cv = cv; + global.combine = HelpFunc.combine; + global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize; + global.cvSize = Base.getCvSize(); + } else { + enableButton(); + cvSize = getCvSize(); + } + let totalCaseNum, currentCaseId; + + const SobelSize = [cvSize.szODD, cvSize.szQVGA, cvSize.szVGA]; + const Sobel3x3dxdy = ["(0,1)", "(1,0)", "(1,1)", "(0,2)", "(2,0)", "(2,2)"]; + const Sobeldxdy = ["(0,1)", "(1,0)", "(1,1)", "(0,2)", "(2,0)"]; + const BorderType3x3 = ["BORDER_REPLICATE", "BORDER_CONSTANT"]; + const BorderType3x3ROI = ["BORDER_DEFAULT", "BORDER_REPLICATE|BORDER_ISOLATED", "BORDER_CONSTANT|BORDER_ISOLATED"]; + const BorderType = ["BORDER_REPLICATE", "BORDER_CONSTANT", "BORDER_REFLECT", "BORDER_REFLECT101"]; + const BorderTypeROI = ["BORDER_DEFAULT", "BORDER_REPLICATE|BORDER_ISOLATED", "BORDER_CONSTANT|BORDER_ISOLATED", "BORDER_REFLECT|BORDER_ISOLATED", "BORDER_REFLECT101|BORDER_ISOLATED"] + + const combiSobelBorder3x3 = combine(SobelSize, ["CV_16SC1", "CV_32FC1"], Sobel3x3dxdy, BorderType3x3); + const combiSobelBorder3x3ROI = combine(SobelSize, ["CV_16SC1", "CV_32FC1"], Sobel3x3dxdy, BorderType3x3ROI); + const combiSobelBorder5x5 = combine(SobelSize, ["CV_16SC1", "CV_32FC1"], Sobeldxdy, BorderType); + const combiSobelBorder5x5ROI = combine(SobelSize, ["CV_16SC1", "CV_32FC1"], Sobeldxdy, BorderTypeROI); + + function addSobelCase(suite, type) { + suite.add('sobel', function() { + cv.Sobel(src, dst, ddepth, dx, dy, ksize, 1, 0, borderType); + }, { + 'setup': function() { + let size = this.params.size; + let ddepth = cv[this.params.ddepth]; + let dxdy = this.params.dxdy; + let ksize = this.params.ksize; + let type = this.params.type; + let src, dst; + if (type %2 == 0) { + src = new cv.Mat(size[1], size[0], cv.CV_8U); + dst = new cv.Mat(size[1], size[0], ddepth); + } else { + src = new cv.Mat(size[1]+10, size[0]+10, cv.CV_8U); + dst = new cv.Mat(size[1]+10, size[0]+10, ddepth); + src = src.colRange(5, size[0]+5); + src = src.rowRange(5, size[1]+5); + dst = dst.colRange(5, size[0]+5); + dst = dst.rowRange(5, size[1]+5); + } + + let dx = parseInt(dxdy[1]); + let dy = parseInt(dxdy[3]); + let borderTypeArray = this.params.borderType; + let borderType; + if (borderTypeArray.length == 1) { + borderType = cv[borderTypeArray[0]]; + } else { + borderType = cv[borderTypeArray[0]] | cv[borderTypeArray[1]]; + } + }, + 'teardown': function() { + src.delete(); + dst.delete(); + } + }); + } + + function addSobelModeCase(suite, combination, type) { + totalCaseNum += combination.length; + for (let i = 0; i < combination.length; ++i) { + let size = combination[i][0]; + let ddepth = combination[i][1]; + let dxdy = combination[i][2]; + let borderType = combination[i][3]; + let sizeArray = [size.width, size.height]; + let ksize; + if (type < 2) { + ksize = 3; + } else { + ksize = 5; + } + + let borderTypeArray = borderType.split("|"); + let params = {size: sizeArray, ddepth: ddepth, dxdy: dxdy, ksize:ksize, borderType:borderTypeArray, type:type}; + addKernelCase(suite, params, type, addSobelCase); + } + } + + function genBenchmarkCase(paramsContent) { + let suite = new Benchmark.Suite; + totalCaseNum = 0; + currentCaseId = 0; + let params = ""; + let paramObjs = []; + paramObjs.push({name:"size", value:"", reg:[""], index:0}); + paramObjs.push({name:"ddepth", value:"", reg:["/CV\_[0-9]+[FSUfsu]C1/g"], index:1}); + paramObjs.push({name:"dxdy", value:"", reg:["/\\([0-2],[0-2]\\)/"], index:2}); + + if (/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\([0-2],[0-2]\),[\ ]*\w+\)/g.test(paramsContent.toString())) { + params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\([0-2],[0-2]\),[\ ]*\w+\)/g)[0]; + paramObjs.push({name:"boderType", value:"", reg:["/BORDER\_\\w+/"], index:3}); + } else if (/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\([0-2],[0-2]\),[\ ]*\w+\|\w+\)/g.test(paramsContent.toString())) { + params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\([0-2],[0-2]\),[\ ]*\w+\|\w+\)/g)[0]; + paramObjs.push({name:"boderType", value:"", reg:["/BORDER\_\\w+\\|BORDER\_\\w+/"], index:3}); + } + + if (params != ""){ + let locationList = decodeParams2Case(params, paramObjs,sobelCombinations); + for (let i = 0; i < locationList.length; i++){ + let first = locationList[i][0]; + let second = locationList[i][1]; + addSobelModeCase(suite, [sobelCombinations[first][second]], first); + } + } else { + log("no filter or getting invalid params, run all the cases"); + addSobelModeCase(suite, combiSobelBorder3x3, 0); + addSobelModeCase(suite, combiSobelBorder3x3ROI, 1); + addSobelModeCase(suite, combiSobelBorder5x5, 2); + addSobelModeCase(suite, combiSobelBorder5x5ROI, 3); + } + setBenchmarkSuite(suite, "sobel", currentCaseId); + log(`Running ${totalCaseNum} tests from Sobel`); + suite.run({ 'async': true }); // run the benchmark + } + + let sobelCombinations = [combiSobelBorder3x3, combiSobelBorder3x3ROI, combiSobelBorder5x5, combiSobelBorder5x5ROI]; + + if (isNodeJs) { + const args = process.argv.slice(2); + let paramsContent = ''; + if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\([0-2],[0-2]\),[\ ]*\w+\)/g.test(args.toString())) { + paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\([0-2],[0-2]\),[\ ]*\w+\)/g)[0]; + } else if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\([0-2],[0-2]\),[\ ]*\w+\|\w+\)/g.test(args.toString())) { + paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\([0-2],[0-2]\),[\ ]*\w+\|\w+\)/g)[0]; + } + genBenchmarkCase(paramsContent); + } else { + runButton.onclick = function() { + let paramsContent = paramsElement.value; + genBenchmarkCase(paramsContent); + if (totalCaseNum !== 0) { + disableButton(); + } + } + } +}; + +async function main() { + if (cv instanceof Promise) { + cv = await cv; + perf(); + } else { + cv.onRuntimeInitialized = perf; + } +} + +main(); \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_threshold.js b/modules/js/perf/perf_imgproc/perf_threshold.js index 2616a2feaaf889de163cd1740de8dd2b00c12050..381ddaeade52ea4b0b624890d4789528387cd449 100644 --- a/modules/js/perf/perf_imgproc/perf_threshold.js +++ b/modules/js/perf/perf_imgproc/perf_threshold.js @@ -11,17 +11,17 @@ if (isNodeJs) { var logElement = document.getElementById('log'); } -cv.onRuntimeInitialized = () => { +function perf() { + console.log('opencv.js loaded'); if (isNodeJs) { global.cv = cv; global.combine = HelpFunc.combine; global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize; - global.cvSize = Base.cvSize; + global.cvSize = Base.getCvSize(); } else { - runButton.removeAttribute('disabled'); - runButton.setAttribute('class', 'btn btn-primary'); - runButton.innerHTML = 'Run'; + enableButton(); + cvSize = getCvSize(); } let totalCaseNum, currentCaseId; @@ -32,173 +32,105 @@ cv.onRuntimeInitialized = () => { const combiSizeMatTypeThreshType = combine(typicalMatSizes, matTypes, threshTypes); const combiSizeOnly = combine(typicalMatSizes, ['CV_8UC1'], ['THRESH_BINARY|THRESH_OTSU']); - function addSizeMatTypeThreshTypeCase(suite, combination) { - totalCaseNum += combination.length; - for (let i = 0; i < combination.length; ++i) { - let matSize = combination[i][0]; - let matType = combination[i][1]; - let threshType = combination[i][2]; - suite.add('threshold', function() { + function addThresholdCase(suite, type) { + suite.add('threshold', function() { + if (type == "sizeonly") { + cv.threshold(src, dst, threshold, thresholdMax, cv.THRESH_BINARY|cv.THRESH_OTSU); + } else { cv.threshold(src, dst, threshold, thresholdMax, threshType); - }, { - 'setup': function() { - let matSize = this.params.matSize; - let matType = cv[this.params.matType]; - let threshType = cv[this.params.threshType]; - let threshold = 127.0; - let thresholdMax = 210.0; - let src = new cv.Mat(matSize, matType); - let dst = new cv.Mat(matSize, matType); - let srcView = src.data; - srcView[0] = 0; - srcView[1] = 100; - srcView[2] = 200; - }, - 'teardown': function() { - src.delete(); - dst.delete(); + } + }, { + 'setup': function() { + let matSize = this.params.matSize; + let type = this.params.modeType; + let src, dst, matType, threshType; + if (type == "sizeonly") { + src = new cv.Mat(matSize, cv.CV_8UC1); + dst = new cv.Mat(matSize, cv.CV_8UC1); + } else { + matType = cv[this.params.matType]; + threshType = cv[this.params.threshType]; + src = new cv.Mat(matSize, matType); + dst = new cv.Mat(matSize, matType); } - }); - - // set init params - let index = suite.length - 1; - suite[index].params = { - matSize: matSize, - matType: matType, - threshType: threshType - }; - } + let threshold = 127.0; + let thresholdMax = 210.0; + let srcView = src.data; + srcView[0] = 0; + srcView[1] = 100; + srcView[2] = 200; + }, + 'teardown': function() { + src.delete(); + dst.delete(); + } + }); } - function addSizeOnlyCase(suite, combination) { + function addThresholdModecase(suite, combination, type) { totalCaseNum += combination.length; for (let i = 0; i < combination.length; ++i) { let matSize = combination[i][0]; - - suite.add('threshold', function() { - cv.threshold(src, dst, threshold, thresholdMax, cv.THRESH_BINARY|cv.THRESH_OTSU); - }, { - 'setup': function() { - let matSize = this.params.matSize; - let threshold = 127.0; - let thresholdMax = 210.0; - let src = new cv.Mat(matSize, cv.CV_8UC1); - let dst = new cv.Mat(matSize, cv.CV_8UC1); - let srcView = src.data; - srcView[0] = 0; - srcView[1] = 100; - srcView[2] = 200; - }, - 'teardown': function() { - src.delete(); - dst.delete(); - } - }); - - // set init params - let index = suite.length - 1; - suite[index].params = { - matSize: matSize, - matType: 'CV_8UC1', - threshType: 'THRESH_BINARY|THRESH_OTSU' - }; - } - } - - function decodeParams2Case(suite, params, isSizeOnly) { - let sizeString = params.match(/[0-9]+x[0-9]+/g).toString(); - let sizes = sizeString.match(/[0-9]+/g); - let size1Str = sizes.slice(0, 2).toString(); - let matSize = cvtStr2cvSize(size1Str); - let matType, threshType; - if (isSizeOnly) { - matType = 'CV_8UC1'; - threshType = 'THRESH_BINARY|THRESH_OTSU'; - } else { - matType = (params.match(/CV\_[0-9]+[A-z][A-z][0-9]/) || []).toString(); - threshType = (params.match(/THRESH\_[A-z]+\_?[A-z]*/) || []).toString(); - } - // check if the params match and add case - for (let i = 0; i < combinations.length; ++i) { - let combination = combinations[i]; - for (let j = 0; j < combination.length; ++j) { - if (matSize === combination[j][0] && matType === combination[j][1] && threshType === combination[j][2]) { - thresholdFunc[i](suite, [combination[j]]); - } + let matType = 'CV_8UC1'; + let threshType = 'THRESH_BINARY|THRESH_OTSU'; + if (type != "sizeonly") { + matType = combination[i][1]; + threshType = combination[i][2]; } + let params = {matSize: matSize, matType: matType, threshType: threshType, modeType: type}; + addKernelCase(suite, params, type, addThresholdCase); } } - function log(message) { - console.log(message);1 - if (!isNodeJs) { - logElement.innerHTML += `\n${'\t'.repeat(1) + message}`; - } - } - - function setBenchmarkSuite(suite) { - suite - // add listeners - .on('cycle', function(event) { - ++currentCaseId; - let params = event.target.params; - let matSize = params.matSize; - let matType = params.matType; - let threshType = params.threshType; - log(`=== ${event.target.name} ${currentCaseId} ===`); - log(`params: (${parseInt(matSize.width)}x${parseInt(matSize.height)},`+ - `${matType},${threshType})`); - log('elapsed time:' +String(event.target.times.elapsed*1000)+' ms'); - log('mean time:' +String(event.target.stats.mean*1000)+' ms'); - log('stddev time:' +String(event.target.stats.deviation*1000)+' ms'); - log(String(event.target)); - }) - .on('error', function(event) { log(`test case ${event.target.name} failed`); }) - .on('complete', function(event) { - log(`\n ###################################`) - log(`Finished testing ${event.currentTarget.length} cases \n`); - if (!isNodeJs) { - runButton.removeAttribute('disabled'); - runButton.setAttribute('class', 'btn btn-primary'); - runButton.innerHTML = 'Run'; - } - }); - } - function genBenchmarkCase(paramsContent) { let suite = new Benchmark.Suite; totalCaseNum = 0; currentCaseId = 0; - if (/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\w+\)/g.test(paramsContent.toString())) { - let params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\w+\)/g)[0]; - let isSizeOnly = 0; - decodeParams2Case(suite, params, isSizeOnly); + let params = ""; + let paramObjs = []; + paramObjs.push({name:"size", value:"", reg:[""], index:0}); + + if (/\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*THRESH\_\w+\)/g.test(paramsContent.toString())) { + params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*THRESH\_\w+\)/g)[0]; + paramObjs.push({name:"matType", value:"", reg:["/CV\_[0-9]+[A-z][A-z][0-9]/"], index:1}); + paramObjs.push({name:"threshType", value:"", reg:["/THRESH\_[A-z]+\_?[A-z]*/"], index:2}); } else if (/[\ ]*[0-9]+x[0-9]+[\ ]*/g.test(paramsContent.toString())) { - let params = paramsContent.toString().match(/[\ ]*[0-9]+x[0-9]+[\ ]*/g)[0]; - let isSizeOnly = 1; - decodeParams2Case(suite, params, isSizeOnly); + params = paramsContent.toString().match(/[\ ]*[0-9]+x[0-9]+[\ ]*/g)[0]; + paramObjs.push({name:"matType", value:"CV_8UC1", reg:[""], index:1}); + paramObjs.push({name:"threshType", value:"THRESH_BINARY|THRESH_OTSU", reg:[""], index:2}); } - else { + + if(params != ""){ + let locationList = decodeParams2Case(params, paramObjs,combinations); + for (let i = 0; i < locationList.length; i++){ + let first = locationList[i][0]; + let second = locationList[i][1]; + if (first == 0) { + addThresholdModecase(suite, [combinations[first][second]], "normal"); + } else { + addThresholdModecase(suite, [combinations[first][second]], "sizeonly"); + } + } + } else { log("no filter or getting invalid params, run all the cases"); - addSizeMatTypeThreshTypeCase(suite, combiSizeMatTypeThreshType); - addSizeOnlyCase(suite, combiSizeOnly); + addThresholdModecase(suite, combiSizeMatTypeThreshType, "normal"); + addThresholdModecase(suite, combiSizeOnly, "sizeonly"); } - setBenchmarkSuite(suite); + setBenchmarkSuite(suite, "threshold", currentCaseId); log(`Running ${totalCaseNum} tests from Threshold`); suite.run({ 'async': true }); // run the benchmark } // init - let thresholdFunc = [addSizeMatTypeThreshTypeCase, addSizeOnlyCase]; let combinations = [combiSizeMatTypeThreshType, combiSizeOnly]; // set test filter params if (isNodeJs) { const args = process.argv.slice(2); let paramsContent = ''; - if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\w+\)/g.test(args.toString())) { - paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*\w+,[\ ]*\w+\)/g)[0]; + if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*THRESH\_\w+\)/g.test(args.toString())) { + paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*CV\_\w+,[\ ]*THRESH\_\w+\)/g)[0]; } else if (/--test_param_filter=[\ ]*[0-9]+x[0-9]+[\ ]*/g.test(args.toString())) { paramsContent = args.toString().match(/[\ ]*[0-9]+x[0-9]+[\ ]*/g)[0]; } @@ -208,10 +140,19 @@ cv.onRuntimeInitialized = () => { let paramsContent = paramsElement.value; genBenchmarkCase(paramsContent); if (totalCaseNum !== 0) { - runButton.setAttribute("disabled", "disabled"); - runButton.setAttribute('class', 'btn btn-primary disabled'); - runButton.innerHTML = "Running"; + disableButton(); } } } -}; \ No newline at end of file +}; + +async function main() { + if (cv instanceof Promise) { + cv = await cv; + perf(); + } else { + cv.onRuntimeInitialized = perf; + } +} + +main(); \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_warpAffine.html b/modules/js/perf/perf_imgproc/perf_warpAffine.html new file mode 100644 index 0000000000000000000000000000000000000000..53a0fd9d67f53c33fe9ecbddcf4efe09b24d9095 --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_warpAffine.html @@ -0,0 +1,73 @@ + + + + + OpenCV.js Performance Test + + + + +
+
+
+

OpenCV.js Performance Test

+
+

Modules

+ Image Processing +
+
+

Kernels

+ warpAffine +
+
+

Parameters Filter

+ for example: (640x480, INTER_NEAREST, BORDER_CONSTANT) +
+
+
+
+
+ + (It will take several minutes)
+
+
+
+

+          
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_warpAffine.js b/modules/js/perf/perf_imgproc/perf_warpAffine.js new file mode 100644 index 0000000000000000000000000000000000000000..c63cd60e61ecf068f43167637efe272b697f2eb4 --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_warpAffine.js @@ -0,0 +1,130 @@ +const isNodeJs = (typeof window) === 'undefined'? true : false; + +if (isNodeJs) { + var Benchmark = require('benchmark'); + var cv = require('../../opencv'); + var HelpFunc = require('../perf_helpfunc'); + var Base = require('../base'); +} else { + var paramsElement = document.getElementById('params'); + var runButton = document.getElementById('runButton'); + var logElement = document.getElementById('log'); +} + +function perf() { + + console.log('opencv.js loaded'); + if (isNodeJs) { + global.cv = cv; + global.combine = HelpFunc.combine; + global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize; + global.cvSize = Base.getCvSize(); + } else { + enableButton(); + cvSize = getCvSize(); + } + let totalCaseNum, currentCaseId; + + const WarpAffineSize = [cvSize.szVGA, cvSize.sz720p, cvSize.sz1080p]; + const InterType = ["INTER_NEAREST", "INTER_LINEAR"]; + const BorderMode = ["BORDER_CONSTANT", "BORDER_REPLICATE"] + const combiWarpAffine = combine(WarpAffineSize, InterType, BorderMode); + + function addWarpAffineCase(suite, type) { + suite.add('warpAffine', function() { + cv.warpAffine(src, dst, warpMat, sz, interType, borderMode, borderColor); + }, { + 'setup': function() { + let sz = this.params.size; + let interType = cv[this.params.interType]; + let borderMode = cv[this.params.borderMode]; + let srcSize = new cv.Size(512, 512); + + let borderColor = new cv.Scalar.all(150); + let src = new cv.Mat(srcSize, cv.CV_8UC4); + let dst = new cv.Mat(sz, cv.CV_8UC4); + fillGradient(cv, src); + if (borderMode == cv.BORDER_CONSTANT) { + smoothBorder(cv, src, borderMode, 1); + } + + let point = new cv.Point(src.cols/2.0, src.rows/2.0); + let warpMat = cv.getRotationMatrix2D(point, 30.0, 2.2); + }, + 'teardown': function() { + src.delete(); + dst.delete(); + warpMat.delete(); + } + }); + } + + function addWarpAffineModeCase(suite, combination, type) { + totalCaseNum += combination.length; + for (let i = 0; i < combination.length; ++i) { + let size = combination[i][0]; + let interType = combination[i][1]; + let borderMode = combination[i][2]; + + let params = {size: size, interType:interType, borderMode:borderMode}; + addKernelCase(suite, params, type, addWarpAffineCase); + } + } + + function genBenchmarkCase(paramsContent) { + let suite = new Benchmark.Suite; + totalCaseNum = 0; + currentCaseId = 0; + + if (/\([0-9]+x[0-9]+,[\ ]*INTER\_\w+,[\ ]*BORDER\_\w+\)/g.test(paramsContent.toString())) { + let params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*INTER\_\w+,[\ ]*BORDER\_\w+\)/g)[0]; + let paramObjs = []; + paramObjs.push({name:"size", value:"", reg:[""], index:0}); + paramObjs.push({name:"interType", value: "", reg:["/INTER\_\\w+/"], index:1}); + paramObjs.push({name:"borderMode", value: "", reg:["/BORDER\_\\w+/"], index:2}); + let locationList = decodeParams2Case(params, paramObjs, warpAffineCombinations); + + for (let i = 0; i < locationList.length; i++){ + let first = locationList[i][0]; + let second = locationList[i][1]; + addWarpAffineModeCase(suite, [warpAffineCombinations[first][second]], first); + } + } else { + log("no filter or getting invalid params, run all the cases"); + addWarpAffineModeCase(suite, combiWarpAffine, 0); + } + setBenchmarkSuite(suite, "warpAffine", currentCaseId); + log(`Running ${totalCaseNum} tests from warpAffine`); + suite.run({ 'async': true }); // run the benchmark + } + + let warpAffineCombinations = [combiWarpAffine]; + + if (isNodeJs) { + const args = process.argv.slice(2); + let paramsContent = ''; + if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*INTER\_\w+,[\ ]*BORDER\_\w+\)/g.test(args.toString())) { + paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*INTER\_\w+,[\ ]*BORDER\_\w+\)/g)[0]; + } + genBenchmarkCase(paramsContent); + } else { + runButton.onclick = function() { + let paramsContent = paramsElement.value; + genBenchmarkCase(paramsContent); + if (totalCaseNum !== 0) { + disableButton(); + } + } + } +}; + +async function main() { + if (cv instanceof Promise) { + cv = await cv; + perf(); + } else { + cv.onRuntimeInitialized = perf; + } +} + +main(); \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_warpPerspective.html b/modules/js/perf/perf_imgproc/perf_warpPerspective.html new file mode 100644 index 0000000000000000000000000000000000000000..7fc4c89ad2184186334180b843d36fa21f758adf --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_warpPerspective.html @@ -0,0 +1,73 @@ + + + + + OpenCV.js Performance Test + + + + +
+
+
+

OpenCV.js Performance Test

+
+

Modules

+ Image Processing +
+
+

Kernels

+ warpPerspective +
+
+

Parameters Filter

+ for example: (640x480, INTER_NEAREST, BORDER_CONSTANT) +
+
+
+
+
+ + (It will take several minutes)
+
+
+
+

+          
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/modules/js/perf/perf_imgproc/perf_warpPerspective.js b/modules/js/perf/perf_imgproc/perf_warpPerspective.js new file mode 100644 index 0000000000000000000000000000000000000000..dcde2fb22cc2492ddfe4dd811d7ede340a535abc --- /dev/null +++ b/modules/js/perf/perf_imgproc/perf_warpPerspective.js @@ -0,0 +1,143 @@ +const isNodeJs = (typeof window) === 'undefined'? true : false; + +if (isNodeJs) { + var Benchmark = require('benchmark'); + var cv = require('../../opencv'); + var HelpFunc = require('../perf_helpfunc'); + var Base = require('../base'); +} else { + var paramsElement = document.getElementById('params'); + var runButton = document.getElementById('runButton'); + var logElement = document.getElementById('log'); +} + +function perf() { + + console.log('opencv.js loaded'); + if (isNodeJs) { + global.cv = cv; + global.combine = HelpFunc.combine; + global.cvtStr2cvSize = HelpFunc.cvtStr2cvSize; + global.cvSize = Base.getCvSize(); + } else { + enableButton(); + cvSize = getCvSize(); + } + let totalCaseNum, currentCaseId; + + const WarpPersSize = [cvSize.szVGA, cvSize.sz720p, cvSize.sz1080p]; + const InterType = ["INTER_NEAREST", "INTER_LINEAR"]; + const BorderMode = ["BORDER_CONSTANT", "BORDER_REPLICATE"] + const combiWarpPers = combine(WarpPersSize, InterType, BorderMode); + + function addWarpPerspectiveCase(suite, type) { + suite.add('warpPerspective', function() { + cv.warpPerspective(src, dst, warpMat, sz, interType, borderMode, borderColor); + }, { + 'setup': function() { + let sz = this.params.size; + let interType = cv[this.params.interType]; + let borderMode = cv[this.params.borderMode]; + let srcSize = new cv.Size(512, 512); + + let borderColor = new cv.Scalar.all(150); + let src = new cv.Mat(srcSize, cv.CV_8UC4); + let dst = new cv.Mat(sz, cv.CV_8UC4); + fillGradient(cv, src); + if (borderMode == cv.BORDER_CONSTANT) { + smoothBorder(cv, src, borderMode, 1); + } + + let rotMat = cv.getRotationMatrix2D(new cv.Point(src.cols/2.0, src.rows/2.0), 30.0, 2.2); + let warpMat = new cv.Mat(3, 3, cv.CV_64FC1); + + for(r=0; r<2; r++) { + for(c=0; c<3; c++) { + view = warpMat.doublePtr(r,c) + view[0] = rotMat.doubleAt(r, c); + } + } + view = warpMat.doublePtr(2,0); + view[0] = 0.3/sz.width; + view = warpMat.doublePtr(2,1); + view[0] = 0.3/sz.height; + view = warpMat.doublePtr(2,2); + view[0] = 1; + }, + 'teardown': function() { + src.delete(); + dst.delete(); + warpMat.delete(); + } + }); + } + + function addWarpPerspectiveModeCase(suite, combination, type) { + totalCaseNum += combination.length; + for (let i = 0; i < combination.length; ++i) { + let size = combination[i][0]; + let interType = combination[i][1]; + let borderMode = combination[i][2]; + + let params = {size: size, interType:interType, borderMode:borderMode}; + addKernelCase(suite, params, type, addWarpPerspectiveCase); + } + } + + function genBenchmarkCase(paramsContent) { + let suite = new Benchmark.Suite; + totalCaseNum = 0; + currentCaseId = 0; + + if (/\([0-9]+x[0-9]+,[\ ]*INTER\_\w+,[\ ]*BORDER\_\w+\)/g.test(paramsContent.toString())) { + let params = paramsContent.toString().match(/\([0-9]+x[0-9]+,[\ ]*INTER\_\w+,[\ ]*BORDER\_\w+\)/g)[0]; + let paramObjs = []; + paramObjs.push({name:"size", value:"", reg:[""], index:0}); + paramObjs.push({name:"interType", value: "", reg:["/INTER\_\\w+/"], index:1}); + paramObjs.push({name:"borderMode", value: "", reg:["/BORDER\_\\w+/"], index:2}); + let locationList = decodeParams2Case(params, paramObjs, warpPersCombinations); + + for (let i = 0; i < locationList.length; i++){ + let first = locationList[i][0]; + let second = locationList[i][1]; + addWarpPerspectiveModeCase(suite, [warpPersCombinations[first][second]], first); + } + } else { + log("no filter or getting invalid params, run all the cases"); + addWarpPerspectiveModeCase(suite, combiWarpPers, 0); + } + setBenchmarkSuite(suite, "warpPerspective", currentCaseId); + log(`Running ${totalCaseNum} tests from warpPerspective`); + suite.run({ 'async': true }); // run the benchmark + } + + let warpPersCombinations = [combiWarpPers]; + + if (isNodeJs) { + const args = process.argv.slice(2); + let paramsContent = ''; + if (/--test_param_filter=\([0-9]+x[0-9]+,[\ ]*INTER\_\w+,[\ ]*BORDER\_\w+\)/g.test(args.toString())) { + paramsContent = args.toString().match(/\([0-9]+x[0-9]+,[\ ]*INTER\_\w+,[\ ]*BORDER\_\w+\)/g)[0]; + } + genBenchmarkCase(paramsContent); + } else { + runButton.onclick = function() { + let paramsContent = paramsElement.value; + genBenchmarkCase(paramsContent); + if (totalCaseNum !== 0) { + disableButton(); + } + } + } +}; + +async function main() { + if (cv instanceof Promise) { + cv = await cv; + perf(); + } else { + cv.onRuntimeInitialized = perf; + } +} + +main(); \ No newline at end of file diff --git a/modules/js/src/loader.js b/modules/js/src/loader.js new file mode 100644 index 0000000000000000000000000000000000000000..ea100e8601542d748ec01beba9dad97d562b0baa --- /dev/null +++ b/modules/js/src/loader.js @@ -0,0 +1,96 @@ +async function loadOpenCV(paths, onloadCallback) { + let OPENCV_URL = ""; + let asmPath = ""; + let wasmPath = ""; + let simdPath = ""; + let threadsPath = ""; + let threadsSimdPath = ""; + + if(!(paths instanceof Object)) { + throw new Error("The first input should be a object that points the path to the OpenCV.js"); + } + + if ("asm" in paths) { + asmPath = paths["asm"]; + } + + if ("wasm" in paths) { + wasmPath = paths["wasm"]; + } + + if ("threads" in paths) { + threadsPath = paths["threads"]; + } + + if ("simd" in paths) { + simdPath = paths["simd"]; + } + + if ("threadsSimd" in paths) { + threadsSimdPath = paths["threadsSimd"]; + } + + let wasmSupported = !(typeof WebAssembly === 'undefined'); + if (!wasmSupported && OPENCV_URL === "" && asmPath != "") { + OPENCV_URL = asmPath; + console.log("The OpenCV.js for Asm.js is loaded now"); + } else if (!wasmSupported && asmPath == ""){ + throw new Error("The browser supports the Asm.js only, but the path of OpenCV.js for Asm.js is empty"); + } + + let simdSupported = wasmSupported ? await wasmFeatureDetect.simd() : false; + let threadsSupported = wasmSupported ? await wasmFeatureDetect.threads() : false; + + if (simdSupported && threadsSupported && threadsSimdPath != "") { + OPENCV_URL = threadsSimdPath; + console.log("The OpenCV.js with simd and threads optimization is loaded now"); + } else if (simdSupported && simdPath != "") { + if (threadsSupported && threadsSimdPath === "") { + console.log("The browser supports simd and threads, but the path of OpenCV.js with simd and threads optimization is empty"); + } + OPENCV_URL = simdPath; + console.log("The OpenCV.js with simd optimization is loaded now."); + } else if (threadsSupported && threadsPath != "") { + if (simdSupported && threadsSimdPath === "") { + console.log("The browser supports simd and threads, but the path of OpenCV.js with simd and threads optimization is empty"); + } + OPENCV_URL = threadsPath; + console.log("The OpenCV.js with threads optimization is loaded now"); + } else if (wasmSupported && wasmPath != "") { + if(simdSupported && threadsSupported) { + console.log("The browser supports simd and threads, but the path of OpenCV.js with simd and threads optimization is empty"); + } + + if (simdSupported) { + console.log("The browser supports simd optimization, but the path of OpenCV.js with simd optimization is empty"); + } + + if (threadsSupported) { + console.log("The browser supports threads optimization, but the path of OpenCV.js with threads optimization is empty"); + } + + OPENCV_URL = wasmPath; + console.log("The OpenCV.js for wasm is loaded now"); + } else if (wasmSupported) { + console.log("The browser supports wasm, but the path of OpenCV.js for wasm is empty"); + } + + if (OPENCV_URL === "") { + throw new Error("No available OpenCV.js, please check your paths"); + } + + let script = document.createElement('script'); + script.setAttribute('async', ''); + script.setAttribute('type', 'text/javascript'); + script.addEventListener('load', () => { + onloadCallback(); + }); + script.addEventListener('error', () => { + console.log('Failed to load opencv.js'); + }); + script.src = OPENCV_URL; + let node = document.getElementsByTagName('script')[0]; + if (node.src != OPENCV_URL) { + node.parentNode.insertBefore(script, node); + } +} \ No newline at end of file diff --git a/platforms/js/build_js.py b/platforms/js/build_js.py index fbeb1e4fb33d8d926f76a0381ff1d71b2c245e56..38e988a3bd31a619c8dd61fb4b7c4754d0a1b4c1 100644 --- a/platforms/js/build_js.py +++ b/platforms/js/build_js.py @@ -201,6 +201,9 @@ class Builder: def build_doc(self): execute(["make", "-j", str(multiprocessing.cpu_count()), "doxygen"]) + def build_loader(self): + execute(["make", "-j", str(multiprocessing.cpu_count()), "opencv_js_loader"]) + #=================================================================================================== @@ -221,6 +224,7 @@ if __name__ == "__main__": parser.add_argument('--build_test', action="store_true", help="Build tests") parser.add_argument('--build_perf', action="store_true", help="Build performance tests") parser.add_argument('--build_doc', action="store_true", help="Build tutorials") + parser.add_argument('--build_loader', action="store_true", help="Build OpenCV.js loader") parser.add_argument('--clean_build_dir', action="store_true", help="Clean build dir") parser.add_argument('--skip_config', action="store_true", help="Skip cmake config") parser.add_argument('--config_only', action="store_true", help="Only do cmake config") @@ -292,6 +296,11 @@ if __name__ == "__main__": log.info("=====") builder.build_doc() + if args.build_loader: + log.info("=====") + log.info("===== Building OpenCV.js loader") + log.info("=====") + builder.build_loader() log.info("=====") log.info("===== Build finished") @@ -316,3 +325,8 @@ if __name__ == "__main__": opencvjs_tutorial_path = find_file("tutorial_js_root.html", os.path.join(builder.build_dir, "doc", "doxygen", "html")) if check_file(opencvjs_tutorial_path): log.info("OpenCV.js tutorials location: %s", opencvjs_tutorial_path) + + if args.build_loader: + opencvjs_loader_path = os.path.join(builder.build_dir, "bin", "loader.js") + if check_file(opencvjs_loader_path): + log.info("OpenCV.js loader location: %s", opencvjs_loader_path)