mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 07:13:02 +04:00
5.x
228 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f968fb969f |
Broadcasting element-wise engine for cv::Mat (+ cv::texpr) (#29426)
* experimental new arithmetics; work-in-progress * continue working on new-gen arithmetic expressions * * improved performance of the new add on small arrays * added sub * extended tests * fixed potential bug when adding multi-channel array and a single-channel scalar * improved const handling * * added copyMask * added mul/dev (without scale so far) * * accelerated mul * addedd scale to mul and div * * done substantial refactoring; however a few more rounds of refactoring are ahead. * added min, max, absdiff, addweighted. * improved performance of the new arithmetic functions, but some of them are still slow, e.g. operations with mask have some bugs (that affect speed, not accuracy). * * further (significantly) accelerated several functions, especially on small arrays: mul, binary ops with mask * further polished the new arithmetic engine * started integration of the new element-wise arithmetic engine into core * big step forward. We now use the new engine inside cv::add, subtract, multiply, divide, absdiff, min and max. * big progress: * added bitwise operations * fixed and accelerated compare * ported regression tests to test new broadcasting behaviour of arithmetic functions * lot's of improvements in compare, divide, addWeighted! * lot's of small and big performance improvements in the new arithmetics * * some more optimizations; parsing texpr-expressions is now faster as well * port new_arithm to Linux/x86: dispatch guards, scalar-Mat compat fallback, dnn shape-contract fixes Core: - arithm.simd.hpp: CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY guards (the file is included once per dispatched mode on x86), vx_load_expand instead of the 128-bit v_load_expand, VTraits::vlanes() instead of ::nlanes - arithm.cpp/precomp.hpp: compat fallback for scalar-like Mat operands (1x1, 1xcn/cnx1, 4x1 CV_64F - java/python tuples, operator-(Mat, Matx)): treated as a per-channel scalar ONLY when the shapes are not broadcast-compatible, so every valid numpy-style broadcast keeps its meaning and calls that would otherwise throw get the 4.x semantics DNN (fallout of the stricter shape semantics, found by the new engine): - dict.hpp: DictValue relied on fresh AutoBuffer having size()==fixed_size; allocate explicitly - batch_norm: weights_/bias_ are 1-D [n] now; 0/1-D forward runs on exact-shape 1-D views - net_impl2: extend the post-forward sanity check to non-temp outputs - a layer that reallocates its preallocated output tensor now fails loudly instead of silently detaching the result from the graph - LSTM/LSTM2 batchwise (layout=1): getMemoryShapes now matches what forward() writes (ONNX: Y=(batch,seq,dirs,hid), Yh/Yc=(batch,dirs,hid)); forward assembles seq-major results in a local buffer and transposes INTO the preallocated outputs in place Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * u8/s8 multiply: exact integer SIMD path on non-FP16 builds (3-10x vs 5.x) The unit-scale branch of vecBinaryKernel already supported a separate work-vector type Wvec1 (used by the ARM f16 build and by u16/s16 everywhere), but on x86 the u8/s8 same-type multiply still went through the f32 hub. Route it through v_uint16/v_int16: products of 8-bit values fit exactly (255^2 < 2^16), the saturating pack on store gives bit-exact results at half the vector traffic. Also fix a latent kernel bug this exposed: the unit-scale branch stepped by Wvec's lane count while loading/storing Wvec1 vectors. All previous Wvec1 instantiations had equal lane counts, but u8's v_uint16 has 2x the lanes of v_float32 - the pairs overlapped (50% redundant work) and the tail backoff could write VECSZ bytes past the row end. The branch now derives its step, offsets and tail condition from Wvec1 itself. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * vecBinaryKernel: constexpr Op::useScalar instead of a runtime-only scale check Every binary op functor now declares whether it consumes the scale scalar (params[0]): true only for mul and the two div variants. Ops that ignore it (add/sub/min/max/absdiff) take the fast 2-arg branch unconditionally - the 'scalar == 1' check used to fail for them (their params[0] is 0), sending them through the preproc branch, and the condition now folds at compile time. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * restore cv::hal::mul8u as a wrapper over the element-wise engine The symbol is still declared in core/hal/hal.hpp and called directly by external code (the G-API fluid backend in opencv_contrib), but its implementation went away with the old arithm kernels. Forward it to getMulFunc(CV_8U, CV_8U) - with scale==1 it lands on the new exact integer SIMD path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * silence every new-arithm warning reported by CI (ARM64/Mac) and gcc 15 - arithm.cpp: bitwise_op_ocl and the actualScalarDepth/coerceTypes helpers are consumed only by the OpenCL paths - guard them with HAVE_OPENCL; haveScalar in cv::compare is read only inside CV_OCL_RUN - CV_UNUSED for OpenCL-less builds - arithm_expr.hpp: declare getBitwiseFunc/getNotFunc/getAddWeightedFunc next to the other per-op entry points (-Wmissing-prototypes in arithm.dispatch.cpp) - arithm.simd.hpp: define CV_SIMD_16F to 0 when FP16 SIMD is absent (-Wundef); {}-init the expandScalar staging buffers (-Wmaybe-uninitialized: they are fully written before use, but the compiler cannot prove it with runtime vector widths); rename the compare kernel's lambda parameter (-Wshadow) - arithm_expr.cpp: rename the exec tile-lambda's hot-field locals that shadowed TExpr members and outer locals (-Wshadow) - test_new_arithm_extensive.cpp: rename the name-generator lambdas' parameter shadowing the INSTANTIATE macro's own (-Wshadow), drop an unused variable Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * restore 4.x scalar semantics for the bindings' 4x1 CV_64F Scalar columns The python/java bindings materialize numbers and tuples as a 2-D 4x1 CV_64F Mat - or UMat, when the call carries UMat arguments. Three CI-reported python failures came from those pseudo-scalars reaching the engine as arrays: - absdiff(int_arr, 0): the (4,1) column is broadcast-COMPATIBLE with a 1-D array, so numpy semantics silently won - an outer-product f64 result instead of the int per-channel-scalar one; - subtract(u8 4x8x4, (40,)): same, by the rows==4 coincidence; - multiply(UMat, 2., dst=UMat): the scalar arrives as a UMAT, which the scalar detection did not recognize at all. isScalarArg now treats the exact bindings shape - 2-D 4x1 CV_64F single-channel Mat/UMat against a <=4-channel array - as a scalar UNCONDITIONALLY (a 1-D [4] array has dims==1 and still broadcasts). One exception, decided in arithm_op: when the partner is itself a tiny scalar-shaped array, both are honest data and ride the broadcast (compare(Mat 4x1, Mat 1x1) - issue #8999 - stays elementwise). Small-array discipline, this all runs per engine call: the probes read Mat/UMat fields directly (rows == 4 alone rejects almost everything, no _InputArray getter dispatch), and a UMAT scalar's 32 bytes are copied into a caller-stack buffer - no heap, no getMat mapping. Measured: no latency change on 4x4/16x16 element-wise calls. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * cv::texpr: std::string_view -> const std::string& in the public API string_view in an exported signature breaks some CUDA toolchain builds, and for short expression strings the difference is immaterial (SSO, parsed once). The parser internals keep string_view - the argument converts implicitly. Also drop the now-unused <string_view> include from cvstd.hpp, so the header does not reach every nvcc TU. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * compare boundary-rewrite: fixed 4-slot kind/bound arrays instead of AutoBuffers A CONST operand is capped at 4 channels (addConst), so the per-channel kind/bound staging needs no dynamic buffers - plain int[4]/double[4], with a CV_Assert on the contract. This is also what gcc's -Wmaybe-uninitialized was flagging (it could not see the AutoBuffer's inline storage get filled). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * element-wise engine: unary math kernels (sqrt/exp/log/sin/cos/tanh/erf/relu) + select New dispatched pair math.simd.hpp / math.dispatch.cpp - the unary/ternary sibling of arithm.simd.hpp: - vecUnaryKernel: T -> T over f16/bf16/f32/f64 on top of the intrin_math primitives (v_exp/v_log/v_sin/v_cos/v_sqrt/v_erf/v_max). f32/f64 compute natively, f16/bf16 ride the f32 hub inside the kernel (vx_load_pair_as / v_store_pair_as) - no materialized casts. Continuity collapse + the halide right-edge backoff, suppressed in-place (it would re-apply Op to already-written values). tanh = (e^2x-1)/(e^2x+1) with the input clamped to +/-10 (f32) / +/-20 (f64) - unclamped saturation hits inf/inf = NaN. erf has no f64 SIMD primitive: std::erf per lane. - selectKernel(mask, x, y): 1-byte mask expanded to lane width and tested against zero in the INTEGER domain (immune to DAZ/FTZ), branches of any depth by element size, broadcast branches supported. - emitUnary: math over a float input is T -> T now (f16 in -> f16 out, native kernel when input and result depths match); integer inputs still compute in the float domain and land in f32. - emitTernary/select: literal branches are typed via typedConstFrom (an OP_CAST of a depth-less flex const crashed); a non-1-byte mask is normalized by an explicit "mask != 0" compare, never a value cast. texpr already parsed the function names - they now execute. Tests: per-depth accuracy of all 8 ops against the double std:: reference, integer input, in-place, select over 4 depths / const branch / float mask. Perf vs the classic kernels (1920x1080 f32, 16 threads, AVX2): exp 3.7x, log 2.6x, sqrt 5.7x faster; polarToCart expressed as (r*cos(a), r*sin(a)) 4.0x. Accuracy improves too (max rel err vs f64 reference): exp 8.1e-8 vs 2.1e-7, log 8.0e-8 vs 1.5e-7. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * engine: OP_COPY_MASK folded into OP_SELECT; selectKernel moved to arithm.simd.hpp copyMask(dst, mask, src) is select(mask, src, dst) - one masking primitive instead of two. The compiler emits the masked-op tail as addInsn(OP_SELECT, mask, r, out, out): the output slot rides as both arg2 and the result, so unmasked elements are preserved by reading them back through the b-branch. OP_COPY_MASK, copyMaskKernel and getCopyMaskFunc are gone. selectKernel (moved from math.simd.hpp to arithm.simd.hpp) inherits every copyMaskKernel optimization: - the interleaved multichannel fast path (2..4 channels under a per-pixel mask: expand the mask once per VECSZ rows, v_store_interleave across lanes); - the per-row scalar path with the row-skip when the selected source row IS dst (the "leave the output untouched" half of copyMask); - plus the select-specific ones: branch broadcasts (stepx == 0) and the right-edge tail backoff under dst-aliases-a-branch - safe because re-running select over already-blended elements is idempotent; only dst == mask keeps the backoff off (the store would rewrite mask bytes before the re-read). Masked-add perf is on par with the old copyMask (1280x720, 1 thread: 8UC3 204 -> 198 us, 32FC3 1395 -> 1344, 8UC1/32FC1 within noise). Full core suite 24117 green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * engine: dedicated vectorized pow kernel (moved from arithm to math.simd.hpp) pow was the last scalar-only binary op (scalarBinaryKernel + std::pow, f32/f64 only). The new powKernel keeps exact std::pow semantics and is T x T -> T over all four float depths (f16/bf16 via the f32 hub): - scalar exponent (the dominant call shape - texpr literals ride as 0-dim broadcast consts) is dispatched PER ROW to the special cases: y==2 -> x*x, y==3 -> x*x*x, y==0.5 -> v_sqrt, y==1 -> copy, y==0 -> fill 1; - everything else - including a per-element exponent array - runs the general vectorized exp(y * log(x)) path, valid for x > 0; a vector pair containing any x <= 0 lane falls back to scalar std::pow for that pair (v_check_any), which preserves every std::pow subtlety: signed results for integer y on negative bases, NaN for fractional y, the x == 0 family; - no right-edge tail backoff: pow is not idempotent, in-place calls finish rows in the scalar tail. Perf vs the classic cv::pow (1920x1080 f32, 16 threads, AVX2): p=2 1.4x (classic special-cases it too), p=3 6.1x, p=0.5 6.3x, fractional p 4.5x with slightly better accuracy (6.1e-7 vs 7.4e-7 max rel err). Tests: exponent sweep 2/3/0.5/1/0/2.5/-1.5 vs the double std::pow reference on f32/f64, negative bases (exact signed cubes, NaN for fractional), array exponent. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * powKernel: halide right-edge tail backoff in every SIMD loop Same shape as vecBinaryKernel: the final partial vector re-processes [width - VECSZ*2, width) instead of finishing scalar, suppressed when dst aliases an input (pow is not idempotent - the overlap region must be recomputed from an untouched source, which the no-alias case guarantees). Modest measured win (~2% on ROI rows for the special-cased exponents; the general path tail was already cheap - modern libm powf is fast), no regressions; mainly aligns the kernel with the house style, where every SIMD loop ends vector-wide. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix MSVC 2019 C2975: function-local constexpr as a template argument inside a lambda MSVC 2019 loses the constexpr-ness of function-local constants (LOCAL_OPS, MAX_DIMS, ...) when they are used as template arguments inside a lambda body (AutoBuffer<Slice, LOCAL_OPS> / std::array<int, MAX_DIMS> in the parallel bodies of BroadcastOp::run and TExpr::exec). Hoist them to namespace scope - no behavior change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ocl_arithm_op: route 16U multiply to the CPU engine on Apple OpenCL The Apple OpenCL driver miscompiles the 16U multiply kernel: products near the top of the u16 range come back wrapped instead of saturated (CPU vs GPU NORM_INF up to 65535 in OCL_Arithm/Mul.Mat CV_16U cases). The same arithm.cl kernel is correct on Intel NEO and NVIDIA drivers - verified not to reproduce on Linux/Intel iGPU - so gate the decline to __APPLE__ only; the CPU engine computes 16u multiply exactly (integer SIMD path). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * engine: neg/abs as compositions, clamp kernel, ** and ?: operators, abs(a-b) peephole - OP_NEG and OP_ABS need no kernels: neg = sub(0, a), abs = absdiff(a, 0) - including the engine absdiff auto-type rule (signed |a| lands in the UNSIGNED type of the same width: |SHRT_MIN| fits u16 exactly instead of saturating; NB the public cv::absdiff auto depth keeps the source type for 4.x compatibility - values agree, the depth rule is the engine own). - peephole: abs(x - y) rewrites to absdiff(x, y) ALWAYS. On integers the literal semantics differ (the subtract saturates first: u8 gives max(x-y, 0)), but whoever writes abs(a - b) means absdiff - we deliberately hand out the useful semantics instead of the saturation artifact. The just- emitted OP_SUB is retired via the moveToOutput manoeuvre, so the program shrinks to the single absdiff instruction. abs(x), abs(x - 0) and absdiff(x, 0) all give one result. - OP_CLAMP kernel (arithm.simd.hpp): v_min(v_max(x, lo), hi) over u8/s8/u16/s16/u32/s32/f32 (+f64 with 64-bit SIMD), scalar f16/bf16/64-bit ints; lo/hi may broadcast (the common clamp(img, a, b) shape) or be full arrays; the tail backoff stays on under dst-aliases-x (clamp is idempotent). emitTernary types literal bounds via typedConstFrom (same flex-const crash select had) and keeps the auto result type pinned to x. - parser: "a ** b" == pow(a, b), precedence above * /, RIGHT-associative (a ** 2 ** 3 == a ** 8); "cond ? a : b" == select(cond, a, b), precedence below everything, right-associative chains (f1 ? a : f2 ? b : c) work without parentheses. parseTernary() is the expression entry point now. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * cv::exp/log/sqrt on the engine via math_op; hal functions wrapped as engine kernels math_op is the master function of the unary math family (the arithm_op analogue): same-shape same-type output over f16/bf16/f32/f64 (classic exp/log accepted f32/f64 only - the half floats are new), two tiers: - small (<= 100000 elements) and continuous: call the kernel DIRECTLY over the flattened data - no TExpr, no broadcastOp, no parallel_for setup; - everything else: the usual single-instruction program via compile()/exec() (parallelism for large arrays, real steps for ROIs). getMathFunc routes OP_EXP/OP_LOG at f32/f64 through the full cv::hal stack - an external vendor HAL (CALL_HAL), IPP, or the built-in table kernels, whichever is installed - by wrapping hal::exp32f/exp64f/log32f/log64f as engine kernels with the function pointer in TKernel::userdata, the same mechanism castKernel uses for core BinaryFuncs. The engine adds tiling and parallelism on top, so every tier gets the best available scalar-span implementation. v_exp/v_log remain for f16/bf16 (the f32 hub) and the ops hal has no entry points for. v_log_default_32f: the degree-8 polynomial is evaluated by Estrin pairing (4 dependent levels) instead of an 8-FMA Horner chain (~5% on the f16 hub path). An exp64 Taylor-without-division rewrite was tried and benched SLOWER than the Cephes Pade scheme (the evaluation is FMA-throughput-bound, and vdivpd pipelines well enough) - reverted; a table-based reduction is the only way further there. cv::exp f32 (16 threads, AVX2+IPP build), old -> new: 640 elements 0.16 -> 0.15 us, 16k 2.79 -> 2.49, 640x480 47 -> 20, 1920x1080 452 -> 60 us (the old CPU loops were single-threaded); f64 exp 1080p 1295 -> 161 us. No size regresses; small arrays now run at installed-HAL speed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * getMathFunc: IPP tier + raw-HAL probing; the exp/log table kernels are deleted The raw cv_hal_* entry points return int for a reason: without an installed HAL they are stubs returning CV_HAL_ERROR_NOT_IMPLEMENTED. getMathFunc now selects the exp/log implementation in three tiers: 1. HAVE_IPP && ipp::useIPP(): ippsExp/ippsLn through thin int adapters (IPP is not routed through the cv_hal_ hooks, so it needs its own tier); 2. the raw cv_hal_exp32f/... hook, PROBED once with a 1-element call on the safe input 1.0 (cached in magic statics): implemented -> wrapped as an engine kernel with the function pointer in TKernel::userdata; 3. the engine own v_exp/v_log kernels. Whichever wins, the engine adds tiling and parallelism on top. The EXPTAB/LOGTAB table kernels and their tables (~790 lines in mathfuncs_core.simd.hpp + mathfuncs.cpp) are DELETED: they benched within ~15% of v_exp/v_log, not worth a second implementation. The public cv::hal::exp32f/exp64f/log32f/log64f keep their contract - CALL_HAL, then IPP, then the built-in implementation - but the built-in is now the engine vector kernel via ew::mathSpanEngine (one contiguous span, exported from math.dispatch.cpp). All unary math kernels (vec/scalar/hal wrappers, pow) also handle the vertical-broadcast tile (s0y == 0, a row expanded into a matrix): the first row is computed, the rest are memcpy of it - transcendentals cost far more than a row copy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * texpr: hypot(x, y) binary op (alias: mag) hypot = sqrt(x^2 + y^2), NAIVE like cv::magnitude (not the overflow-safe std::hypot), computed in the float work type; kernels for the four float depths only (T x T -> T; integer inputs ride the usual f32-compute + cast). A 10-line EwHypot functor on top of vecBinaryKernel in arithm.simd.hpp - broadcast branches, continuity collapse and the tail backoff come for free. Registered in the parser as both "hypot" (the C/numpy name) and "mag" (the cv::magnitude-flavored alias). A building block for the future cartToPolar. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * texpr: atan2(y, x) binary op - radians, standard C range v_atan2 (arithm.simd.hpp, generic over the universal-intrinsic float vector): the fastAtan2 minimax polynomial from mathfuncs_core v_atan_f32 reworked to plain radians - the 180/pi factor dropped from the coefficients and the C quadrant logic instead of the [0, 360) wrap, so the result matches std::atan2 over (-pi, pi]. Measured absolute accuracy ~1.6e-4 rad. (v_atan_f32 itself is untouched - cv::phase/fastAtan2 keep their degree semantics.) EwAtan2 rides vecBinaryKernel: f16/bf16/f32 through v_atan2 (the f32 hub), f64 through exact scalar std::atan2. arg0 = y, arg1 = x, like std::atan2; float depths only, same emitBinary policy as pow/hypot. Parser name "atan2". Together with hypot this completes the cartToPolar building blocks. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix the RISC-V RVV build and two ARM64 warnings The new f64 kernel registrations (hypot, pow, the unary math family) gate on CV_SIMD_64F || CV_SIMD_SCALABLE_64F, but the vx_setall_as(const double*, v_float64&) helper family in arithm.simd.hpp was still CV_SIMD_64F-only - scalable platforms (RVV) have v_float64 with CV_SIMD_64F == 0, so vecBinaryKernel<double, ...> failed to instantiate there. Widen the helper gate to match (verified with a riscv64 rv64gcv cross-build of opencv_core - the engine f64 paths now vectorize on RVV instead of not compiling). cv::exp/cv::log: the depth local is consumed by CV_OCL_RUN only - CV_UNUSED for OpenCL-less builds (ARM64 -Wunused-variable). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * silence the remaining ARM64 gcc warnings - compare boundary-rewrite: {}-init the fixed kind/bound arrays (filled for every channel used below, but gcc cannot prove it across the cn <= 4 loop); - cv::exp/log: [[maybe_unused]] on the depth local (consumed by CV_OCL_RUN only), instead of the CV_UNUSED idiom; - AutoBuffer::reserve: a targeted -Wmaybe-uninitialized suppression around the live-element copy loop - only [0, sz) is read, all written before, but gcc inlining a grow-from-inline-storage chain cannot see that. An annotation for the analyzer, no behavior change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * saturating 32-bit add/sub kernels; cv::texpr python binding; two CI warnings - v_add_sat/v_sub_sat for v_int32/v_uint32, local to arithm.simd.hpp for now (the plan is to grow them into proper universal intrinsics later): NEON single-instruction vqadd/vqsub, elsewhere the Hacker Delight bit tricks over universal intrinsics (u32 add is 2 ops: or with the wrapped-compare mask). EwAdd/EwSub overload vec() for the 32-bit lanes and getAddSubFunc routes 32S/32U T->T through vecBinaryKernel instead of the former pure scalar kernel. Semantics unchanged - the scalar int64 tail already saturated; directed boundary tests added (both rails, 0 - INT_MIN, u32 cases, a full-range random block vs an exact int64 reference). 640x480 32S add: 0.48x of 5.x -> parity (memory-bound); 1080p: 6-8x. - cv::texpr becomes CV_EXPORTS_W: python gets cv.texpr(expr, [inputs]) -> tuple of ndarrays, so `res, = cv.texpr(...)` and `mag, ang = cv.texpr(...)` unpacking both work. modules/python/test/test_expr.py covers arithmetic, the fused abs(a-b), casts, broadcasting, ?: and ** operators, math functions vs numpy, clamp, named temporaries, tuple outputs, the one-line cartToPolar and the int32 saturation cases. - warnings: {}-init the parser args array (gcc -Wmaybe-uninitialized on Ubuntu 20/22); the compare short-row block gates sizeof(T) <= 4 as constexpr so the f64 instantiation does not leave set-but-unused locals (gcc 9 -Wunused-but-set-variable). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * arithm_op: direct-kernel fast path for small continuous arrays Building and compiling the 1-instruction program plus the BroadcastOp setup costs ~40-250ns per call - negligible on big images, dominant at 127x61-class sizes where the classic 5.x functions were 1.3-2x faster. Mirror math_op two tiers in arithm_op: two same-type same-shape continuous arrays, no mask, no scalar, result depth == input depth, <= 100k elements -> call the T x T -> T kernel directly over the flattened elements (checks ordered cheapest-first). Applies to add/subtract/min/max/absdiff/multiply/addWeighted/and/or/xor; compare and divide lower to more than a single kernel (boundary rewrites, int guards) and keep the ordinary path. addWeighted falls through automatically for the 32/64-bit int types whose lowering is wide-compute + cast (getElemwiseFunc returns no direct kernel there). 127x61 vs 5.x, was -> now: add/subtract 8UC1 0.76x -> 1.3x, min/max u8 0.6x -> ~1x, addWeighted 1.0x -> 1.1-1.4x (32SC1 stays 4.5x); the one remaining laggard is add/sub 32SC1 (0.74-0.82x) - the price of the new SATURATING semantics (7-instruction AVX2 emulation vs the wrapping single add of 5.x; single-instruction on NEON). The 127x61 size is ADDED PERMANENTLY to the arithmetic/addWeighted/compare perf grids: per-call overhead regressions in these base functions must be caught by CI, not discovered by users. dst creation goes through createSameSize (whole-shape transfer including layout and future metadata, not piecemeal dims+sizes) here and in math_op. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * cv::pow rebuilt on the engine; integer-exponent and 1/sqrt(x) kernel branches Routing: p = 0/1/2 keep their early special cases (fill/copy/multiply); an INTEGER array with an INTEGER power keeps the classic iPow multiply chain - bit-exact compatibility, including its wrap-around quirks (iPow squares in int, so e.g. pow(255,4) on u8 wraps negative and saturates to 0 - somebody may rely on that). Everything else goes through the engine with the math_op two-tier scheme: small continuous arrays call powKernel directly (the exponent rides as a broadcast T scalar), the rest run the tiled parallel program. Integer arrays with fractional powers compute in the float domain and saturate back; the 32U/64-bit depths (classic iPow asserted on them) and f16/bf16 (the classic float path misread them) now just work. powKernel gets two new per-row exponent branches: - p == -0.5: 1/v_sqrt(x) (the classic path used IPP ippsInvSqrt_A21, a 21-bit approximation; ours is exact - slightly slower on small arrays, 4.5x faster at 1080p via parallelism); - any other INTEGER p (|p| <= 65536): LSB-first binary exponentiation, the same multiply chain and order as iPow, fully vectorized - a few ulp accurate vs ~2e-7 of exp(p*log x), and exact on non-positive bases (the sign falls out of the multiplies, 0^negative divides to inf) - no scalar patching. cv::pow f32 vs 5.x: p=0.5 365 -> 61 us at 1080p (6x), p=3 7.7x, p=5 7x AND faster at every size (the old scalar chain: 0.81 -> 0.47 us at 127x61), p=2.5 5.3x. The s16^5 iPow path is untouched (118.7 == 118.5 us). pow_exponents accuracy tests extended to 11 exponents x f32/f64 against the double std::pow reference. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * perf: SANITY_CHECK_NOTHING for the tests whose grids got the 127x61 size The 127x61 entry added to guard per-call overhead has no regression data in opencv_extra, so the legacy SANITY_CHECK in addWeighted/compare failed on CI (locally it passes silently without the test-data path). Accuracy of both functions is covered by the accuracy suite; the perf tests should measure time. PatchNaNs/finiteMask keep their SANITY_CHECK - their grids are untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix a temp-buffer double release in the liveness pass ("d*d" crash) When the same temp is passed as SEVERAL arguments of its last-use instruction (e.g. the named-intermediate expression "d = {0} - {1}; d*d", where the MUL consumes slot d twice), the buffer-reuse scan pushed the temp's physical buffer onto the free list once per argument. That overflows the ntemps-sized freeBufs array (caught by the AutoBuffer range check in Debug: python test_expr.py::test_named_temporary) and, in larger programs, would hand the same physical buffer to two live temps. Release the buffer once by retiring lastUse[t] after the first hit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * executor: recalibrate opCost to vectorized cycles + clamp the stripe count The per-element op costs fed into the parallel_for_ stripe hint were scalar-era estimates (~20x above the vectorized reality: the atan2/exp polynomials run at ~1.5 cycles/element, not 30). The hint therefore split transcendental/divide work into hundreds of ~1 us jobs, which the macOS/GCD backend dispatches poorly under sustained load, on top of the P/E-core equal-share straggler effect. Measured on M4 Max (12P+4E), sustained medians @1920x1080 f32: texpr atan2 320 -> 133 us, cv::exp 280 -> 141 us, cv::log 301 -> ~200 us, cv::pow(x,2.5) 388 -> 376 us; the PR tables' math rows improved ~1.5-2x across the board. - opCost is now in units of ~1/4 cycle/element of the SIMD kernels: cheap ops 1 (unchanged), div/sqrt/hypot/convert_scale 10 -> 3, transcendentals 30 -> 6. - the stripe hint is clamped by min(4*nthreads, max(32, 3*nthreads)): ~4 stripes/thread is plenty of granularity for element-wise work, and the ceiling is 32 pieces except on machines with many (heterogeneous) cores, where anything coarser than ~3 pieces/worker turns the slow cores into equal-share bottlenecks (measured: 32 stripes on 16 threads is the worst point of the curve - 193 us vs 137 us at 48 for atan2). getNumThreads() is clamped from below (WINRT/plugin backends may report 0). Not addressed here (needs cross-machine data, M2/M3 Ultra): streaming memory-bound ops saturate the M4 Max fabric at ~8 fat stripes and E-core participation only adds contention - a cost model cannot express that; candidate follow-up is a bytes-aware clamp or a GCD-backend-level fix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * multiply: v_mul_sat integer kernels (full product clamped to the type) v_mul_sat(V, V) -> V for u8/s8/u16/s16/u32/s32 - the full-precision product clamped to the lane type, which is exactly cv::multiply's integer semantics at scale == 1. Local to arithm.simd.hpp for now, next to v_add_sat/v_sub_sat, to be promoted into proper universal intrinsics later. NEON: widening vmull + saturating narrow (vqmovn); other backends: the portable v_mul_expand + saturating v_pack composition for 8/16-bit lanes. 32-bit lanes have no universal widening multiply (no v_mul_expand for s32), so the 32-bit integer fast path is NEON-only for now and the other backends keep the previous f64 work-vector kernels (which measure well on x86 with IPP-free AVX2). EwMul::vec() now routes the integer lane types through v_mul_sat, and getMulFunc_ passes the NATIVE lane vector as the scale==1 fast-path type: whole-register loads/stores, the widening happens inside the multiply. Replaces both the half-register widening loads (u8/s8/u16/s16) and the scalar-equivalent f64 path for 32S/32U on NEON. M4 Max, 640x480 (the sizes where the old kernels lost to carotene): 8U 22.0 -> 13.6 us, 8S 15.0 -> 11.1, 16S 21.2 -> 17.4, 32S 84.8 -> 30.5 (parity with the classic path everywhere, 32S was 0.38x). 1920x1080: 8S 1.30x -> 1.78x, 16S 2.57x -> 2.98x, 32S 2.20x -> 4.02x vs 5.x. Correctness: exhaustive 8-bit (all 65536 pairs per sign), directed saturation corners for 16/32-bit (46341^2, INT_MIN*-1, 65536*65536, all sign combinations) against an exact int64 reference. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * NEON: make v_cvt_f64(v_int32) exact (was via f32, losing bits > 2^24) The NEON implementations of v_cvt_f64/v_cvt_f64_high for v_int32 did s32 -> f32 -> f64 (vcvt_f32_s32 + vcvt_f64_f32), silently rounding any |x| > 2^24. Every vectorized f64 work path with int32 inputs on AArch64 was affected: the engine's addWeighted/divide 32S kernels, convertTo 32S -> 64F, etc. Found via addWeighted 32SC1 on values ~1e9: max error was 32 vs the exact double reference (the classic carotene path is worse still - it computes in f32 end-to-end with f32-truncated weights, max error 96 on the same data). The exact sequence sxtl + scvtf (vmovl_s32 + vcvtq_f64_s64) is the same 2 instructions, so there is no cost. addWeighted 32SC1 on the engine now matches the exact-double reference bit-for-bit and stays at parity/1.4x vs the classic path (640x480/1920x1080). Pre-existing upstream bug (same code in 4.x) - worth a standalone backport with directed large-value tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * math_op: drop the temporary direct-IPP tier for exp/log Upstream moved the IPP math wrappers into the hal/ipp HAL module (cv_hal_exp32f/ log32f & co now resolve to ipp_hal_* which honor cv::ipp::useIPP via CV_HAL_CHECK_USE_IPP). The engine's single probeHalUnary(cv_hal_*) probe already picks that up uniformly, so the stopgap #ifdef HAVE_IPP ippExp/ippLog tier and its ipp::useIPP() branch in getMathFunc are now redundant - removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * arithm: restore cv::hal::and8u/or8u/xor8u/not8u as engine wrappers These public CV_EXPORTS entry points (core/hal/hal.hpp) lost their definitions when the bitwise ops moved to the element-wise engine, but they are still declared and called by other modules (opencv_objdetect's aruco) and external code - the link broke with undefined references to cv::hal::and8u/xor8u. Restore them as thin forwarders over the engine's byte-wise bitwise kernels (getBitwiseFunc / getNotFunc), mirroring the existing mul8u wrapper. CV_Assert guards the kernel lookup. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * blobdetector: guard empty contour when computing blob radius The new AutoBuffer leaves its tail uninitialized for trivial types, which surfaced a -Wmaybe-uninitialized in findBlobs where the median of per-point distances is read. Use a std::vector, default the radius to 0, and compute the median only for a non-empty contour - no unproven size invariant. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
abb0115648 | Merge branch 4.x | ||
|
|
e6d0c0340b |
Merge pull request #29413 from amd:fast_basic_op
core: Fix mul32f and addWeighted32f to use native f32 SIMD paths #29413 OpenCV Extra: https://github.com/opencv/opencv_extra/pull/1388 - add 32FC1 coverage to addWeighted benchmark - avoid intermediate double for f32 variants of scaled multiply and addWeighted. - Relax AddWeighted 32F test tolerance to match f32 FMA semantics. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake |
||
|
|
74a25df87e |
Merge pull request #28706 from amd:perf_gemm
Perf test for gemm #28706 OpenCV Extra: https://github.com/opencv/opencv_extra/pull/1336 - Added perf test to verify gemm performance. - small sizes, square & rectangular matrix shapes are added. - special case of n=1 and m=1 are added. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake |
||
|
|
5137676ea7 |
Merge pull request #29172 from hcy11123323:op
Fast-path transposeND for identity and 2D transpose orders #29172 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake <!-- Note!!! If you are an automated agent, we have a special process for you: add 🤖🤖🤖 to the end of the PR title. --> This PR adds fast paths to cv::transposeND() for two common cases: - identity permutation: dispatch to copyTo() - 2D permutation {1, 0}: dispatch to transpose() All other permutations continue to use the existing generic ND implementation. Why: transposeND() currently falls back to the generic memcpy/index-update loop even for the common 2D transpose case, while OpenCV already has an optimized transpose() path. Reusing that path avoids unnecessary index arithmetic and improves performance for 2D inputs passed through transposeND(). Performance: [BinaryOpTest.transposeND/21 (1920x1080, 8UC3): 28.21 ms -> 0.66 ms (-97.7%)] [BinaryOpTest.transposeND/22 (1920x1080, 8UC4): 37.61 ms -> 0.88 ms (-97.7%)] [BinaryOpTest.transposeND/29 (1920x1080, 32FC1): 10.26 ms -> 0.75 ms (-92.7%)] Full transposeND perf subset: 6760 ms -> 592 ms (-91.2%) |
||
|
|
1a6f669763 | Merge branch 4.x | ||
|
|
a4d9b45168 | Benchmark cv::mean instead of cvtest::mean | ||
|
|
350b211b57 | Merge branch 4.x | ||
|
|
f8de2e06e6 | Merge branch 4.x | ||
|
|
7a9ce585f0 | core(ocl): fix POWN OpenCL implementation | ||
|
|
3bfc408995 |
Merge pull request #27261 from fengyuentau:5.x-merge-4.x-norm-hal_rvv
5.x merge 4.x: merge changes of norm and norm_diff in hal rvv from 4.x #27261 Merge with https://github.com/opencv/opencv_extra/pull/1251 No related changes in contrib https://github.com/opencv/opencv/pull/26991 from fengyuentau:4x/core/norm2hal_rvv https://github.com/opencv/opencv/pull/27045 from fengyuentau:4x/hal_rvv/normDiff Previous "Merge 4.x" on norm_diff vectorization: https://github.com/opencv/opencv/pull/27068 |
||
|
|
2fb786532a |
Merge pull request #27257 from fengyuentau:4x/hal_rvv/flip_opt
hal_rvv: further optimized flip #27257 Checklist: - [x] flipX - [x] flipY - [x] flipXY ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake |
||
|
|
325e59bd4c |
Merge pull request #27229 from fengyuentau:4x/hal_rvv/transpose
HAL: implemented cv_hal_transpose in hal_rvv #27229 Checklists: - [x] transpose2d_8u - [x] transpose2d_16u - [ ] ~transpose2d_8uC3~ - [x] transpose2d_32s - [ ] ~transpose2d_16uC3~ - [x] transpose2d_32sC2 - [ ] ~transpose_32sC3~ - [ ] ~transpose_32sC4~ - [ ] ~transpose_32sC6~ - [ ] ~transpose_32sC8~ - [ ] ~inplace transpose~ ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake |
||
|
|
1b3db545a3 |
Merge pull request #27145 from fengyuentau:4x/core/copyMask-simd
core: further vectorize copyTo with mask #27145 Merge with https://github.com/opencv/opencv_extra/pull/1247. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake |
||
|
|
98cbe0ac49 |
Merge pull request #27068 from fengyuentau:5x-merge-4x/core/normDiff-simd
5.x merge 4.x: vectorized normDiff #27068 Merge with https://github.com/opencv/opencv_extra/pull/1243 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake |
||
|
|
8207549638 |
Merge pull request #26991 from fengyuentau:4x/core/norm2hal_rvv
core: improve norm of hal rvv #26991 Merge with https://github.com/opencv/opencv_extra/pull/1241 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake |
||
|
|
2090407002 |
Merge pull request #26999 from GenshinImpactStarts:polar_to_cart
[HAL RVV] unify and impl polar_to_cart | add perf test #26999 ### Summary 1. Implement through the existing `cv_hal_polarToCart32f` and `cv_hal_polarToCart64f` interfaces. 2. Add `polarToCart` performance tests 3. Make `cv::polarToCart` use CALL_HAL in the same way as `cv::cartToPolar` 4. To achieve the 3rd point, the original implementation was moved, and some modifications were made. Tested through: ```sh opencv_test_core --gtest_filter="*PolarToCart*:*Core_CartPolar_reverse*" opencv_perf_core --gtest_filter="*PolarToCart*" --perf_min_samples=300 --perf_force_samples=300 ``` ### HAL performance test ***UPDATE***: Current implementation is no more depending on vlen. **NOTE**: Due to the 4th point in the summary above, the `scalar` and `ui` test is based on the modified code of this PR. The impact of this patch on `scalar` and `ui` is evaluated in the next section, `Effect of Point 4`. Vlen 256 (Muse Pi): ``` Name of Test scalar ui rvv ui rvv vs vs scalar scalar (x-factor) (x-factor) PolarToCart::PolarToCartFixture::(127x61, 32FC1) 0.315 0.110 0.034 2.85 9.34 PolarToCart::PolarToCartFixture::(127x61, 64FC1) 0.423 0.163 0.045 2.59 9.34 PolarToCart::PolarToCartFixture::(640x480, 32FC1) 13.695 4.325 1.278 3.17 10.71 PolarToCart::PolarToCartFixture::(640x480, 64FC1) 17.719 7.118 2.105 2.49 8.42 PolarToCart::PolarToCartFixture::(1280x720, 32FC1) 40.678 13.114 3.977 3.10 10.23 PolarToCart::PolarToCartFixture::(1280x720, 64FC1) 53.124 21.298 6.519 2.49 8.15 PolarToCart::PolarToCartFixture::(1920x1080, 32FC1) 95.158 29.465 8.894 3.23 10.70 PolarToCart::PolarToCartFixture::(1920x1080, 64FC1) 119.262 47.743 14.129 2.50 8.44 ``` ### Effect of Point 4 To make `cv::polarToCart` behave the same as `cv::cartToPolar`, the implementation detail of the former has been moved to the latter's location (from `mathfuncs.cpp` to `mathfuncs_core.simd.hpp`). #### Reason for Changes: This function works as follows: $y = \text{mag} \times \sin(\text{angle})$ and $x = \text{mag} \times \cos(\text{angle})$. The original implementation first calculates the values of $\sin$ and $\cos$, storing the results in the output buffers $x$ and $y$, and then multiplies the result by $\text{mag}$. However, when the function is used as an in-place operation (one of the output buffers is also an input buffer), the original implementation allocates an extra buffer to store the $\sin$ and $\cos$ values in case the $\text{mag}$ value gets overwritten. This extra buffer allocation prevents `cv::polarToCart` from functioning in the same way as `cv::cartToPolar`. Therefore, the multiplication is now performed immediately without storing intermediate values. Since the original implementation also had AVX2 optimizations, I have applied the same optimizations to the AVX2 version of this implementation. ***UPDATE***: UI use v_sincos from #25892 now. The original implementation has AVX2 optimizations but is slower much than current UI so it's removed, and AVX2 perf test is below. Scalar implementation isn't changed because it's faster than using UI's method. #### Test Result `scalar` and `ui` test is done on Muse PI, and AVX2 test is done on Intel(R) Xeon(R) Gold 6140 CPU @ 2.30GHz. `scalar` test: ``` Name of Test orig pr pr vs orig (x-factor) PolarToCart::PolarToCartFixture::(127x61, 32FC1) 0.333 0.294 1.13 PolarToCart::PolarToCartFixture::(127x61, 64FC1) 0.385 0.403 0.96 PolarToCart::PolarToCartFixture::(640x480, 32FC1) 14.749 12.343 1.19 PolarToCart::PolarToCartFixture::(640x480, 64FC1) 19.419 16.743 1.16 PolarToCart::PolarToCartFixture::(1280x720, 32FC1) 44.155 37.822 1.17 PolarToCart::PolarToCartFixture::(1280x720, 64FC1) 62.108 50.358 1.23 PolarToCart::PolarToCartFixture::(1920x1080, 32FC1) 99.011 85.769 1.15 PolarToCart::PolarToCartFixture::(1920x1080, 64FC1) 127.740 112.874 1.13 ``` `ui` test: ``` Name of Test orig pr pr vs orig (x-factor) PolarToCart::PolarToCartFixture::(127x61, 32FC1) 0.306 0.110 2.77 PolarToCart::PolarToCartFixture::(127x61, 64FC1) 0.455 0.163 2.79 PolarToCart::PolarToCartFixture::(640x480, 32FC1) 13.381 4.325 3.09 PolarToCart::PolarToCartFixture::(640x480, 64FC1) 21.851 7.118 3.07 PolarToCart::PolarToCartFixture::(1280x720, 32FC1) 39.975 13.114 3.05 PolarToCart::PolarToCartFixture::(1280x720, 64FC1) 67.006 21.298 3.15 PolarToCart::PolarToCartFixture::(1920x1080, 32FC1) 90.362 29.465 3.07 PolarToCart::PolarToCartFixture::(1920x1080, 64FC1) 129.637 47.743 2.72 ``` AVX2 test: ``` Name of Test orig pr pr vs orig (x-factor) PolarToCart::PolarToCartFixture::(127x61, 32FC1) 0.019 0.009 2.11 PolarToCart::PolarToCartFixture::(127x61, 64FC1) 0.022 0.013 1.74 PolarToCart::PolarToCartFixture::(640x480, 32FC1) 0.788 0.355 2.22 PolarToCart::PolarToCartFixture::(640x480, 64FC1) 1.102 0.618 1.78 PolarToCart::PolarToCartFixture::(1280x720, 32FC1) 2.383 1.042 2.29 PolarToCart::PolarToCartFixture::(1280x720, 64FC1) 3.758 2.316 1.62 PolarToCart::PolarToCartFixture::(1920x1080, 32FC1) 5.577 2.559 2.18 PolarToCart::PolarToCartFixture::(1920x1080, 64FC1) 9.710 6.424 1.51 ``` A slight performance loss occurs because the check for whether $mag$ is nullptr is performed with every calculation, instead of being done once per batch. This is to reuse current `SinCos_32f` function. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [ ] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake |
||
|
|
2a8d4b8e43 |
Merge pull request #27000 from GenshinImpactStarts:cart_to_polar
[HAL RVV] reuse atan | impl cart_to_polar | add perf test #27000 Implement through the existing `cv_hal_cartToPolar32f` and `cv_hal_cartToPolar64f` interfaces. Add `cartToPolar` performance tests. cv_hal_rvv::fast_atan is modified to make it more reusable because it's needed in cartToPolar. **UPDATE**: UI enabled. Since the vec type of RVV can't be stored in struct. UI implementation of `v_atan_f32` is modified. Both `fastAtan` and `cartToPolar` are affected so the test result for `atan` is also appended. I have tested the modified UI on RVV and AVX2 and no regressions appears. Perf test done on MUSE-PI. AVX2 test done on Intel(R) Xeon(R) Gold 6140 CPU @ 2.30GHz. ```sh $ opencv_test_core --gtest_filter="*CartToPolar*:*Core_CartPolar_reverse*:*Phase*" $ opencv_perf_core --gtest_filter="*CartToPolar*:*phase*" --perf_min_samples=300 --perf_force_samples=300 ``` Test result between enabled UI and HAL: ``` Name of Test ui rvv rvv vs ui (x-factor) CartToPolar::CartToPolarFixture::(127x61, 32FC1) 0.106 0.059 1.80 CartToPolar::CartToPolarFixture::(127x61, 64FC1) 0.155 0.070 2.20 CartToPolar::CartToPolarFixture::(640x480, 32FC1) 4.188 2.317 1.81 CartToPolar::CartToPolarFixture::(640x480, 64FC1) 6.593 2.889 2.28 CartToPolar::CartToPolarFixture::(1280x720, 32FC1) 12.600 7.057 1.79 CartToPolar::CartToPolarFixture::(1280x720, 64FC1) 19.860 8.797 2.26 CartToPolar::CartToPolarFixture::(1920x1080, 32FC1) 28.295 15.809 1.79 CartToPolar::CartToPolarFixture::(1920x1080, 64FC1) 44.573 19.398 2.30 phase32f::VectorLength::128 0.002 0.002 1.20 phase32f::VectorLength::1000 0.008 0.006 1.32 phase32f::VectorLength::131072 1.061 0.731 1.45 phase32f::VectorLength::524288 3.997 2.976 1.34 phase32f::VectorLength::1048576 8.001 5.959 1.34 phase64f::VectorLength::128 0.002 0.002 1.33 phase64f::VectorLength::1000 0.012 0.008 1.58 phase64f::VectorLength::131072 1.648 0.931 1.77 phase64f::VectorLength::524288 6.836 3.837 1.78 phase64f::VectorLength::1048576 14.060 7.540 1.86 ``` Test result before and after enabling UI on RVV: ``` Name of Test perf perf perf ui ui ui orig pr pr vs perf ui orig (x-factor) CartToPolar::CartToPolarFixture::(127x61, 32FC1) 0.141 0.106 1.33 CartToPolar::CartToPolarFixture::(127x61, 64FC1) 0.187 0.155 1.20 CartToPolar::CartToPolarFixture::(640x480, 32FC1) 5.990 4.188 1.43 CartToPolar::CartToPolarFixture::(640x480, 64FC1) 8.370 6.593 1.27 CartToPolar::CartToPolarFixture::(1280x720, 32FC1) 18.214 12.600 1.45 CartToPolar::CartToPolarFixture::(1280x720, 64FC1) 25.365 19.860 1.28 CartToPolar::CartToPolarFixture::(1920x1080, 32FC1) 40.437 28.295 1.43 CartToPolar::CartToPolarFixture::(1920x1080, 64FC1) 56.699 44.573 1.27 phase32f::VectorLength::128 0.003 0.002 1.54 phase32f::VectorLength::1000 0.016 0.008 1.90 phase32f::VectorLength::131072 2.048 1.061 1.93 phase32f::VectorLength::524288 8.219 3.997 2.06 phase32f::VectorLength::1048576 16.426 8.001 2.05 phase64f::VectorLength::128 0.003 0.002 1.44 phase64f::VectorLength::1000 0.020 0.012 1.60 phase64f::VectorLength::131072 2.621 1.648 1.59 phase64f::VectorLength::524288 10.780 6.836 1.58 phase64f::VectorLength::1048576 22.723 14.060 1.62 ``` Test result before and after modifying UI on AVX2: ``` Name of Test perf perf perf avx2 avx2 avx2 orig pr pr vs perf avx2 orig (x-factor) CartToPolar::CartToPolarFixture::(127x61, 32FC1) 0.006 0.005 1.14 CartToPolar::CartToPolarFixture::(127x61, 64FC1) 0.010 0.009 1.08 CartToPolar::CartToPolarFixture::(640x480, 32FC1) 0.273 0.264 1.03 CartToPolar::CartToPolarFixture::(640x480, 64FC1) 0.511 0.487 1.05 CartToPolar::CartToPolarFixture::(1280x720, 32FC1) 0.760 0.723 1.05 CartToPolar::CartToPolarFixture::(1280x720, 64FC1) 2.009 1.937 1.04 CartToPolar::CartToPolarFixture::(1920x1080, 32FC1) 1.996 1.923 1.04 CartToPolar::CartToPolarFixture::(1920x1080, 64FC1) 5.721 5.509 1.04 phase32f::VectorLength::128 0.000 0.000 0.98 phase32f::VectorLength::1000 0.001 0.001 0.97 phase32f::VectorLength::131072 0.105 0.111 0.95 phase32f::VectorLength::524288 0.402 0.402 1.00 phase32f::VectorLength::1048576 0.775 0.767 1.01 phase64f::VectorLength::128 0.000 0.000 1.00 phase64f::VectorLength::1000 0.001 0.001 1.01 phase64f::VectorLength::131072 0.163 0.162 1.01 phase64f::VectorLength::524288 0.669 0.653 1.02 phase64f::VectorLength::1048576 1.660 1.634 1.02 ``` ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [ ] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake |
||
|
|
e30697fd42 |
Merge pull request #27002 from GenshinImpactStarts:magnitude
[HAL RVV] impl magnitude | add perf test #27002 Implement through the existing `cv_hal_magnitude32f` and `cv_hal_magnitude64f` interfaces. **UPDATE**: UI is enabled. The only difference between UI and HAL now is HAL use a approximate `sqrt`. Perf test done on MUSE-PI. ```sh $ opencv_test_core --gtest_filter="*Magnitude*" $ opencv_perf_core --gtest_filter="*Magnitude*" --perf_min_samples=300 --perf_force_samples=300 ``` Test result between enabled UI and HAL: ``` Name of Test ui rvv rvv vs ui (x-factor) Magnitude::MagnitudeFixture::(127x61, 32FC1) 0.029 0.016 1.75 Magnitude::MagnitudeFixture::(127x61, 64FC1) 0.057 0.036 1.57 Magnitude::MagnitudeFixture::(640x480, 32FC1) 1.063 0.648 1.64 Magnitude::MagnitudeFixture::(640x480, 64FC1) 2.261 1.530 1.48 Magnitude::MagnitudeFixture::(1280x720, 32FC1) 3.261 2.118 1.54 Magnitude::MagnitudeFixture::(1280x720, 64FC1) 6.802 4.682 1.45 Magnitude::MagnitudeFixture::(1920x1080, 32FC1) 7.287 4.738 1.54 Magnitude::MagnitudeFixture::(1920x1080, 64FC1) 15.226 10.334 1.47 ``` Test result before and after enabling UI: ``` Name of Test orig pr pr vs orig (x-factor) Magnitude::MagnitudeFixture::(127x61, 32FC1) 0.032 0.029 1.11 Magnitude::MagnitudeFixture::(127x61, 64FC1) 0.067 0.057 1.17 Magnitude::MagnitudeFixture::(640x480, 32FC1) 1.228 1.063 1.16 Magnitude::MagnitudeFixture::(640x480, 64FC1) 2.786 2.261 1.23 Magnitude::MagnitudeFixture::(1280x720, 32FC1) 3.762 3.261 1.15 Magnitude::MagnitudeFixture::(1280x720, 64FC1) 8.549 6.802 1.26 Magnitude::MagnitudeFixture::(1920x1080, 32FC1) 8.408 7.287 1.15 Magnitude::MagnitudeFixture::(1920x1080, 64FC1) 18.884 15.226 1.24 ``` ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [ ] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake |
||
|
|
eefa327f30 |
Merge pull request #27042 from fengyuentau:4x/core/normDiff_simd
core: vectorize normDiff with universal intrinsics #27042 Merge with https://github.com/opencv/opencv_extra/pull/1242. Performance results on Desktop Intel i7-12700K, Apple M2, Jetson Orin and SpaceMIT K1: [perf-normDiff.zip](https://github.com/user-attachments/files/19178689/perf-normDiff.zip) ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake |
||
|
|
4919cda8b2 | Merge branch 4.x | ||
|
|
524d8ae01c |
impl exp and log | add log perf test
Co-authored-by: Liutong HAN <liutong2020@iscas.ac.cn> |
||
|
|
57a78cb9df |
Merge pull request #26941 from GenshinImpactStarts:lut_hal_rvv
Impl hal_rvv LUT | Add more LUT test #26941 Implement through the existing `cv_hal_lut` interfaces. Add more LUT accuracy and performance tests: - **Accuracy test**: Multi-channel table tests are added, and the boundary of `randu` used for generating test data is broadened to make the test more robust. - **Performance test**: Multi-channel input and multi-channel table tests are added. Perf test done on - MUSE-PI (vlen=256) - Compiler: gcc 14.2 (riscv-collab/riscv-gnu-toolchain Nightly: December 16, 2024) ```sh $ opencv_test_core --gtest_filter="Core_LUT*" $ opencv_perf_core --gtest_filter="SizePrm_LUT*" --perf_min_samples=300 --perf_force_samples=300 ``` ```sh Geometric mean (ms) Name of Test scalar ui rvv ui rvv vs vs scalar scalar (x-factor) (x-factor) LUT::SizePrm::320x240 0.248 0.249 0.052 1.00 4.74 LUT::SizePrm::640x480 0.277 0.275 0.085 1.01 3.28 LUT::SizePrm::1920x1080 0.950 0.947 0.634 1.00 1.50 LUT_multi2::SizePrm::320x240 2.051 2.045 2.049 1.00 1.00 LUT_multi2::SizePrm::640x480 2.128 2.134 2.125 1.00 1.00 LUT_multi2::SizePrm::1920x1080 7.397 7.380 7.390 1.00 1.00 LUT_multi::SizePrm::320x240 0.715 0.747 0.154 0.96 4.64 LUT_multi::SizePrm::640x480 0.741 0.766 0.257 0.97 2.88 LUT_multi::SizePrm::1920x1080 2.766 2.765 1.925 1.00 1.44 ``` This optimization is achieved by loading the entire lookup table into vector registers. Due to register size limitations, the optimization is only effective under the following conditions: - For the U8C1 table type, the optimization works when `vlen >= 256` - For U16C1, it works when `vlen >= 512` - For U32C1, it works when `vlen >= 1024` Since I don’t have real hardware with `vlen > 256`, the corresponding accuracy tests were conducted on QEMU built from the `riscv-collab/riscv-gnu-toolchain`. This patch does not implement optimizations for multi-channel tables. Previous attempts: 1. For the U8C1 table type, when `vlen = 128`, it is possible to use four `u8m4` vectors to load the entire table, perform gathering, and merge the results. However, the performance is almost the same as the scalar version. 2. Loading part of the table and repeatedly loading the source data is faster for small sizes. But as the table size grows, the performance quickly degrades compared to the scalar version. 3. Using `vluxei8` as a general solution does not show any performance improvement. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [ ] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake |
||
|
|
db40139f16 | Merge branch 4.x | ||
|
|
6a6a5a765d |
Merge pull request #26943 from GenshinImpactStarts:flip_hal_rvv
Impl RISC-V HAL for cv::flip | Add perf test for flip #26943 Implement through the existing `cv_hal_flip` interfaces. Add perf test for `cv::flip`. The reason why select these args for testing: - **size**: copied from perf_lut - **type**: - U8C1: basic situation - U8C3: unaligned element size - U8C4: large element size Tested on - MUSE-PI (vlen=256) - Compiler: gcc 14.2 (riscv-collab/riscv-gnu-toolchain Nightly: December 16, 2024) ```sh $ opencv_test_core --gtest_filter="Core_Flip/ElemWiseTest.*" $ opencv_perf_core --gtest_filter="Size_MatType_FlipCode*" --perf_min_samples=300 --perf_force_samples=300 ``` ``` Geometric mean (ms) Name of Test scalar ui rvv ui rvv vs vs scalar scalar (x-factor) (x-factor) flip::Size_MatType_FlipCode::(320x240, 8UC1, FLIP_X) 0.026 0.033 0.031 0.81 0.84 flip::Size_MatType_FlipCode::(320x240, 8UC1, FLIP_XY) 0.206 0.212 0.091 0.97 2.26 flip::Size_MatType_FlipCode::(320x240, 8UC1, FLIP_Y) 0.185 0.189 0.082 0.98 2.25 flip::Size_MatType_FlipCode::(320x240, 8UC3, FLIP_X) 0.070 0.084 0.084 0.83 0.83 flip::Size_MatType_FlipCode::(320x240, 8UC3, FLIP_XY) 0.616 0.612 0.235 1.01 2.62 flip::Size_MatType_FlipCode::(320x240, 8UC3, FLIP_Y) 0.587 0.603 0.204 0.97 2.88 flip::Size_MatType_FlipCode::(320x240, 8UC4, FLIP_X) 0.263 0.110 0.109 2.40 2.41 flip::Size_MatType_FlipCode::(320x240, 8UC4, FLIP_XY) 0.930 0.831 0.316 1.12 2.95 flip::Size_MatType_FlipCode::(320x240, 8UC4, FLIP_Y) 1.175 1.129 0.313 1.04 3.75 flip::Size_MatType_FlipCode::(640x480, 8UC1, FLIP_X) 0.303 0.118 0.111 2.57 2.73 flip::Size_MatType_FlipCode::(640x480, 8UC1, FLIP_XY) 0.949 0.836 0.405 1.14 2.34 flip::Size_MatType_FlipCode::(640x480, 8UC1, FLIP_Y) 0.784 0.783 0.409 1.00 1.92 flip::Size_MatType_FlipCode::(640x480, 8UC3, FLIP_X) 1.084 0.360 0.355 3.01 3.06 flip::Size_MatType_FlipCode::(640x480, 8UC3, FLIP_XY) 3.768 3.348 1.364 1.13 2.76 flip::Size_MatType_FlipCode::(640x480, 8UC3, FLIP_Y) 4.361 4.473 1.296 0.97 3.37 flip::Size_MatType_FlipCode::(640x480, 8UC4, FLIP_X) 1.252 0.469 0.451 2.67 2.78 flip::Size_MatType_FlipCode::(640x480, 8UC4, FLIP_XY) 5.732 5.220 1.303 1.10 4.40 flip::Size_MatType_FlipCode::(640x480, 8UC4, FLIP_Y) 5.041 5.105 1.203 0.99 4.19 flip::Size_MatType_FlipCode::(1920x1080, 8UC1, FLIP_X) 2.382 0.903 0.903 2.64 2.64 flip::Size_MatType_FlipCode::(1920x1080, 8UC1, FLIP_XY) 8.606 7.508 2.581 1.15 3.33 flip::Size_MatType_FlipCode::(1920x1080, 8UC1, FLIP_Y) 8.421 8.535 2.219 0.99 3.80 flip::Size_MatType_FlipCode::(1920x1080, 8UC3, FLIP_X) 6.312 2.416 2.429 2.61 2.60 flip::Size_MatType_FlipCode::(1920x1080, 8UC3, FLIP_XY) 29.174 26.055 12.761 1.12 2.29 flip::Size_MatType_FlipCode::(1920x1080, 8UC3, FLIP_Y) 25.373 25.500 13.382 1.00 1.90 flip::Size_MatType_FlipCode::(1920x1080, 8UC4, FLIP_X) 7.620 3.204 3.115 2.38 2.45 flip::Size_MatType_FlipCode::(1920x1080, 8UC4, FLIP_XY) 32.876 29.310 12.976 1.12 2.53 flip::Size_MatType_FlipCode::(1920x1080, 8UC4, FLIP_Y) 28.831 29.094 14.919 0.99 1.93 ``` The optimization for vlen <= 256 and > 256 are different, but I have no real hardware with vlen > 256. So accuracy tests for that like 512 and 1024 are conducted on QEMU built from the `riscv-collab/riscv-gnu-toolchain`. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [ ] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake |
||
|
|
b5f5540e8a |
Merge pull request #26886 from sk1er52:feature/exp64f
Enable SIMD_SCALABLE for exp and sqrt #26886 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake ``` CPU - Banana Pi k1, compiler - clang 18.1.4 ``` ``` Geometric mean (ms) Name of Test baseline hal ui hal ui vs vs baseline baseline (x-factor) (x-factor) Exp::ExpFixture::(127x61, 32FC1) 0.358 -- 0.033 -- 10.70 Exp::ExpFixture::(640x480, 32FC1) 14.304 -- 1.167 -- 12.26 Exp::ExpFixture::(1280x720, 32FC1) 42.785 -- 3.538 -- 12.09 Exp::ExpFixture::(1920x1080, 32FC1) 96.206 -- 7.927 -- 12.14 Exp::ExpFixture::(127x61, 64FC1) 0.433 0.050 0.098 8.59 4.40 Exp::ExpFixture::(640x480, 64FC1) 17.315 1.935 3.813 8.95 4.54 Exp::ExpFixture::(1280x720, 64FC1) 52.181 5.877 11.519 8.88 4.53 Exp::ExpFixture::(1920x1080, 64FC1) 117.082 13.157 25.854 8.90 4.53 ``` Additionally, this PR brings Sqrt optimization with UI: ``` Geometric mean (ms) Name of Test baseline ui ui vs baseline (x-factor) Sqrt::SqrtFixture::(127x61, 5, false) 0.111 0.027 4.11 Sqrt::SqrtFixture::(127x61, 6, false) 0.149 0.053 2.82 Sqrt::SqrtFixture::(640x480, 5, false) 4.374 0.967 4.52 Sqrt::SqrtFixture::(640x480, 6, false) 5.885 2.046 2.88 Sqrt::SqrtFixture::(1280x720, 5, false) 12.960 2.915 4.45 Sqrt::SqrtFixture::(1280x720, 6, false) 17.648 6.107 2.89 Sqrt::SqrtFixture::(1920x1080, 5, false) 29.178 6.524 4.47 Sqrt::SqrtFixture::(1920x1080, 6, false) 39.709 13.670 2.90 ``` Reference Muller, J.-M. Elementary Functions: Algorithms and Implementation. 2nd ed. Boston: Birkhäuser, 2006. https://www.springer.com/gp/book/9780817643720 |
||
|
|
d32d4da9a3 |
Merge pull request #26887 from kyler1cartesis:4.x
invSqrt SIMD_SCALABLE implementation & HAL tests refactoring #26887 Enable CV_SIMD_SCALABLE for invSqrt. * Banana Pi BF3 (SpacemiT K1) RISC-V * Compiler: Syntacore Clang 18.1.4 (build 2024.12) ``` Geometric mean (ms) Name of Test baseline simd simd scalable scalable vs baseline (x-factor) InvSqrtf::InvSqrtfFixture::(127x61, 32FC1) 0.163 0.051 3.23 InvSqrtf::InvSqrtfFixture::(127x61, 64FC1) 0.241 0.103 2.35 InvSqrtf::InvSqrtfFixture::(640x480, 32FC1) 6.460 1.893 3.41 InvSqrtf::InvSqrtfFixture::(640x480, 64FC1) 9.687 3.999 2.42 InvSqrtf::InvSqrtfFixture::(1280x720, 32FC1) 19.292 5.701 3.38 InvSqrtf::InvSqrtfFixture::(1280x720, 64FC1) 29.452 11.963 2.46 InvSqrtf::InvSqrtfFixture::(1920x1080, 32FC1) 43.326 12.805 3.38 InvSqrtf::InvSqrtfFixture::(1920x1080, 64FC1) 65.566 26.881 2.44 ``` |
||
|
|
603b1cafdf |
Merge pull request #26821 from fengyuentau:core/transform_simd
Core: vectorize cv::transform in terms of all data types #26821 ## Performance ### i7-12700K ``` Geometric mean (ms) Name of Test base patch patch vs base (x-factor) Mat_Transform::Size_MatType::(127x61, 8SC3) 0.017 0.004 4.64 Mat_Transform::Size_MatType::(127x61, 16SC3) 0.015 0.004 3.78 Mat_Transform::Size_MatType::(127x61, 32SC3) 0.015 0.007 2.03 Mat_Transform::Size_MatType::(127x61, 64FC3) 0.007 0.004 1.78 Mat_Transform::Size_MatType::(640x480, 8SC3) 0.673 0.140 4.80 Mat_Transform::Size_MatType::(640x480, 16SC3) 0.618 0.158 3.90 Mat_Transform::Size_MatType::(640x480, 32SC3) 0.579 0.278 2.08 Mat_Transform::Size_MatType::(640x480, 64FC3) 0.290 0.266 1.09 Mat_Transform::Size_MatType::(1280x720, 8SC3) 1.919 0.414 4.63 Mat_Transform::Size_MatType::(1280x720, 16SC3) 1.811 0.488 3.71 Mat_Transform::Size_MatType::(1280x720, 32SC3) 1.736 0.917 1.89 Mat_Transform::Size_MatType::(1280x720, 64FC3) 2.310 2.030 1.14 Mat_Transform::Size_MatType::(1920x1080, 8SC3) 4.339 0.924 4.70 Mat_Transform::Size_MatType::(1920x1080, 16SC3) 4.095 1.288 3.18 Mat_Transform::Size_MatType::(1920x1080, 32SC3) 4.267 3.191 1.34 Mat_Transform::Size_MatType::(1920x1080, 64FC3) 6.641 5.481 1.21 Mat_Transform_Diagonal::Size_MatType::(640x480, 8SC3) 0.415 0.104 3.98 Mat_Transform_Diagonal::Size_MatType::(640x480, 16SC3) 0.385 0.128 3.00 Mat_Transform_Diagonal::Size_MatType::(640x480, 32SC3) 0.389 0.225 1.72 Mat_Transform_Diagonal::Size_MatType::(640x480, 64FC3) 0.279 0.275 1.01 Mat_Transform_Diagonal::Size_MatType::(1280x720, 8SC3) 1.223 0.313 3.91 Mat_Transform_Diagonal::Size_MatType::(1280x720, 16SC3) 1.118 0.387 2.89 Mat_Transform_Diagonal::Size_MatType::(1280x720, 32SC3) 1.215 0.801 1.52 Mat_Transform_Diagonal::Size_MatType::(1280x720, 64FC3) 2.198 1.900 1.16 Mat_Transform_Diagonal::Size_MatType::(1920x1080, 8SC3) 2.772 0.705 3.93 Mat_Transform_Diagonal::Size_MatType::(1920x1080, 16SC3) 2.572 1.134 2.27 Mat_Transform_Diagonal::Size_MatType::(1920x1080, 32SC3) 3.477 3.276 1.06 Mat_Transform_Diagonal::Size_MatType::(1920x1080, 64FC3) 5.984 5.186 1.15 ``` ### A311D ``` Geometric mean (ms) Name of Test base patch patch vs base (x-factor) Mat_Transform::Size_MatType::(127x61, 8SC3) 0.143 0.035 4.05 Mat_Transform::Size_MatType::(127x61, 16SC3) 0.135 0.037 3.67 Mat_Transform::Size_MatType::(127x61, 32SC3) 0.110 0.062 1.77 Mat_Transform::Size_MatType::(127x61, 64FC3) 0.034 0.039 0.89 Mat_Transform::Size_MatType::(640x480, 8SC3) 5.673 1.395 4.07 Mat_Transform::Size_MatType::(640x480, 16SC3) 5.331 1.439 3.70 Mat_Transform::Size_MatType::(640x480, 32SC3) 4.329 2.472 1.75 Mat_Transform::Size_MatType::(640x480, 64FC3) 1.560 2.316 0.67 Mat_Transform::Size_MatType::(1280x720, 8SC3) 17.002 4.139 4.11 Mat_Transform::Size_MatType::(1280x720, 16SC3) 15.996 4.308 3.71 Mat_Transform::Size_MatType::(1280x720, 32SC3) 12.948 7.241 1.79 Mat_Transform::Size_MatType::(1280x720, 64FC3) 4.742 7.376 0.64 Mat_Transform::Size_MatType::(1920x1080, 8SC3) 38.253 9.384 4.08 Mat_Transform::Size_MatType::(1920x1080, 16SC3) 35.913 9.750 3.68 Mat_Transform::Size_MatType::(1920x1080, 32SC3) 29.145 16.528 1.76 Mat_Transform::Size_MatType::(1920x1080, 64FC3) 10.606 20.968 0.51 Mat_Transform_Diagonal::Size_MatType::(640x480, 8SC3) 4.439 1.086 4.09 Mat_Transform_Diagonal::Size_MatType::(640x480, 16SC3) 4.251 1.136 3.74 Mat_Transform_Diagonal::Size_MatType::(640x480, 32SC3) 3.786 1.999 1.89 Mat_Transform_Diagonal::Size_MatType::(640x480, 64FC3) 1.555 1.551 1.00 Mat_Transform_Diagonal::Size_MatType::(1280x720, 8SC3) 13.319 3.243 4.11 Mat_Transform_Diagonal::Size_MatType::(1280x720, 16SC3) 12.828 3.398 3.78 Mat_Transform_Diagonal::Size_MatType::(1280x720, 32SC3) 11.336 5.989 1.89 Mat_Transform_Diagonal::Size_MatType::(1280x720, 64FC3) 4.707 4.690 1.00 Mat_Transform_Diagonal::Size_MatType::(1920x1080, 8SC3) 29.952 7.293 4.11 Mat_Transform_Diagonal::Size_MatType::(1920x1080, 16SC3) 28.817 7.656 3.76 Mat_Transform_Diagonal::Size_MatType::(1920x1080, 32SC3) 25.476 13.388 1.90 Mat_Transform_Diagonal::Size_MatType::(1920x1080, 64FC3) 10.533 10.509 1.00 ``` ### M2 ``` Geometric mean (ms) Name of Test base patch patch vs base (x-factor) Mat_Transform::Size_MatType::(127x61, 8SC3) 0.020 0.004 4.45 Mat_Transform::Size_MatType::(127x61, 16SC3) 0.016 0.004 4.48 Mat_Transform::Size_MatType::(127x61, 32SC3) 0.016 0.007 2.23 Mat_Transform::Size_MatType::(127x61, 64FC3) 0.007 0.006 1.20 Mat_Transform::Size_MatType::(640x480, 8SC3) 0.793 0.197 4.03 Mat_Transform::Size_MatType::(640x480, 16SC3) 0.626 0.154 4.08 Mat_Transform::Size_MatType::(640x480, 32SC3) 0.627 0.306 2.05 Mat_Transform::Size_MatType::(640x480, 64FC3) 0.273 0.253 1.08 Mat_Transform::Size_MatType::(1280x720, 8SC3) 2.350 0.540 4.35 Mat_Transform::Size_MatType::(1280x720, 16SC3) 1.875 0.415 4.52 Mat_Transform::Size_MatType::(1280x720, 32SC3) 1.893 0.844 2.24 Mat_Transform::Size_MatType::(1280x720, 64FC3) 0.830 0.808 1.03 Mat_Transform::Size_MatType::(1920x1080, 8SC3) 5.302 1.178 4.50 Mat_Transform::Size_MatType::(1920x1080, 16SC3) 4.475 0.946 4.73 Mat_Transform::Size_MatType::(1920x1080, 32SC3) 4.409 1.864 2.37 Mat_Transform::Size_MatType::(1920x1080, 64FC3) 1.853 1.512 1.23 Mat_Transform_Diagonal::Size_MatType::(640x480, 8SC3) 0.586 0.110 5.32 Mat_Transform_Diagonal::Size_MatType::(640x480, 16SC3) 0.518 0.110 4.69 Mat_Transform_Diagonal::Size_MatType::(640x480, 32SC3) 0.430 0.220 1.95 Mat_Transform_Diagonal::Size_MatType::(640x480, 64FC3) 0.228 0.178 1.28 Mat_Transform_Diagonal::Size_MatType::(1280x720, 8SC3) 1.768 0.336 5.26 Mat_Transform_Diagonal::Size_MatType::(1280x720, 16SC3) 1.514 0.335 4.52 Mat_Transform_Diagonal::Size_MatType::(1280x720, 32SC3) 1.292 0.670 1.93 Mat_Transform_Diagonal::Size_MatType::(1280x720, 64FC3) 0.681 0.579 1.18 Mat_Transform_Diagonal::Size_MatType::(1920x1080, 8SC3) 3.998 0.747 5.35 Mat_Transform_Diagonal::Size_MatType::(1920x1080, 16SC3) 3.392 0.757 4.48 Mat_Transform_Diagonal::Size_MatType::(1920x1080, 32SC3) 2.956 1.491 1.98 Mat_Transform_Diagonal::Size_MatType::(1920x1080, 64FC3) 1.546 1.476 1.05 ``` ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake |
||
|
|
bfb54aa691 | Remove useless C headers | ||
|
|
0213483c18 | Merge branch 4.x | ||
|
|
bf914a7681 | 8uc2 added | ||
|
|
2d9c0c8592 | C-API cleanup: core module tests | ||
|
|
9f0c3f5b2b |
Merge pull request #26327 from asmorkalov:as/drop_convertFp16
Finally dropped convertFp16 function in favor of cv::Mat::convertTo() #26327 Partially address https://github.com/opencv/opencv/issues/24909 Related PR to contrib: https://github.com/opencv/opencv_contrib/pull/3812 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake |
||
|
|
b574db2cff | Merge branch 4.x | ||
|
|
7590813b69 |
Merge pull request #26115 from savuor:rv/flip_ocl_dtypes
Added more data types to OCL flip() and rotate() perf tests #26115 Connected PR with updated sanity data: https://github.com/opencv/opencv_extra/pull/1206 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake |
||
|
|
100db1bc0b | Merge branch 4.x | ||
|
|
f4c2e4f872 |
Merge pull request #26061 from penghuiho:fix-pow-bug
Fixed the simd bugs of iPow8u and iPow16u #26061 Add the following cases in opencv_perf_core: * OCL_PowFixture_iPow.iPow/0, where GetParam() = (640x480, 8UC1) * OCL_PowFixture_iPow.iPow/2, where GetParam() = (640x480, 16UC1) iPow8u and iPow16u failed to call to simd accelerating while executing. Fix the bug by changing the input type of iPow_SIMD function. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [ ] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake |
||
|
|
26ea34c4cb | Merge branch '4.x' into '5.x' | ||
|
|
a7e53aa184 |
Merge pull request #25671 from savuor:rv/arithm_extend_tests
Tests added for mixed type arithmetic operations #25671 ### Changes * added accuracy tests for mixed type arithmetic operations _Note: div-by-zero values are removed from checking since the result is implementation-defined in common case_ * added perf tests for the same cases * fixed a typo in `getMulExtTab()` function that lead to dead code ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake |
||
|
|
b267f1791c |
Merge pull request #25633 from savuor:rv/rotate_tests
Tests for cv::rotate() added #25633 fixes #25449 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake |
||
|
|
357b9abaef |
Merge pull request #25450 from savuor:rv/svd_perf
Perf tests for SVD and solve() created #25450 fixes #25336 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake |
||
|
|
8cbdd0c833 |
Merge pull request #25075 from mshabunin:cleanup-imgproc-1
C-API cleanup: apps, imgproc_c and some constants #25075 Merge with https://github.com/opencv/opencv_contrib/pull/3642 * Removed obsolete apps - traincascade and createsamples (please use older OpenCV versions if you need them). These apps relied heavily on C-API * removed all mentions of imgproc C-API headers (imgproc_c.h, types_c.h) - they were empty, included core C-API headers * replaced usage of several C constants with C++ ones (error codes, norm modes, RNG modes, PCA modes, ...) - most part of this PR (split into two parts - all modules and calib+3d - for easier backporting) * removed imgproc C-API headers (as separate commit, so that other changes could be backported to 4.x) Most of these changes can be backported to 4.x. |
||
|
|
3a55f50133 | Merge branch 4.x | ||
|
|
40533dbf69 |
Merge pull request #24918 from opencv-pushbot:gitee/alalek/core_convertfp16_replacement
core(OpenCL): optimize convertTo() with CV_16F (convertFp16() replacement) #24918 relates #24909 relates #24917 relates #24892 Performance changes: - [x] 12700K (1 thread) + Intel iGPU |Name of Test|noOCL|convertFp16|convertTo BASE|convertTo PATCH| |---|:-:|:-:|:-:|:-:| |ConvertFP16FP32MatMat::OCL_Core|3.130|3.152|3.127|3.136| |ConvertFP16FP32MatUMat::OCL_Core|3.030|3.996|3.007|2.671| |ConvertFP16FP32UMatMat::OCL_Core|3.010|3.101|3.056|2.854| |ConvertFP16FP32UMatUMat::OCL_Core|3.016|3.298|2.072|2.061| |ConvertFP32FP16MatMat::OCL_Core|2.697|2.652|2.723|2.721| |ConvertFP32FP16MatUMat::OCL_Core|2.752|4.268|2.662|2.947| |ConvertFP32FP16UMatMat::OCL_Core|2.706|2.601|2.603|2.528| |ConvertFP32FP16UMatUMat::OCL_Core|2.704|3.215|1.999|1.988| Patched version is not worse than convertFp16 and convertTo baseline (except MatUMat 32->16, baseline uses CPU code+dst buffer map). There are still gaps against noOpenCL(CPU only) mode due to T-API implementation issues (unnecessary synchronization). - [x] 12700K + AMD dGPU |Name of Test|noOCL|convertFp16 dGPU|convertTo BASE dGPU|convertTo PATCH dGPU| |---|:-:|:-:|:-:|:-:| |ConvertFP16FP32MatMat::OCL_Core|3.130|3.133|3.172|3.087| |ConvertFP16FP32MatUMat::OCL_Core|3.030|1.713|9.559|1.729| |ConvertFP16FP32UMatMat::OCL_Core|3.010|6.515|6.309|4.452| |ConvertFP16FP32UMatUMat::OCL_Core|3.016|0.242|23.597|0.170| |ConvertFP32FP16MatMat::OCL_Core|2.697|2.641|2.713|2.689| |ConvertFP32FP16MatUMat::OCL_Core|2.752|4.076|6.483|4.191| |ConvertFP32FP16UMatMat::OCL_Core|2.706|9.042|16.481|1.834| |ConvertFP32FP16UMatUMat::OCL_Core|2.704|0.229|15.730|0.176| convertTo-baseline can't compile OpenCL kernel for FP16 properly - FIXED. dGPU has much more power, so results are x16-17 better than single cpu core. Patched version is not worse than convertFp16 and convertTo baseline. There are still gaps against noOpenCL(CPU only) mode due to T-API implementation issues (unnecessary synchronization) and required memory transfers. Co-authored-by: Alexander Alekhin <alexander.a.alekhin@gmail.com> |
||
|
|
c739117a7c | Merge branch 4.x | ||
|
|
53aad98a1a |
Merge pull request #23098 from savuor:nanMask
finiteMask() and doubles for patchNaNs() #23098 Related to #22826 Connected PR in extra: [#1037@extra](https://github.com/opencv/opencv_extra/pull/1037) ### TODOs: - [ ] Vectorize `finiteMask()` for 64FC3 and 64FC4 ### Changes This PR: * adds a new function `finiteMask()` * extends `patchNaNs()` by CV_64F support * moves `patchNaNs()` and `finiteMask()` to a separate file **NOTE:** now the function is called `finiteMask()` as discussed with the OpenCV core team ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake |
||
|
|
ea47cb3ffe |
Merge pull request #24480 from savuor:backport_patch_nans
Backport to 4.x: patchNaNs() SIMD acceleration #24480 backport from #23098 connected PR in extra: [#1118@extra](https://github.com/opencv/opencv_extra/pull/1118) ### This PR contains: * new SIMD code for `patchNaNs()` * CPU perf test <details> <summary>Performance comparison</summary> Geometric mean (ms) |Name of Test|noopt|sse2|avx2|sse2 vs noopt (x-factor)|avx2 vs noopt (x-factor)| |---|:-:|:-:|:-:|:-:|:-:| |PatchNaNs::OCL_PatchNaNsFixture::(640x480, 32FC1)|0.019|0.017|0.018|1.11|1.07| |PatchNaNs::OCL_PatchNaNsFixture::(640x480, 32FC4)|0.037|0.037|0.033|1.00|1.10| |PatchNaNs::OCL_PatchNaNsFixture::(1280x720, 32FC1)|0.032|0.032|0.033|0.99|0.98| |PatchNaNs::OCL_PatchNaNsFixture::(1280x720, 32FC4)|0.072|0.072|0.070|1.00|1.03| |PatchNaNs::OCL_PatchNaNsFixture::(1920x1080, 32FC1)|0.051|0.051|0.050|1.00|1.01| |PatchNaNs::OCL_PatchNaNsFixture::(1920x1080, 32FC4)|0.137|0.138|0.128|0.99|1.06| |PatchNaNs::OCL_PatchNaNsFixture::(3840x2160, 32FC1)|0.137|0.128|0.129|1.07|1.06| |PatchNaNs::OCL_PatchNaNsFixture::(3840x2160, 32FC4)|0.450|0.450|0.448|1.00|1.01| |PatchNaNs::PatchNaNsFixture::(640x480, 32FC1)|0.149|0.029|0.020|5.13|7.44| |PatchNaNs::PatchNaNsFixture::(640x480, 32FC2)|0.304|0.058|0.040|5.25|7.65| |PatchNaNs::PatchNaNsFixture::(640x480, 32FC3)|0.448|0.086|0.059|5.22|7.55| |PatchNaNs::PatchNaNsFixture::(640x480, 32FC4)|0.601|0.133|0.083|4.51|7.23| |PatchNaNs::PatchNaNsFixture::(1280x720, 32FC1)|0.451|0.093|0.060|4.83|7.52| |PatchNaNs::PatchNaNsFixture::(1280x720, 32FC2)|0.892|0.184|0.126|4.85|7.06| |PatchNaNs::PatchNaNsFixture::(1280x720, 32FC3)|1.345|0.311|0.230|4.32|5.84| |PatchNaNs::PatchNaNsFixture::(1280x720, 32FC4)|1.831|0.546|0.436|3.35|4.20| |PatchNaNs::PatchNaNsFixture::(1920x1080, 32FC1)|1.017|0.250|0.160|4.06|6.35| |PatchNaNs::PatchNaNsFixture::(1920x1080, 32FC2)|2.077|0.646|0.605|3.21|3.43| |PatchNaNs::PatchNaNsFixture::(1920x1080, 32FC3)|3.134|1.053|0.961|2.97|3.26| |PatchNaNs::PatchNaNsFixture::(1920x1080, 32FC4)|4.222|1.436|1.288|2.94|3.28| |PatchNaNs::PatchNaNsFixture::(3840x2160, 32FC1)|4.225|1.401|1.277|3.01|3.31| |PatchNaNs::PatchNaNsFixture::(3840x2160, 32FC2)|8.310|2.953|2.635|2.81|3.15| |PatchNaNs::PatchNaNsFixture::(3840x2160, 32FC3)|12.396|4.455|4.252|2.78|2.92| |PatchNaNs::PatchNaNsFixture::(3840x2160, 32FC4)|17.174|5.831|5.824|2.95|2.95| </details> ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake |
||
|
|
5fb3869775 |
Merge pull request #23109 from seanm:misc-warnings
* Fixed clang -Wnewline-eof warnings * Fixed all trivial clang -Wextra-semi and -Wc++98-compat-extra-semi warnings * Removed trailing semi from various macros * Fixed various -Wunused-macros warnings * Fixed some trivial -Wdocumentation warnings * Fixed some -Wdocumentation-deprecated-sync warnings * Fixed incorrect indentation * Suppressed some clang warnings in 3rd party code * Fixed QRCodeEncoder::Params documentation. --------- Co-authored-by: Alexander Smorkalov <alexander.smorkalov@xperience.ai> |
||
|
|
a308dfca98 |
core: add broadcast (#23965)
* add broadcast_to with tests * change name * fix test * fix implicit type conversion * replace type of shape with InputArray * add perf test * add perf tests which takes care of axis * v2 from ficus expand * rename to broadcast * use randu in place of declare * doc improvement; smaller scale in perf * capture get_index by reference |
||
|
|
60b806f9b8 |
Merge pull request #22947 from chacha21:hasNonZero
Added cv::hasNonZero() #22947 `cv::hasNonZero()` is semantically equivalent to (`cv::countNonZero()>0`) but stops parsing the image when a non-zero value is found, for a performance gain - [X] I agree to contribute to the project under Apache 2 License. - [X] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [X] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake This pull request might be refused, but I submit it to know if further work is needed or if I just stop working on it. The idea is only a performance gain vs `countNonZero()>0` at the cost of more code. Reasons why it might be refused : - this is just more code - the execution time is "unfair"/"unpredictable" since it depends on the position of the first non-zero value - the user must be aware that default search is from first row/col to last row/col and has no way to customize that, even if his use case lets him know where a non zero could be found - the PR in its current state is using, for the ocl implementation, a mere `countNonZero()>0` ; there is not much sense in trying to break early the ocl kernel call when non-zero is encountered. So the ocl implementation does not bring any improvement. - there is no IPP function that can help (`countNonZero()` is based in `ippCountInRange`) - the PR in its current state might be slower than a call to `countNonZero()>0` in some cases (see "challenges" below) Reasons why it might be accepted : - the performance gain is huge on average, if we consider that "on average" means "non zero in the middle of the image" - the "missing" IPP implementation is replaced by an "Open-CV universal intrinsics" implementation - the PR in its current state is almost always faster than a call to `countNonZero()>0`, is only slightly slower in the worst cases, and not even for all matrices **Challenges** The worst case is either an all-zero matrix, or a non-zero at the very last position. In such a case, the `hasNonZero()` implementation will parse the whole matrix like `countNonZero()` would do. But we expect the performance to be the same in this case. And `ippCountInRange` is hard to beat ! There is also the case of very small matrices (<=32x32...) in 8b, where the SIMD can be hard to feed. For all cases but the worse, my custom `hasNonZero()` performs better than `ippCountInRange()` For the worst case, my custom `hasNonZero()` performs better than `ippCountInRange()` *except for large matrices of type CV_32S or CV_64F* (but surprisingly, not CV_32F). The difference is small, but it exists (and I don't understand why). For very small CV_8U matrices `ippCountInRange()` seems unbeatable. Here is the code that I use to check timings ``` //test cv::hasNonZero() vs (cv::countNonZero()>0) for different matrices sizes, types, strides... { cv::setRNGSeed(1234); const std::vector<cv::Size> sizes = {{32, 32}, {64, 64}, {128, 128}, {320, 240}, {512, 512}, {640, 480}, {1024, 768}, {2048, 2048}, {1031, 1000}}; const std::vector<int> types = {CV_8U, CV_16U, CV_32S, CV_32F, CV_64F}; const size_t iterations = 1000; for(const cv::Size& size : sizes) { for(const int type : types) { for(int c = 0 ; c<2 ; ++c) { const bool continuous = !c; for(int i = 0 ; i<4 ; ++i) { cv::Mat m = continuous ? cv::Mat::zeros(size, type) : cv::Mat(cv::Mat::zeros(cv::Size(2*size.width, size.height), type), cv::Rect(cv::Point(0, 0), size)); const bool nz = (i <= 2); const unsigned int nzOffsetRange = 10; const unsigned int nzOffset = cv::randu<unsigned int>()%nzOffsetRange; const cv::Point pos = (i == 0) ? cv::Point(nzOffset, 0) : (i == 1) ? cv::Point(size.width/2-nzOffsetRange/2+nzOffset, size.height/2) : (i == 2) ? cv::Point(size.width-1-nzOffset, size.height-1) : cv::Point(0, 0); std::cout << "============================================================" << std::endl; std::cout << "size:" << size << " type:" << type << " continuous = " << (continuous ? "true" : "false") << " iterations:" << iterations << " nz=" << (nz ? "true" : "false"); std::cout << " pos=" << ((i == 0) ? "begin" : (i == 1) ? "middle" : (i == 2) ? "end" : "none"); std::cout << std::endl; cv::Mat mask = cv::Mat::zeros(size, CV_8UC1); mask.at<unsigned char>(pos) = 0xFF; m.setTo(cv::Scalar::all(0)); m.setTo(cv::Scalar::all(nz ? 1 : 0), mask); std::vector<bool> results; std::vector<double> timings; { bool res = false; auto ref = cv::getTickCount(); for(size_t k = 0 ; k<iterations ; ++k) res = cv::hasNonZero(m); auto now = cv::getTickCount(); const bool error = (res != nz); if (error) printf("!!ERROR!!\r\n"); results.push_back(res); timings.push_back(1000.*(now-ref)/cv::getTickFrequency()); } { bool res = false; auto ref = cv::getTickCount(); for(size_t k = 0 ; k<iterations ; ++k) res = (cv::countNonZero(m)>0); auto now = cv::getTickCount(); const bool error = (res != nz); if (error) printf("!!ERROR!!\r\n"); results.push_back(res); timings.push_back(1000.*(now-ref)/cv::getTickFrequency()); } const size_t bestTimingIndex = (std::min_element(timings.begin(), timings.end())-timings.begin()); if ((bestTimingIndex != 0) || (std::find_if_not(results.begin(), results.end(), [&](bool r) {return (r == nz);}) != results.end())) { std::cout << "cv::hasNonZero\t\t=>" << results[0] << ((results[0] != nz) ? " ERROR" : "") << " perf:" << timings[0] << "ms => " << (iterations/timings[0]*1000) << " im/s" << ((bestTimingIndex == 0) ? " * " : "") << std::endl; std::cout << "cv::countNonZero\t=>" << results[1] << ((results[1] != nz) ? " ERROR" : "") << " perf:" << timings[1] << "ms => " << (iterations/timings[1]*1000) << " im/s" << ((bestTimingIndex == 1) ? " * " : "") << std::endl; } } } } } } ``` Here is a report of this benchmark (it only reports timings when `cv::countNonZero()` is faster) My CPU is an Intel Core I7 4790 @ 3.60Ghz ``` ============================================================ size:[32 x 32] type:0 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[32 x 32] type:0 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[32 x 32] type:0 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[32 x 32] type:0 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[32 x 32] type:0 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[32 x 32] type:0 continuous = false iterations:1000 nz=true pos=middle cv::hasNonZero =>1 perf:0.353764ms => 2.82674e+06 im/s cv::countNonZero =>1 perf:0.282044ms => 3.54555e+06 im/s * ============================================================ size:[32 x 32] type:0 continuous = false iterations:1000 nz=true pos=end cv::hasNonZero =>1 perf:0.610478ms => 1.63806e+06 im/s cv::countNonZero =>1 perf:0.283182ms => 3.5313e+06 im/s * ============================================================ size:[32 x 32] type:0 continuous = false iterations:1000 nz=false pos=none cv::hasNonZero =>0 perf:0.630115ms => 1.58701e+06 im/s cv::countNonZero =>0 perf:0.282044ms => 3.54555e+06 im/s * ============================================================ size:[32 x 32] type:2 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[32 x 32] type:2 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[32 x 32] type:2 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[32 x 32] type:2 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[32 x 32] type:2 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[32 x 32] type:2 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[32 x 32] type:2 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[32 x 32] type:2 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[32 x 32] type:4 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[32 x 32] type:4 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[32 x 32] type:4 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[32 x 32] type:4 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[32 x 32] type:4 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[32 x 32] type:4 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[32 x 32] type:4 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[32 x 32] type:4 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[32 x 32] type:5 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[32 x 32] type:5 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[32 x 32] type:5 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[32 x 32] type:5 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[32 x 32] type:5 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[32 x 32] type:5 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[32 x 32] type:5 continuous = false iterations:1000 nz=true pos=end cv::hasNonZero =>1 perf:0.607347ms => 1.64651e+06 im/s cv::countNonZero =>1 perf:0.467037ms => 2.14116e+06 im/s * ============================================================ size:[32 x 32] type:5 continuous = false iterations:1000 nz=false pos=none cv::hasNonZero =>0 perf:0.618162ms => 1.6177e+06 im/s cv::countNonZero =>0 perf:0.468175ms => 2.13595e+06 im/s * ============================================================ size:[32 x 32] type:6 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[32 x 32] type:6 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[32 x 32] type:6 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[32 x 32] type:6 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[32 x 32] type:6 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[32 x 32] type:6 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[32 x 32] type:6 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[32 x 32] type:6 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[64 x 64] type:0 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[64 x 64] type:0 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[64 x 64] type:0 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[64 x 64] type:0 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[64 x 64] type:0 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[64 x 64] type:0 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[64 x 64] type:0 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[64 x 64] type:0 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[64 x 64] type:2 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[64 x 64] type:2 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[64 x 64] type:2 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[64 x 64] type:2 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[64 x 64] type:2 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[64 x 64] type:2 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[64 x 64] type:2 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[64 x 64] type:2 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[64 x 64] type:4 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[64 x 64] type:4 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[64 x 64] type:4 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[64 x 64] type:4 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[64 x 64] type:4 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[64 x 64] type:4 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[64 x 64] type:4 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[64 x 64] type:4 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[64 x 64] type:5 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[64 x 64] type:5 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[64 x 64] type:5 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[64 x 64] type:5 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[64 x 64] type:5 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[64 x 64] type:5 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[64 x 64] type:5 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[64 x 64] type:5 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[64 x 64] type:6 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[64 x 64] type:6 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[64 x 64] type:6 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[64 x 64] type:6 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[64 x 64] type:6 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[64 x 64] type:6 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[64 x 64] type:6 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[64 x 64] type:6 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[128 x 128] type:0 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[128 x 128] type:0 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[128 x 128] type:0 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[128 x 128] type:0 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[128 x 128] type:0 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[128 x 128] type:0 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[128 x 128] type:0 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[128 x 128] type:0 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[128 x 128] type:2 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[128 x 128] type:2 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[128 x 128] type:2 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[128 x 128] type:2 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[128 x 128] type:2 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[128 x 128] type:2 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[128 x 128] type:2 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[128 x 128] type:2 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[128 x 128] type:4 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[128 x 128] type:4 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[128 x 128] type:4 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[128 x 128] type:4 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[128 x 128] type:4 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[128 x 128] type:4 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[128 x 128] type:4 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[128 x 128] type:4 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[128 x 128] type:5 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[128 x 128] type:5 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[128 x 128] type:5 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[128 x 128] type:5 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[128 x 128] type:5 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[128 x 128] type:5 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[128 x 128] type:5 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[128 x 128] type:5 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[128 x 128] type:6 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[128 x 128] type:6 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[128 x 128] type:6 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[128 x 128] type:6 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[128 x 128] type:6 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[128 x 128] type:6 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[128 x 128] type:6 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[128 x 128] type:6 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[320 x 240] type:0 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[320 x 240] type:0 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[320 x 240] type:0 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[320 x 240] type:0 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[320 x 240] type:0 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[320 x 240] type:0 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[320 x 240] type:0 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[320 x 240] type:0 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[320 x 240] type:2 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[320 x 240] type:2 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[320 x 240] type:2 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[320 x 240] type:2 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[320 x 240] type:2 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[320 x 240] type:2 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[320 x 240] type:2 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[320 x 240] type:2 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[320 x 240] type:4 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[320 x 240] type:4 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[320 x 240] type:4 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[320 x 240] type:4 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[320 x 240] type:4 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[320 x 240] type:4 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[320 x 240] type:4 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[320 x 240] type:4 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[320 x 240] type:5 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[320 x 240] type:5 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[320 x 240] type:5 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[320 x 240] type:5 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[320 x 240] type:5 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[320 x 240] type:5 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[320 x 240] type:5 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[320 x 240] type:5 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[320 x 240] type:6 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[320 x 240] type:6 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[320 x 240] type:6 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[320 x 240] type:6 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[320 x 240] type:6 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[320 x 240] type:6 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[320 x 240] type:6 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[320 x 240] type:6 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[512 x 512] type:0 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[512 x 512] type:0 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[512 x 512] type:0 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[512 x 512] type:0 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[512 x 512] type:0 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[512 x 512] type:0 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[512 x 512] type:0 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[512 x 512] type:0 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[512 x 512] type:2 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[512 x 512] type:2 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[512 x 512] type:2 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[512 x 512] type:2 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[512 x 512] type:2 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[512 x 512] type:2 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[512 x 512] type:2 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[512 x 512] type:2 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[512 x 512] type:4 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[512 x 512] type:4 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[512 x 512] type:4 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[512 x 512] type:4 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[512 x 512] type:4 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[512 x 512] type:4 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[512 x 512] type:4 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[512 x 512] type:4 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[512 x 512] type:5 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[512 x 512] type:5 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[512 x 512] type:5 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[512 x 512] type:5 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[512 x 512] type:5 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[512 x 512] type:5 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[512 x 512] type:5 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[512 x 512] type:5 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[512 x 512] type:6 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[512 x 512] type:6 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[512 x 512] type:6 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[512 x 512] type:6 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[512 x 512] type:6 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[512 x 512] type:6 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[512 x 512] type:6 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[512 x 512] type:6 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[640 x 480] type:0 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[640 x 480] type:0 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[640 x 480] type:0 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[640 x 480] type:0 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[640 x 480] type:0 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[640 x 480] type:0 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[640 x 480] type:0 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[640 x 480] type:0 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[640 x 480] type:2 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[640 x 480] type:2 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[640 x 480] type:2 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[640 x 480] type:2 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[640 x 480] type:2 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[640 x 480] type:2 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[640 x 480] type:2 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[640 x 480] type:2 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[640 x 480] type:4 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[640 x 480] type:4 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[640 x 480] type:4 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[640 x 480] type:4 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[640 x 480] type:4 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[640 x 480] type:4 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[640 x 480] type:4 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[640 x 480] type:4 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[640 x 480] type:5 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[640 x 480] type:5 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[640 x 480] type:5 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[640 x 480] type:5 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[640 x 480] type:5 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[640 x 480] type:5 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[640 x 480] type:5 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[640 x 480] type:5 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[640 x 480] type:6 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[640 x 480] type:6 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[640 x 480] type:6 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[640 x 480] type:6 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[640 x 480] type:6 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[640 x 480] type:6 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[640 x 480] type:6 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[640 x 480] type:6 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[1024 x 768] type:0 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[1024 x 768] type:0 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[1024 x 768] type:0 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[1024 x 768] type:0 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[1024 x 768] type:0 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[1024 x 768] type:0 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[1024 x 768] type:0 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[1024 x 768] type:0 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[1024 x 768] type:2 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[1024 x 768] type:2 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[1024 x 768] type:2 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[1024 x 768] type:2 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[1024 x 768] type:2 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[1024 x 768] type:2 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[1024 x 768] type:2 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[1024 x 768] type:2 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[1024 x 768] type:4 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[1024 x 768] type:4 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[1024 x 768] type:4 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[1024 x 768] type:4 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[1024 x 768] type:4 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[1024 x 768] type:4 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[1024 x 768] type:4 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[1024 x 768] type:4 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[1024 x 768] type:5 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[1024 x 768] type:5 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[1024 x 768] type:5 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[1024 x 768] type:5 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[1024 x 768] type:5 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[1024 x 768] type:5 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[1024 x 768] type:5 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[1024 x 768] type:5 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[1024 x 768] type:6 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[1024 x 768] type:6 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[1024 x 768] type:6 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[1024 x 768] type:6 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[1024 x 768] type:6 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[1024 x 768] type:6 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[1024 x 768] type:6 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[1024 x 768] type:6 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[2048 x 2048] type:0 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[2048 x 2048] type:0 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[2048 x 2048] type:0 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[2048 x 2048] type:0 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[2048 x 2048] type:0 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[2048 x 2048] type:0 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[2048 x 2048] type:0 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[2048 x 2048] type:0 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[2048 x 2048] type:2 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[2048 x 2048] type:2 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[2048 x 2048] type:2 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[2048 x 2048] type:2 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[2048 x 2048] type:2 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[2048 x 2048] type:2 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[2048 x 2048] type:2 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[2048 x 2048] type:2 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[2048 x 2048] type:4 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[2048 x 2048] type:4 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[2048 x 2048] type:4 continuous = true iterations:1000 nz=true pos=end cv::hasNonZero =>1 perf:895.381ms => 1116.84 im/s cv::countNonZero =>1 perf:882.569ms => 1133.06 im/s * ============================================================ size:[2048 x 2048] type:4 continuous = true iterations:1000 nz=false pos=none cv::hasNonZero =>0 perf:899.53ms => 1111.69 im/s cv::countNonZero =>0 perf:870.894ms => 1148.24 im/s * ============================================================ size:[2048 x 2048] type:4 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[2048 x 2048] type:4 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[2048 x 2048] type:4 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[2048 x 2048] type:4 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[2048 x 2048] type:5 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[2048 x 2048] type:5 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[2048 x 2048] type:5 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[2048 x 2048] type:5 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[2048 x 2048] type:5 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[2048 x 2048] type:5 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[2048 x 2048] type:5 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[2048 x 2048] type:5 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[2048 x 2048] type:6 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[2048 x 2048] type:6 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[2048 x 2048] type:6 continuous = true iterations:1000 nz=true pos=end cv::hasNonZero =>1 perf:2018.92ms => 495.313 im/s cv::countNonZero =>1 perf:1966.37ms => 508.552 im/s * ============================================================ size:[2048 x 2048] type:6 continuous = true iterations:1000 nz=false pos=none cv::hasNonZero =>0 perf:2005.87ms => 498.537 im/s cv::countNonZero =>0 perf:1992.78ms => 501.812 im/s * ============================================================ size:[2048 x 2048] type:6 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[2048 x 2048] type:6 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[2048 x 2048] type:6 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[2048 x 2048] type:6 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[1031 x 1000] type:0 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[1031 x 1000] type:0 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[1031 x 1000] type:0 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[1031 x 1000] type:0 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[1031 x 1000] type:0 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[1031 x 1000] type:0 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[1031 x 1000] type:0 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[1031 x 1000] type:0 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[1031 x 1000] type:2 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[1031 x 1000] type:2 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[1031 x 1000] type:2 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[1031 x 1000] type:2 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[1031 x 1000] type:2 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[1031 x 1000] type:2 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[1031 x 1000] type:2 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[1031 x 1000] type:2 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[1031 x 1000] type:4 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[1031 x 1000] type:4 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[1031 x 1000] type:4 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[1031 x 1000] type:4 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[1031 x 1000] type:4 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[1031 x 1000] type:4 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[1031 x 1000] type:4 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[1031 x 1000] type:4 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[1031 x 1000] type:5 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[1031 x 1000] type:5 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[1031 x 1000] type:5 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[1031 x 1000] type:5 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[1031 x 1000] type:5 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[1031 x 1000] type:5 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[1031 x 1000] type:5 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[1031 x 1000] type:5 continuous = false iterations:1000 nz=false pos=none ============================================================ size:[1031 x 1000] type:6 continuous = true iterations:1000 nz=true pos=begin ============================================================ size:[1031 x 1000] type:6 continuous = true iterations:1000 nz=true pos=middle ============================================================ size:[1031 x 1000] type:6 continuous = true iterations:1000 nz=true pos=end ============================================================ size:[1031 x 1000] type:6 continuous = true iterations:1000 nz=false pos=none ============================================================ size:[1031 x 1000] type:6 continuous = false iterations:1000 nz=true pos=begin ============================================================ size:[1031 x 1000] type:6 continuous = false iterations:1000 nz=true pos=middle ============================================================ size:[1031 x 1000] type:6 continuous = false iterations:1000 nz=true pos=end ============================================================ size:[1031 x 1000] type:6 continuous = false iterations:1000 nz=false pos=none done ``` |