getNormFunc and getNormDiffFunc had no entries for CV_8F_E4M3FN and
CV_8F_E4M3FNUZ, so cv::norm failed with "func != 0". Add the fp8 kernels
with float accumulators and the same block accumulation as CV_16F and
CV_16BF. Add cv_absdiff overloads for fp8_t and fp8a_t that return
float, so the difference of two fp8 values is not rounded back to fp8.
Add a Core_Norm_FP8 test.
dnn: check weights and soft labels shape in SoftmaxCrossEntropyLoss 🤖🤖🤖 - #30530
`SoftmaxCrossEntropyLossImpl::forward` reads the optional `weights` input as a float array of `C` class weights (`weightBase[y]`, and `wData[c]` on the probability-label path) but never checks its length or type. The probability-label path also reads `labels` with the scores layout (n, c, s) without checking that the labels have the scores shape. Both tensors come straight from the ONNX model, so a short weights initializer or a `[1, C]` labels tensor against `[2, C]` scores reads past the buffer.
Before: weights of shape `[1]` with `C = 64` and labels `C - 1` gives an ASan heap-buffer-overflow READ in `reduceSCEPerSample`. Probability labels `[1, 64]` against scores `[2, 64]` give a READ of size 16 in the forward lambda.
After: both cases throw from `forward`. Weights are checked against `C` and converted to `CV_32F`, which `NegativeLogLikelihoodLoss` already does. Valid models are unchanged, and all 104 `test_sce_*` / `test_nllloss_*` conformance cases pass on OCV/CPU.
Tradeoff: one extra `convertTo` of a `C`-element vector per forward call. In exchange, `float16`/`double` weights are now read with their real values instead of being reinterpreted as float.
A regression test was added to `test_layers.cpp`. It fails under ASan without the fix and passes with it.
### 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
dnn: share equal constants and merge duplicate nodes in the ONNX importer - #30276
# Summary
The ONNX importer now gives initializers with the same type, shape and bytes a single constant,
and `parseNode()` skips a node that has the same op, attributes and inputs as an earlier one,
reusing that node's outputs instead. Many exported models repeat identical work: RAFT pads the
same correlation pyramid again in each of its 10 refinement iterations, and each iteration's
`pads` constant has a different name, so the Pads only look identical when constants are
compared by value. With this change RAFT runs 5 Pads instead of 41, as ONNX Runtime does.
Custom-domain ops, random ops, nodes with subgraphs and nodes producing graph outputs are never
merged. Neither are `QuantizeLinear`/`DequantizeLinear`: `fuseQDQ()` only folds a DQ into
MatMul/Gemm/Conv while it has a single consumer, so merging them would switch off int8 fusion.
Outputs match ONNX Runtime as closely as before.
| Model | This PR | OpenCV 5.0.0 | ORT 1.30 | vs 5.0.0 | vs ORT 1.30 |
|---|---:|---:|---:|---:|---:|
| RAFT | 392.4 ms | 544.5 ms | 291.3 ms | 1.39× faster | 0.74× |
| NAFNet | 1815.8 ms | 2157.6 ms | 1532.6 ms | 1.19× faster | 0.84× |
| YOLOX | 28.3 ms | 29.8 ms | 15.1 ms | 1.05× faster | 0.53× |
> Benchmarked on AMD Ryzen 9 9950X
### 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
python: add documentation signatures for hand-wrapped highgui functions - #30549
Port of #30508 to 5.x
`createTrackbar`, `createButton` and `setMouseCallback` are registered by hand in `cv2.cpp`, so `gen2.py` never sees them and they end up with no Python signature in the generated docs.
Argument names come from the keyword lists in `cv2_highgui.cpp`, which is why `setMouseCallback` reads `window_name, on_mouse` rather than the camelCase in its `cv2.cpp` docstring.
### 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 flag for bitexact resize in blobFromImage and overloads. - #30131
Current INTER_LINEAR resize allows small deviations up to rounding. It affects inference result for networks that produce coordinates (object detectors, features) and descriptors. The new option allow to get the same result independently on CPU arch and used HALs.
Companion PR for references update: https://github.com/opencv/opencv_extra/pull/1422
### 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
FFmpeg for Windows update to 9.0.2 - #30515
aom v3.15.0
ffmpeg n9.0.2
vpx v1.17.0
openh264 v2.7.0
Closes https://github.com/opencv/opencv/issues/30343
### 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
core: support fp8 depths in countNonZero and hasNonZero - #30463Fixes#30461
### Problem
`countNonZeroTab` (`count_non_zero.simd.hpp`) and `hasNonZeroTab` (`has_non_zero.simd.hpp`) have `0` in the `CV_8F_E4M3FN` and `CV_8F_E4M3FNUZ` slots, so `cv::countNonZero` and `cv::hasNonZero` fail with `func != 0` for fp8 input. `cv::findNonZero` already supports both depths since #30341.
### Fix
- `CV_8F_E4M3FN`: new `countNonZero8f` / `hasNonZero8f` kernels. Same as the 8u kernels, but the sign bit is ignored so `-0.0` (`0x80`) counts as zero: the vector path reuses the `v_add_wrap(x, x)` compare of the 16f kernels, and the scalar tail uses `CHECK_NZ_FP8(x) = ((x) & 0x7f) != 0`.
- `CV_8F_E4M3FNUZ`: the existing 8u kernels. This format has no `-0`; `0x80` is its NaN and counts as non-zero, the same as in `findNonZero`.
### Tests
- `CountNonZero1D` now also runs on both fp8 depths.
- `HasNonZeroNegZeros` now also covers `CV_8F_E4M3FNC1`.
- New `CountNonZeroFP8.sign_bit`, a `TEST_P` over both fp8 depths and n = 1, 100, 1031 (scalar tail, single-vector loop, unrolled loop). It fills a `CV_32F` Mat with random values in ±[0.5, 4), sets every 5th element and the last one to `-0.0`, `NaN` or `+0.0`, converts it to fp8, and checks `countNonZero` / `hasNonZero` against the number of non-zero values set. `-0.0` becomes `0x80` in E4M3FN and must count as zero; `NaN` becomes `0x80` in E4M3FNUZ and must count as non-zero.
These fail on current 5.x (`func != 0`) and pass with this patch. All `*NonZero*` and `*FP8*` tests in `opencv_test_core` pass locally on Apple M1 (190 tests), with OpenCL enabled and with `OPENCV_OPENCL_DEVICE=disabled`.
### 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.
- [ ] The feature is well documented and sample code can be built with the project CMake
getLUTFunc had no case for CV_8F_E4M3FN and CV_8F_E4M3FNUZ tables, so
cv::LUT failed with "An unexpected type combination was specified". LUT
only copies table entries, so use the same 1-byte copy as CV_Bool for
both 8-bit and 16-bit indices.
Add both fp8 depths to the LUTAccuracyNewDstTypes test.
* A workaround for the issue in ICV package on Windows implemented in PR opencv/opencv#29771 for IPP Warp perspective implementation for HAL has been reverted since the original issue was fixed in the latest version of ICV package (2026.1.0) enabled in OpenCV in PR #30078.
* The corresponding issue: opencv/opencv#29166.
core: support 5.x depths in sort and sortIdx - #30506Fixes#30505
### Problem
The kernel tables of `cv::sort` and `cv::sortIdx` (`modules/core/src/matrix_operations.cpp`) only have entries for `CV_8U` to `CV_64F`, so every depth added in 5.x fails with `func != 0`.
### Fix
Both tables now use the existing `sort_<T>` / `sortIdx_<T>` templates for:
- `CV_16F` → `hfloat`, `CV_16BF` → `bfloat`, `CV_8F_E4M3FN` → `fp8_t`, `CV_8F_E4M3FNUZ` → `fp8a_t` (compared through their `float` conversion);
- `CV_Bool` → `uchar`, the same kernel as `CV_8U`;
- `CV_64U` → `uint64_t`, `CV_64S` → `int64_t`, `CV_32U` → `uint32_t`.
### Tests
- `Core/sortIdx.simple` now also runs on `CV_16U`, `CV_16F`, `CV_16BF`, `CV_Bool`, `CV_64U`, `CV_64S`, `CV_32U` and both fp8 depths (`CV_16U` was already supported but not tested), and also checks `cv::sort` against sorting a `CV_64F` copy of the same data; there was no `cv::sort` test before.
- New `Core_sort.large_integers` checks exact `sort` / `sortIdx` results for `CV_32S`, `CV_32U`, `CV_64S` and `CV_64U` with values that need the full type: `INT_MIN` / `INT_MAX`, the unsigned high bit (`0x80000000`, `UINT_MAX`, `2^63`, `UINT64_MAX`) and `2^53` vs `2^53 + 1`. With signed kernels for `CV_32U` / `CV_64U` it fails, while the random `sortIdx` test still passes.
The new cases fail on current 5.x and pass with this patch. All `sortIdx` / `sort` tests in `opencv_test_core` pass locally on Apple M1 Pro (242 tests), with OpenCL enabled and with `OPENCV_OPENCL_DEVICE=disabled`. The full `opencv_test_core` passes, except 7 tests that need `opencv_extra` test data, which I didn't have locally (FileStorage base64 and globbing).
### 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.
- [ ] The feature is well documented and sample code can be built with the project CMake
imgcodecs(avif): add support for alpha channel quality control #30499
This pull request adds support for independent alpha channel quality control when encoding AVIF images, resolving #30451.
### What was happening
OpenCV previously only controlled color channel compression via `IMWRITE_AVIF_QUALITY`. Alpha channels remained unhandled or were tied to color quality, making it impossible to adjust color and alpha compression independently (for example, keeping crisp lossless alpha edges while compressing background RGB content lossily to save file size).
### What changed
1. In `modules/imgcodecs/include/opencv2/imgcodecs.hpp`, added `IMWRITE_AVIF_ALPHA_QUALITY = 515` (range 0 to 100, default 95), and updated documentation for `IMWRITE_AVIF_QUALITY` to clarify that it controls color planes.
2. In `modules/imgcodecs/src/grfmt_avif.cpp`:
- Registered `IMWRITE_AVIF_ALPHA_QUALITY` in `m_supported_encode_key`.
- Handled `IMWRITE_AVIF_ALPHA_QUALITY` to set `encoder_->qualityAlpha` (and quantizers for fallback paths).
- Removed the automatic fallback that synced alpha quality to color quality, keeping the two parameters decoupled and order-independent.
3. Added dedicated unit test `Imgcodecs_Avif.alpha_quality_control` in `modules/imgcodecs/test/test_avif.cpp` verifying independent lossy/lossless combinations, order independence, and bounds clamping.
### Testing
- Verified with standalone reproducer (`reproduce_opencv_30451.cpp`):
- Quality=100, AlphaQuality=10: 0 color difference (lossless color) with lossy alpha.
- Quality=10, AlphaQuality=100: 0 alpha difference (lossless alpha) with lossy color.
- Parameter order independence confirmed.
- Native test suite: All 413 AVIF tests passed in `opencv_test_imgcodecs`.
### 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
The eight test_qlinearmatmul_{2D,3D}_{int8,uint8}_{float16,float32} cases
and test_quantizelinear_blocked_asymmetric were on the parser denylist
without test data; opencv_extra#1436 (paired with #30289) added the models
and with them all nine pass on current 5.x. The old denylist comment calls
the QLinearMatMul entries float-output variants, but the suffix is the
scale dtype and the outputs are int8/uint8, which the importer and kernels
already handle.
Remove the nine entries from the denylist and add them to the OpenVINO
filter as SKIP, like the other QLinearMatMul/QuantizeLinear cases there.
Verified on macOS arm64 against current opencv_extra: all 18
parameterizations (OCV/CPU, OCV/CPU_FP16) pass and the whole
Test_ONNX_conformance suite stays green.
Check the [1, 1, N, 7] boxes layout in getMemoryShapes so the output size and the box loop agree on every backend. Emit the extrapolation value for samples outside [0, H - 1] x [0, W - 1] and sample the box center for 1-pixel crops, on both the CPU and CUDA paths.
According to the ONNX protobuf specification, boolean tensors may be stored either in raw_data or packed into repeated int32 int32_data as individual 32-bit integers (not a bitmask). Previously, getMatFromTensor only read raw_data, causing assertion failures when parsing ONNX models that serialize boolean initializers into int32_data.
This patch adds int32_data extraction with conversion to CV_Bool, adds specification documentation, removes unreachable duplicate branches for UINT16/UINT32/UINT64, and adds tests in test_onnx_importer using models from opencv_extra.
Test data in opencv_extra under the same branch name as this patch: https://github.com/opencv/opencv_extra/pull/TBD
Addresses #19366.
dnn: fix GatherND division by zero on empty indices - #30503
GatherND divided by zero in `forward_impl` when the indices tensor is empty, which kills the process with SIGFPE on x86-64 (seen with `LightGlueMatcher` when nothing matches). The layer now returns early when the output is empty.
Fixes#30501
### 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
dnn : int8 optimisation - #30289
### Correctness
- **AVX-VNNI 1x1 conv, leftover pixels:** the last `H*W % 8` output pixels read the VNNI-repacked
weights in the wrong order. Fixes the wrong top-1 of MobileNetV2 and DenseNet121 int8 with VNNI.
- **Padded taps in scalar paths:** the depthwise (AVX2) tail and the NEON kxk scalar path skipped
out-of-image taps instead of using the input zero point. The VNNI kxk kernel now never leaves a
tile under 8 pixels.
### Speed
- **First conv:** quantizing the float image is now parallel and vectorized. A float-input conv
with up to 4 channels runs as a 1x1 conv over each pixel's window. First conv 5-6x faster
(ResNet50: 0.88 -> 0.16 ms). `OPENCV_DNN_INT8_CONV_WINDOW_PACKING=0` disables the window packing.
- **AVX-VNNI depthwise conv:** a new kernel transposes input rows into one row per channel and
adds 4 taps for 8 pixels with one `pshufb` + `vpdpbusd`. Depthwise about 2x faster, output
bit-identical.
- **int8 MatMul at batch 1:** uses all threads instead of one. AlexNet int8: 2.75 -> 1.52 ms.
- **Asymmetric padding:** convs with TF "SAME" padding at stride 2 are now fused to int8 instead of
running in float between Dequantize and Quantize. Float convs in EfficientNet-Lite4 and MP hand
pose: 5 -> 0-1.
- **Broadcast int8 Add/Mul:** copies whole contiguous runs in parallel instead of computing an
index per element.
- **int8 Quantize/Dequantize:** AVX2 fast path for signed int8; per-tensor Q/DQ keep the block
layout.
### Tests
- Companion PR : opencv/opencv_extra#1436 (test data).
### Results (ms, i9-14900KS , default threads)
| Model | 5.x before (ms) | this PR (ms) | ONNX Runtime 1.30 (ms) | Speedup vs 5.x | ORT / this PR |
|---|---|---|---|---|---|
| DenseNet121 int8 | 109.4 | 14.7 | 16.1 | 7.43x | 1.09x |
| PP-OCRv3 det int8 | 65.7 | 12.7 | 33.1 | 5.15x | 2.60x |
| SFace int8 | 8.1 | 3.0 | 19.0 | 2.75x | 6.43x |
| EfficientNet-Lite4 int8 | 4.1 | 2.9 | 1.9 | 1.40x | 0.67x |
| EfficientNet-Lite4 qdq | 4.6 | 3.1 | 2.0 | 1.49x | 0.65x |
| MP hand pose int8 | 2.5 | 0.8 | 2.2 | 3.06x | 2.69x |
| PPHumanSeg int8 | 2.6 | 1.9 | 5.6 | 1.41x | 3.02x |
Co-authored with @Prasadayus
### 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
imgcodecs(avif): fix norm calculation and extend 16-bit tests - #30431
- Correct lossy test normalization from dividing by total samples (N) to root-mean-square (RMS) error divided by sqrt(N), and recalibrate thresholds with margin for 8/10/12/16-bit tests.
- Extend 16-bit AVIF tests to cover all supported channel counts (1, 3, and 4 channels) using testing::Combine.
### 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.
- [ ] The feature is well documented and sample code can be built with the project CMake
dnn: skip MatMul's zero-fill when there is no bias - #30297
Without a bias, MatMul pre-zeroed the whole output with a single-threaded memset and then still passed beta = 1 into the gemm, forcing every kernel to read and multiply-add against that zeroed buffer. Passing beta = 0 instead removes the memset and lets MLAS/fastGemmThin write the product directly. Measured 31-50% faster on a small, write-heavy, no-bias shape (512x32x512, 8 threads); `MatMul.matmul/41` and the new `MatMul.matmul_dynamicB/41` cover the constant-B and dynamic-B paths.
### 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: accept CV_Bool input in morphological operations - #29799
### Pull Request Readiness Checklist
Fixes#29798
In 5.0 `cv::Mat_<bool>::depth()` returns `CV_Bool` instead of `CV_8U`, so the morphology filter factories in `morph.simd.hpp` no longer matched any branch and threw `Unsupported data type`. This worked in 4.x.
`CV_Bool` is a 1-byte 0/1 type, so it is dispatched through the same `uchar` min/max filters as `CV_8U`, and the default border value follows the `CV_8U` case (1 for erode, 0 for dilate). The OpenCL path bails out for `CV_Bool` and falls back to the CPU implementation, since `ocl::typeToStr` has no mapping for it.
Accepting `CV_Bool` also exposed a latent bug in `FilterEngine::init`: `borderElemSize` was computed from `CV_MAT_DEPTH(srcType) >= CV_32S`, which assumes the depth enum is ordered by element size. `CV_Bool` is 9, so a 1-byte type took the `sizeof(int)` branch and `borderElemSize` became 0, leaving `borderTab` empty and making every non-`BORDER_CONSTANT` erode/dilate read through a null pointer. It now keys off `CV_ELEM_SIZE1` instead. `CV_16F`/`CV_16BF` had the same latent miscomputation.
Added a test comparing `Mat_<bool>` against the equivalent `CV_8UC1` mask for erode, dilate, open and close over the three structuring element shapes and four border types, plus in-place and multi-iteration calls.
`MORPH_GRADIENT`/`TOPHAT`/`BLACKHAT` remain unsupported for `CV_Bool`: they subtract two masks, which has no meaning for a boolean type, and they throw rather than returning a wrong result.
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
Do not call Lapack for small operations. - #29909
This reduces the cache for GEMM in calibration: the transposed Jacobian is 6 x 2Number points while the result is 6 x 1.
The previous code was only looking at the input number of rows.
### 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
dnn: avoid unused quadratic workspace for MLAS attention - #30405
`AttentionLayerImpl` allocates a dense `[batch * heads, sequence, sequence]` probability buffer before calling MLAS FlashAttention, even though that path never uses it. With 12 heads and 8,192 tokens, this is an unused 3 GiB allocation that can make inference fail before the tiled kernel runs.
This patch shares the existing fast-path eligibility check between memory planning and execution. It keeps one-element placeholders for the unused probability and output workspaces, preserving the internal buffer indices used by RoPE. If MLAS declines the call, the generic path allocates the dense buffers it needs. Masked attention and builds without MLAS keep their existing workspace plans. The numerical kernels are unchanged.
I reproduced the allocation with a generated FP32 ONNX Attention model loaded through `readNetFromONNX`, using the 5.x graph engine. For batch 1, 12 heads, head width 16 and 8,192 tokens:
| Measurement | Before | After |
| --- | ---: | ---: |
| Largest `cv::Mat` allocation | 3 GiB | 18 MiB |
| Peak live `cv::Mat` storage | 3,279,180,288 bytes | 51,663,368 bytes |
| Forward with a 512 MiB address-space limit | Allocation failure | Completes |
| Peak RSS without the limit | 65,664 KiB | 65,616 KiB |
The allocation trace goes through `allocateLayerOutputs` and `Mat::fit` before the layer's `forward`. The same failure is resolved at 4,096 and 16,384 tokens; at 16,384 tokens, the largest allocation drops from 12 GiB to 36 MiB. Outputs from the constrained runs match the unrestricted runs byte for byte.
The limit above is Linux `RLIMIT_AS`, which limits virtual address space. RSS barely changes because the unused buffer is not touched. The allocation measurements cover `cv::Mat` storage only.
Validation on Linux x86-64:
- 40 targeted tests pass with MLAS in Release, and the same 40 pass under ASan/UBSan with MLAS and SIMD disabled. The workspace regression test fails against the baseline library.
- 56 ONNX baseline/patch comparisons are byte-identical, covering sequence lengths, 1/6 threads, static and dynamic weights, masks, and RoPE. Four of these force `mlasFlashAttention` to return false after dispatch to exercise fallback from a compact workspace plan.
- Reusing a graph across changing sequence lengths passes 40 comparisons against fresh graphs on each version. A separate layer-level matrix adds 144 byte-identical comparisons.
- The existing Attention perf fixture passes all five cases at 1 and 6 threads with `--perf_verify_sanity=true` and no regression data files. This includes new constant-weight cases at 257, 1,024, and 4,096 tokens. Separate longer pinned timing runs measured approximately +0.5% at 257 tokens and -1.1% at 1,024 tokens; timings vary on this shared host, so this PR makes no speedup claim.
The half-input audit passed six configurations that the graph promotes to FP32. Static, unmasked FP16 constants exposed a separate existing weight-packing issue: the baseline already produces invalid outputs, and ASan reports an out-of-bounds read in unchanged packing code. Those cases are excluded from passing validation. ARM and other platforms still need CI.
This follows the MLAS integration in #29126. #30126 addresses a different source of memory use (weight ownership), but touches the same class. `AttentionOnnxAiLayerImpl` is outside this change.
### 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 targets the proper branch (`5.x`).
- [x] Related work is referenced above; the reproducer and measurements describe the bug.
- [x] Accuracy and performance tests are included. They generate their inputs and require no new `opencv_extra` data.
- [x] No public API changes or new samples requiring documentation.