video: fix DISOpticalFlow heap-buffer-overflow with patch_size > border_size - #29715Fixes#20185.
### What
`DISOpticalFlowImpl` pads `I1` of every pyramid level with a **fixed 16 pixel border** (`border_size`), while `PatchInverseSearch` clamps a patch's sample position to:
```cpp
float i_lower_limit = bsz - psz + 1.0f; // bsz = border_size, psz = patch_size
float i_upper_limit = bsz + dis->h - 1.0f;
```
i.e. a patch may be placed up to `patch_size - 1` pixels outside of the image. `computeSSD()`/`computeSSDMeanNorm()` then read `patch_size` (+1 for bilinear interpolation) rows/columns starting at that clamped position, which stays inside the padded buffer only while `patch_size <= border_size`. `patch_size` is user-settable via `setPatchSize()` with no upper bound relative to the hardcoded `border_size` -- so `setPatchSize()` past 16, or a temporal-candidate flow large enough to push the clamped search against its limit, reads past the end of `I1s_ext` (confirmed via AddressSanitizer: heap-buffer-overflow in `computeSSDMeanNorm`).
### Fix
Size the border to whichever is larger, exactly once, at the top of `prepareBuffers()` (where every `I1s_ext[i]` already gets freshly created/padded on every `calc()` call, so this doesn't need any additional cache-invalidation logic):
```cpp
border_size = max(16, patch_size);
```
The needed inequality (`border_size >= patch_size`) is independent of image size, so this is sufficient at every pyramid level uniformly. `ocl_prepareBuffers()` does not need the equivalent change: `calc()`'s `CV_OCL_RUN` gate only takes the OpenCL path when `patch_size == 8` exactly, which is always within the hardcoded border, so that path can never reach this overflow.
### On the prior attempt
A prior attempt at this exact fix (#29600) was closed by @asmorkalov, who ran its own added regression test and got the same ASan heap-buffer-overflow again ("the patch is not efficient"). I want to be upfront about this rather than just re-submitting the same-looking diff: **I could not reproduce that failure.** I reproduced the original overflow on unfixed 5.x (same crash site / allocator stack as both the original issue report and #29600's own ASan trace), then applied the same one-line fix and ran #29600's own added test 20x plus a new 40-trial randomized stress test (`patch_size` 9-48 -- spanning above and below `border_size=16` -- varying image size, `patch_stride`, flow magnitude up to 120px, and a same-instance second `calc()` call to exercise buffer re-use across a patch-size change) under AddressSanitizer, with zero failures. I don't have a confirmed explanation for the discrepancy -- possibly a stale incremental build on the original attempt's end, since I hit and had to work around exactly that kind of false "no work to do" ninja build-cache issue myself while setting up this reproduction. Flagging this openly rather than asserting certainty either way -- happy to dig further if CI or review surfaces a case this doesn't cover.
### Testing
Verified locally with a dedicated ASan-instrumented Debug build (`-fsanitize=address`, separate from the Release build used to verify the rest of today's changes), specifically because an out-of-bounds read like this often just silently returns garbage in a Release build instead of crashing:
- Confirmed the crash reproduces on unfixed 5.x, and is gone with the fix, under both `regression_20185_patch_larger_than_border` (from #29600, included here) and a new `regression_20185_stress` test (40 randomized trials) -- both passing cleanly under ASan.
- Re-verified both tests pass in the standard Release configuration too.
- Full `opencv_test_video` suite (both ASan and Release): no failures attributable to this change; everything else failing needs `opencv_extra` test data (tracking/ECC/optical-flow reference videos/images) not configured in this scoped build.
### PR checklist
- [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 code under GPL or another incompatible license.
- [x] The PR is proposed to the proper branch (5.x).
- [x] Accuracy tests included (see above).
- [x] No public API/behavior change, so no documentation or sample updates needed.
js: doc: clean up Emscripten installation guide and remove outdated C++17 note - #30009
### Summary
- Updated `js_setup.markdown` for modern Emscripten (emsdk 6.x) usage.
- Replaced deprecated `./emsdk update` with `git pull`.
- Replaced outdated version recommendations (`2.0.10`) with `latest` and explicit version fallback (`6.0.9`).
- Removed obsolete Note regarding `--cmake_option="-DCMAKE_CXX_STANDARD=17"`, as OpenCV 5 now defaults to C++17.
### 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
imgcodecs: avoid copying PNG IDAT data during header parsing 🤖🤖🤖 - #29872
`PngDecoder::readHeader()` copies the first IDAT chunk into a temporary vector, discards it, then rewinds the input so libpng can read it again. A PNG stored in one large IDAT chunk therefore incurs an avoidable allocation and payload copy before decoding.
Skip materializing IDAT data during header discovery. For memory input, validate the remaining length and advance the cursor. For file input, seek to and read the final CRC byte to retain early rejection of truncated chunks. Keep buffered reads for small file chunks and when the seek offset cannot fit in `long`; libpng still validates IDAT CRC while decoding static PNGs. APNG frame decoding retains its existing chunk-reading path.
Validation against `52377dee533dbba170d6437a7cf6d42a749a3f8f`, with only this PNG patch applied:
- macOS 26.6.2 / Apple M5 Pro / Apple Clang 21: 579 image-codec cases, four default skips, zero failures; all four new perf smoke cases pass.
- Linux (Ubuntu 24.04.4) / Intel Core i7-6850K / GCC 13.3: the same 579 cases, four default skips, zero failures; all four new perf smoke cases pass.
- All 19 new regression cases also pass against the unchanged baseline libraries on both hosts.
- Matching Release settings within each host, bundled libpng 1.6.57 and zlib 1.3.2.
The revised, committed `PNGDecode` performance cases measure `imdecode(..., IMREAD_UNCHANGED)` on generated random, uncompressed RGB PNGs in memory. Seven alternating baseline/candidate pairs use 30 samples per case and one OpenCV thread; Linux runs are pinned to one CPU. The same revised performance executable is used with each library set, and actual loaded library paths are verified. These measurements are separate from the file-loading results below.
| Memory-decoding workload | Mac speedup | Linux speedup |
| --- | ---: | ---: |
| 512×512, ordinary chunks | 1.001× (0.999–1.003) | 0.999× (0.998–1.002) |
| 512×512, single IDAT | 1.024× (1.022–1.030) | 1.069× (1.067–1.070) |
| 3840×2160, ordinary chunks | 0.999× (0.995–1.011) | 1.001× (1.000–1.001) |
| 3840×2160, single IDAT | 1.022× (1.000–1.024) | 1.383× (1.356–1.419) |
Values are paired median speedups with descriptive bootstrap 95% intervals. Every process passed all four cases with exact pixel comparisons.
Separate C++ `imread(..., IMREAD_COLOR)` measurements use the earlier structured 3840×2160 RGB PNG fixtures, warm filesystem cache, one OpenCV thread, and seven alternating baseline/candidate pairs (minimum 0.15 seconds per batch). Linux runs are pinned to one CPU. Each host checks 100 image/mode cases; decoded dimensions, types, and pixel hashes match across every run and between hosts. The values below are paired median speedups, with bootstrap 95% intervals.
| Workload | Mac speedup | Linux speedup |
| --- | ---: | ---: |
| Uncompressed stream in one ~24.9 MB IDAT | 1.077× (1.046–1.110) | 1.171× (1.170–1.171) |
| Same uncompressed stream in ordinary IDAT chunks | 1.014× (0.945–1.025) | 1.000× (0.997–1.001) |
| Compressed stream in one IDAT | 1.014× (1.007–1.020) | 1.024× (1.021–1.025) |
The large-IDAT case has median latency 16.08→14.83 ms on the Mac and 37.23→31.90 ms on Linux. A separate 15-pair Mac check puts the ordinary chunked control at 1.002× (0.994–1.015). The gain depends on first-IDAT size and decoding cost; ordinary chunked PNGs are approximately neutral.
The new performance tests use the test framework’s `theRNG()` and time `imdecode(encoded, IMREAD_UNCHANGED)` entirely in memory. They generate identical uncompressed RGB images with ordinary 8 KiB IDAT chunks or a single full-image IDAT, at 512×512 and 3840×2160. Encoding and repacking happen outside the timed loop; the performance cases create no temporary files. Run the included cases with the following filters. For an A/B comparison, copy only the test/performance changes to the baseline tree:
```sh
opencv_test_imgcodecs --gtest_filter='*Png_ReadIDAT*'
opencv_perf_imgcodecs --gtest_filter='PNGDecode_idat_layout.idat_layout/*'
```
The regression tests exercise file and memory input, 8/16-bit grayscale/RGB/RGBA, single/multiple/empty-first IDAT layouts, incomplete headers/payloads/CRCs, and corrupt CRCs. They check `imread`, `imdecode`, and `imcount`. All fixtures are generated; no `opencv_extra` patch is needed. Windows was not tested locally.
### Pull Request Readiness Checklist
- [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 code under GPL or another license incompatible with OpenCV.
- [x] The PR is proposed to the proper branch (`5.x`, optimization).
- [x] Accuracy and performance tests are included; test data is generated.
- Original bug report: none; self-contained performance improvement.
- Documentation/sample changes: not applicable; no public API change.
doc: document the bit layout of Mat::type() - #29981
### 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
- [ ] The feature is well documented and sample code can be built with the project CMake
### Description
Fixes#24901.
#### Problem
`cv::Mat::type()` returns a packed bit-field, but the encoding was not documented. Users
had to reverse-engineer the layout from the `CV_*` macros to answer questions such as how many
channels fit, how to build a type from a depth and channel count, and which bits are reserved for
the matrix flags.
#### Change
Expanded the Doxygen for `Mat::type()` in `modules/core/include/opencv2/core/mat.hpp` to describe
the layout used by the 5.x branch:
- bits 0-4 (`CV_MAT_DEPTH_MASK`) – element depth (5 bits);
- bits 5-11 (`CV_MAT_CN_MASK`) – number of channels minus one (7 bits), i.e. 1..`CV_CN_MAX` (128);
- together these occupy the lowest 12 bits (`CV_MAT_TYPE_MASK`).
The description also points to `CV_MAT_DEPTH()`, `CV_MAT_CN()` and `CV_MAKETYPE()`, and notes that
the continuity (`CV_MAT_CONT_FLAG`) and submatrix (`CV_SUBMAT_FLAG`) bits of `Mat::flags` are not
part of the returned value.
#### Branch note
This PR targets `5.x` only. The encoding changed between branches: 5.x uses `CV_CN_SHIFT == 5`
(5-bit depth, 7-bit channel count), whereas 4.x uses `CV_CN_SHIFT == 3`. As requested in the issue,
a separate `4.x` PR would be needed for that branch.
#### Verification
Documentation-only change; no code or behavior is modified. The bit ranges and macro names were
checked against `modules/core/include/opencv2/core/hal/interface.h` and
`modules/core/include/opencv2/core/cvdef.h`:
```
CV_CN_MAX 128
CV_CN_SHIFT 5
CV_DEPTH_MAX (1 << CV_CN_SHIFT) // 32
CV_MAT_DEPTH_MASK (CV_DEPTH_MAX - 1) // 0x1F -> bits 0-4
CV_MAT_CN_MASK ((CV_CN_MAX - 1) << 5) // 0xFE0 -> bits 5-11
CV_MAT_TYPE_MASK (CV_DEPTH_MAX*CV_CN_MAX-1) // 0xFFF
```
core: optimize float REDUCE_SUM2 with RVV - #29930
### Summary
Add an RVV 1.0 kernel for `cv::reduce` with `dim=0` and `CV_32F`
input/output through the CPU dispatch mechanism.
The optimized path targets the floating-point `REDUCE_SUM2` operation.
### Implementation
Process four source rows per vector iteration to reduce intermediate
buffer traffic while preserving source-row accumulation order.
The RVV kernel uses LMUL=4 and dynamic vector lengths for tail handling.
Output writes are deferred until all input rows have been read. This
preserves correct behavior when the source and destination matrices
overlap.
The implementation is VLEN-agnostic.
### Functional Testing
The Reduce tests were run with:
```bash
./bin/opencv_test_core \
--gtest_filter='*Reduce*:*reduce*' \
--test_threads=1
```
### Performance Testing
Performance was measured with:
```bash
./bin/opencv_perf_core \
--gtest_filter='*reduceR*' \
--perf_threads=1
```
Test environment:
- SpacemiT K3
- VLEN = 256
- GCC 14.3.0
- Release build
- Single thread
- 10 samples per case
Results were compared against an unmodified `5.x` baseline.
`CV_32FC1 REDUCE_SUM2` median execution time (ms):
| Size | Baseline | Patched | Speedup |
| --- | ---: | ---: | ---: |
| 640x480 | 0.20 | 0.08 | 2.50x |
| 1280x720 | 0.64 | 0.29 | 2.21x |
| 1920x1080 | 1.33 | 1.05 | 1.27x |
Speedups are approximate and calculated from the rounded benchmark
output.
### Co-authors
- Yang Wang <yangwang@iscas.ac.cn>
- Yuansheng <yuansheng@isrc.iscas.ac.cn>
### Pull Request Readiness Checklist
- [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
FP8 model support in DNN - #29834
ONNX coverage after this PR: 76.6%
co-authored by: @SavyaSanchi-Sharma
### 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
core: fold a*alpha + b*beta + gamma into the fused OP_ADDW kernel - #29953
Part of #29443 — "fuse `a*alpha + b*beta + gamma`, where alpha, beta and gamma are scalars, into
some new `OP_ADDW`". Builds on #29937, which is required for correctness (see below).
### Problem
`OP_ADDW` already computes `a*alpha + b*beta + gamma` as a single kernel over two `v_fma`, and
`emitBinary()` already knows how to emit it — but the string front-end never recognized the
pattern, so `cv::texpr()` always took the written-out path: two multiplies, two adds, three temp
buffers and four passes over the data.
```
{0}*2.0 + {1}*3.0 + 1.0 at CV_32F
insns=4 temps=3 buffers=3 insns=1 temps=0 buffers=0
0: mul(1, 4) -> 5 ==> 0: addWeighted(1, 2) -> 11
1: mul(2, 7) -> 8 params=[2, 3, 1]
2: add(5, 8) -> 9
3: add(9, 11) -> 13
```
### Fix
A peephole in `emitBinary()`: `a*alpha + b*beta` folds into one `OP_ADDW`, and a trailing scalar
folds into that instruction's gamma rather than costing another pass.
`emitBinary()` may wrap a multiply in casts — an integer array times a fractional scalar computes
in the float domain and lands back in the array's own type — so the matcher accepts the optional
widening and narrowing casts around it. That is what makes the common 8-bit blend fuse; without
it `{0}*0.7 + {1}*0.3` at `CV_8U` stays at eight instructions and seven temps.
Shapes that are not an addWeighted keep their own meaning: an `a*b` term has no scalar factor, a
per-channel constant cannot ride the params block, and `CV_Bool` has no `OP_ADDW` form.
**Dependency on #29937.** This retires the instructions it folds, exactly as the
`abs(x - y) -> absdiff` peephole does. Without the `pinned` flag added in #29937 it would
reintroduce that bug for `u = {0}*2.0; v = {1}*3.0; u + v`, where the named terms are still live.
### Semantics on integer types
The fused kernel evaluates at its own work precision, so intermediate results no longer saturate
at each step. On integer inputs the result changes — it now agrees with `cv::addWeighted`, which
is what the expression means. This is the same trade the existing `abs(x - y)` peephole documents
in `emitUnary()`: the saturation artifacts of the literal expansion are never the desired result.
### Performance
1920x1080, best of 5 runs of 50 iterations, same build rebuilt both ways on 03ae9eac50:
| expression | depth | before | after |
| --- | --- | --- | --- |
| `a*0.7 + b*0.3` | 8U | 0.646 ms | 0.159 ms |
| `a*2 + b*3 + 1` | 8U | 0.261 ms | 0.150 ms |
| `a*2.5 + b*-1.5 + 7` | 32F | 0.360 ms | 0.214 ms |
| `a*2 + b*3 + 1` | 32F | 0.213 ms | 0.155 ms |
| `a*b + b*2` (control, not fused) | 32F | 0.393 ms | 0.358 ms |
The control row runs identical code in both builds and still moves by ~9%, so run-to-run noise on
this machine is around 10% — treat the 32F rows as indicative and the 8-bit rows as the real
result. Timings include `cv::texpr()` re-parsing and recompiling the expression on every call, so
the kernel-level gain is larger than the totals suggest.
### Tests
28 parameterised cases — 7 depths crossed with 4 weight sets, including a zero gamma and negative
weights — assert the fused result matches `cv::addWeighted`. Two further tests cover the variants
(no gamma, scalar written first, leading gamma) and the shapes the peephole must decline. 1801
tests in the arithmetic and TExpr suites pass.
Also adds the missing `OP_ADDW` case to `opName()`, which this change makes visible in every dump
of such a program.
### 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
Remove deprecated CommaInitializer API - #29948
This goes hand in hand with https://github.com/opencv/opencv_contrib/pull/4217
### 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
Added Backend Agnostic fusion in DNN - #29656
# What This Adds
A way for any layer, on any backend, to absorb trailing per-element math — with the pass knowing nothing about either layer and holding no list of op types.
- **Description**: `LayerMath` (one layer's math) → `AdjacencyGraph` (hash-consed chain)
- **Contract**: two `bool` virtuals on `Layer`
- **CPU implementations**: three, behind that contract
Pointwise fusion is the first consumer, not the point.
## The Problem
```cpp
ActivationLayer* activ = dynamic_cast<ActivationLayer*>(layer_ptr);
Conv2Layer* conv = getLayer<Conv2Layer>(newprog, conv_layer_idx);
if (conv) conv->fuseActivation(layer);
```
Guest type, host type, method name all hardcoded in the pass. `Clip` never fused (fails the cast), `Gemm` never fused (no virtual), no 2-op chain fused at all, and no backend could fuse anything without a CPU-specific method.
## Results
| Model | 5.x | this PR | speedup |
|-----------------------|----------|----------|---------|
| MPHand | 2.34 ms | 1.03 ms | 2.27 |
| EfficientNet | 9.82 ms | 5.00 ms | 1.96 |
| MPPose | 5.14 ms | 2.81 ms | 1.83 |
| MobileNet_SSD_v1_ONNX | 12.58 ms | 8.38 ms | 1.50 |
| BlazeFace | 0.95 ms | 0.77 ms | 1.23 |
| DenseNet_121 | 20.56 ms | 19.08 ms | 1.08 |
| MobileNetv2_ONNX | 2.07 ms | 1.99 ms | 1.04 |
| MobileViT_XS | 6.33 ms | 6.11 ms | 1.04 |
| YuNet_320 | 1.33 ms | 1.27 ms | 1.04 |
| PPOCRv3 | 43.05 ms | 42.15 ms | 1.02 |
| BERT | 9.78 ms | 9.68 ms | 1.01 |
| BEiT_Base_Patch16_224 | 27.48 ms | 27.08 ms | 1.01 |
| DeiT_Tiny_Patch16_224 | 4.74 ms | 4.72 ms | 1.01 |
| MPPalm | 1.88 ms | 1.85 ms | 1.01 |
| SSD | 50.19 ms | 49.82 ms | 1.01 |
| YOLOv4_tiny | 7.10 ms | 7.03 ms | 1.01 |
### 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
Add a CV_SIMD_SCALABLE path for the DIS patch processing kernels using
universal intrinsics and runtime vector lane counts.
Keep the existing CV_SIMD128 implementation unchanged to avoid affecting
fixed-width SIMD targets. The scalable path vectorizes patch rows with
v_float32 and handles remaining elements with the existing scalar code.
This enables native RVV vectorization for processPatch(),
processPatchMeanNorm(), computeSSD(), and computeSSDMeanNorm().
Co-authored-by: Yang Wang <yangwang@iscas.ac.cn>
Co-authored-by: Yuansheng <yuansheng@isrc.iscas.ac.cn>
core: fix overflow in borderInterpolate BORDER_WRAP path - #29884
### Description
Fixes an integer overflow/underflow bug in `cv::borderInterpolate()` when using `BORDER_WRAP`. For extreme values of `p` (e.g. `INT_MIN` or `INT_MAX`), the previous implementation performed the modulo operation directly on `int`, which can invoke undefined behavior on overflow and produce a result outside the valid `[0, len)` range.
The fix widens the intermediate calculation to `int64_t` before taking the modulo, then adjusts for negative results and narrows back to `int` only once the value is confirmed to be in range.
### Changes
- `modules/core/src/copy.cpp`: use 64-bit intermediate arithmetic in the `BORDER_WRAP` branch of `borderInterpolate()` to avoid overflow.
- `modules/core/test/test_misc.cpp`: add `Core_BorderInterpolate.wrap_no_overflow_29232`, a regression test that exercises `BORDER_WRAP` with `INT_MIN` and `INT_MAX` and asserts the result stays within `[0, len)`.
Fixes#29232
### 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 for the patch (added in test_misc.cpp); no performance test needed as this is a bug fix with negligible performance impact.
- [x] The feature is well documented and sample code can be built with the project CMake
Merge pull request #29931 from abhishek-gola:onnx_conformance_remaining_fixes
fix ONNX auto_pad, PRelu broadcasting and LSTM peepholes - #29931
closes: https://github.com/opencv/opencv/issues/21078
Upated ONNX coverage: 77.8%
### 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
core: rvv: optimize 8U row reduce sum with vwaddu.wv - #29923
### Summary
Optimize the RVV implementation of `reduceRowSum_8u32s` by using the
native widening add instruction `vwaddu.wv`.
The generic scalable-vector path expands each `u8m1` input vector into
two `u16m1` halves and performs two separate load/add/store sequences
for the `u16` accumulation buffer.
On RVV, an `u8m1` vector and an `u16m2` vector have the same number of
elements. This allows the implementation to use an `u16m2` accumulator
directly and combine widening and addition with `vwaddu.wv`:
```text
u16m2 = u16m2 + u8m1
```
This removes the explicit widening and low/high `u16` accumulator split,
reducing the vector operations in the hot accumulation loop.
The existing scalar tail and 256-row `u16`-to-`u32` flush logic remain
unchanged.
The implementation is VLEN-agnostic.
### Functional Testing
The Reduce tests were run with:
```bash
./bin/opencv_test_core \
--gtest_filter='*Reduce*:*reduce*'
```
### Performance Testing
Performance was measured with:
```bash
OPENCV_FOR_THREADS_NUM=1 ./bin/opencv_perf_core \
--gtest_filter='*Reduce*:*reduce*'
```
Test environment:
- SpacemiT K3 / X100
- RVV 1.0
- VLEN = 256
- GCC 14.3.0
- Release build
- Single thread
Results were compared against an unmodified `5.x` baseline.
Median execution time (ms):
| Size / Type | Baseline | RVV `vwaddu.wv` | Speedup |
| --- | ---: | ---: | ---: |
| 640x480 8UC1 | 0.09 | 0.05 | 1.80x |
| 640x480 8UC4 | 0.36 | 0.16 | 2.25x |
| 1280x720 8UC1 | 0.27 | 0.12 | 2.25x |
| 1280x720 8UC4 | 1.08 | 0.56 | 1.93x |
| 1920x1080 8UC1 | 0.62 | 0.29 | 2.14x |
| 1920x1080 8UC4 | 2.43 | 1.11 | 2.19x |
Geometric mean speedup: **~2.09x**.
`REDUCE_MIN`, `REDUCE_MAX`, and `REDUCE_SUM2` performance remains
essentially unchanged, indicating that the speedup is localized to the
optimized 8-bit row SUM path.
### Co-authors
- Yang Wang <yangwang@iscas.ac.cn>
- Yuansheng <yuansheng@isrc.iscas.ac.cn>
### 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
imgproc: fix NaN in phaseCorrelateIterative for float32 input - #29871
### 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
### Summary
`cv::phaseCorrelateIterative` could return the image boundary as the detected shift (e.g. `(-32, -32)` for a 64x64 image) for ordinary float32 input, while the same input in float64 and the non-iterative `cv::phaseCorrelate` both return the correct shift. Reported in #29849 with a reproducer.
### Problem
`calculateCrossPowerSpectrum()` divided by the bin magnitude without a zero check. When a frequency bin of the cross power spectrum has exactly zero magnitude, the division produces NaN (0/0). A single NaN bin is enough: after the inverse DFT the whole correlation landscape becomes NaN, `minMaxLoc` degenerates, the peak lands on the wraparound corner, and the function exits through the out-of-bounds fallback returning `L3peak - L3mid = (-N/2, -M/2)`.
This is reachable with perfectly valid input: for a 64x64 image, bins where either frequency component hits Nyquist produce `dft1[bin] * conj(dft2[bin]) = 0` for Gaussian-like windows (the Hanning-windowed images issue #29849 used), because one of the DFT factors is exactly zero there.
### Solution
Two changes in `calculateCrossPowerSpectrum()`, both matching what the non-iterative implementation already does:
1. Guard the zero-magnitude case: a bin with zero magnitude has undefined phase, so write 0 instead of dividing by zero. `cv::divSpectrums()` handles the same situation by adding an epsilon to the denominator; zeroing the bin is equivalent here and keeps the output strictly on the unit circle.
2. Accumulate in `double` before rounding back to the storage type, as `cv::divSpectrums()` does in its CV_32F branch. This also protects large images, where float32 products of DFT bins can overflow to inf.
### Testing
- Reproduced #29849 with the issue's reproducer ported to C++: float32 returned `(-32, -32)` before the fix, `(-2.96, 1.99)` after (float64 reference: `(-2.94, 1.96)` for the true shift (-3, +2)).
- Added regression test `Imgproc_PhaseCorrelationIterative/64x64_float32_accuracy` covering this case. Verified it fails without the fix (returns `(-32, -32)`) and passes with it.
- `opencv_test_imgproc`: all 1635 tests pass with the fix (opencv_extra testdata, 5.x branch). The pre-existing `float32_overflow` and accuracy tests for the non-iterative path also pass.
Port of #29862 (merged into 4.x) to 5.x.
- Type/stride substitution only; arithmetic and evaluation order unchanged.
- RedBlackSOR: the v_extract<3>(prev, next) previous-lane construction is
replaced by an unaligned vx_load(p_next + j - 1); v_extract<3> is only
previous-lane when vlanes == 4, so this is required for wider lanes.
- HorPass keeps a strict bound, j < len - vlanes, while the other three use
j <= len - vlanes, since the vector body applies UPDATE to every lane and
the rightmost element must not receive UPDATE across the right border.
- No SVE claim: there is no SVE backend in-tree; scalable means RVV today.
video:rvv: optimize PyrLK tracker with RVV - #29947
### Summary
Add an RVV path to `LKTrackerInvoker` for patch interpolation and
covariance matrix accumulation.
### Implementation
Vectorize bilinear interpolation of image pixels and derivatives, and
accumulate A11, A12 and A22 using RVV widening operations. Reuse
temporary vectors and keep the main computation at `e16,m1` and
`e32/f32,m2` to limit vector register pressure.
### Functional Testing
```bash
./bin/opencv_test_video \
--gtest_filter='Video_OpticalFlowPyrLK.accuracy' \
--test_threads=1
./bin/opencv_test_video \
--gtest_filter='Video_OpticalFlowPyrLK.submat' \
--test_threads=1
```
Correctness was verified with:
- `Video_OpticalFlowPyrLK.accuracy`
- `Video_OpticalFlowPyrLK.submat`
### Performance Testing
```bash
OPENCV_FOR_THREADS_NUM=1 \
./bin/opencv_perf_video \
--gtest_filter='*OpticalFlowPyrLK_self*' \
--perf_threads=1
```
Performance was measured with `OpticalFlowPyrLK_self` using a single
thread on an RVV 1.0 system with VLEN=256.
All 96 benchmark cases improved with no regression. The sum of
per-case median execution times decreased from 409.89 ms to 332.33 ms,
a reduction of 18.9%. The best case decreased from 8.41 ms to 5.50 ms,
corresponding to a 34.6% reduction in execution time (1.53x speedup).
Median execution time (ms):
| Metric | Baseline | RVV | Time reduction |
|---|---:|---:|---:|
| Sum of per-case medians across all 96 cases | 409.89 | 332.33 | 18.9% |
| Best case | 8.41 | 5.50 | 34.6% |
### Co-authors
- Yang Wang <yangwang@iscas.ac.cn>
- Yuansheng <yuansheng@iscas.ac.cn>
### Pull Request Readiness Checklist
- [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
Port of #29862 (merged into 4.x) to 5.x.
- Type/stride substitution only; arithmetic and evaluation order unchanged.
- RedBlackSOR: the v_extract<3>(prev, next) previous-lane construction is
replaced by an unaligned vx_load(p_next + j - 1); v_extract<3> is only
previous-lane when vlanes == 4, so this is required for wider lanes.
- HorPass keeps a strict bound, j < len - vlanes, while the other three use
j <= len - vlanes, since the vector body applies UPDATE to every lane and
the rightmost element must not receive UPDATE across the right border.
- No SVE claim: there is no SVE backend in-tree; scalable means RVV today.
FileStorage's XML/YAML/JSON parsers recurse once per nesting level
with no depth limit, allowing a small crafted file to exhaust the
stack and crash the process with an uncatchable SIGSEGV (CWE-674).
Add a shared CV_PERSISTENCE_MAX_DEPTH constant and thread a depth
counter through parseValue (XML/YAML) and parseSeq/parseMap (JSON),
raising a catchable cv::Exception via CV_PARSE_ERROR_CPP once the
limit is exceeded.
Fixes#29939
TExpr::moveToOutput() and the abs(x - y) -> absdiff(x, y) peephole in
TExpr::emitUnary() retire a value's arg slot (reclassify it to NONE) once
its single consumer has been emitted. That holds for an anonymous
intermediate, but a value the parser bound to a name ("t = ...;") may be
referenced again: the parser's name table still points at the retired slot,
so the later reference resolved to the reserved empty operand and
cv::texpr() silently returned a wrong result - for
t = {0} - {1}; abs(t) + t
t = {0} - {1}; (abs(t), t)
t = {0} + {1}; (t, t)
the reused name yielded input {0} instead of its own value, with no
assertion.
Mark a slot as pinned when the parser binds it to a name and skip both
retire manoeuvres for a pinned slot; each then takes the non-destructive
path it already has - moveToOutput() copies into the output via OP_CAST,
and the abs peephole falls through to the plain absdiff(a, 0) form, keeping
the OP_SUB that the name still needs. Anonymous intermediates are
unaffected, so the zero-temp fast path for single-op programs still fires.
core: fix RVV widening load lane count (#29907) - #29921
# core: fix RVV widening load lane count
Partially fixes#29907.
The RVV `v_load_expand` implementation used the source vector lane count for the widening load. For widening loads, the number of loaded elements must match the destination widened vector lane count instead.
This change:
* uses `VTraits<_Tpwvec>::vlanes()` for the RVV widening load and conversion;
* adds regression coverage for `texpr` `select()` with byte masks across multiple data types, channel counts, mask types, strided matrices, and in-place output.
### Pull Request Readiness Checklist
See details at the OpenCV contribution guidelines.
* [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 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 an accuracy/regression test where applicable.
* [x] The change does not require documentation or sample updates.