HoughLines, HoughLinesP, and HoughLinesPointSet document that lines are
returned when votes > threshold. Because both accumulator votes and
threshold are integers, threshold = 0 is the only value that selects
1-vote bins (votes >= 1), as already supported by HoughLinesPointSet,
CPU HoughLines, and the OpenCL paths.
PR #30286 added CV_CheckGT(threshold, 0) at the HoughLines/HoughLinesP
entry points to avoid a divide-by-zero (`nz * numangle / threshold`) in
the IPP path. Relax this check to CV_CheckGE(threshold, 0) and guard the
IPP fast paths with `threshold > 0` instead (IPP also requires
threshold > 0).
dnn(cuda): transformer layer coverage and CUDA Graph replay on the new engine - #30439
Follow-up to #30415 (ResNet layer coverage and cuDNN JIT conv/pooling on the new engine). Adds CUDA support on the new DNN engine
for the layers transformer models need, and brings the CUDA path to parity with ONNX Runtime.
**Companion PR** opencv/opencv_extra#1448
**Changes**
- CUDA execs for Attention, Cast, ConstantOfShape, Expand, Gather, Not, Reduce, Shape, Slice, Softmax, Tile, Transpose, Concat,
Gelu, LayerNormalization, MatMul, Split, Squeeze, Unsqueeze and the element-wise activations.
- A graph with static shapes is recorded as one CUDA Graph on the second `forward()` and replayed from then on.
- The cuDNN JIT convolution reads NCHW buffers in place; NHWC staging is kept only for FP16 grouped convolutions.
- TF32 for cuBLAS GEMMs (`OPENCV_DNN_CUDA_ALLOW_TF32`), FP32 accumulation for FP16 GEMMs
(`OPENCV_DNN_CUDA_FP16_HALF_ACCUMULATE`), and fused MatMul/Gemm post-ops.
- Batch-broadcast MatMul and Shape are safe to capture in a CUDA Graph; the unused pointer-array `cublas::gemmBatched` is
removed.
- Tests: `forward()` runs three times on batch-broadcast MatMul and Shape models; `MatMul_init_bcast` runs on CUDA again;
`AttentionSharedShapeReshape` uses the FP16 default tolerance on CUDA FP16.
- Perf: new CUDA-only `*_CUDA_pinned` tests pin the input shapes.
**Performance** (ms, median of 50, FP32 with TF32, RTX PRO 6000 Blackwell, idle GPU)
| Model | CPU | CUDA (cuDNN JIT) | CUDA (full cuDNN) | ORT 1.31 CUDA EP |
|---|---|---|---|---|
| ResNet-50 | 8.02 | 0.80 | 0.80 | 0.88 |
| ResNet-18 | 3.27 | 0.44 | 0.44 | 0.48 |
| MobileNetV2 | 1.99 | 0.28 | 0.27 | 0.40 |
| DenseNet-121 | 17.42 | 1.48 | 1.58 | 1.58 |
| EfficientNet-Lite4 | 5.03 | 0.53 | 0.54 | 0.73 |
| ViT-B/32 | 11.06 | 1.02 | 1.02 | 0.95 |
| ViT-Base/16 | 24.38 | 1.16 | 1.17 | 1.13 |
| DeiT-Tiny | 4.58 | 0.65 | 0.65 | 0.68 |
| MobileViT-XS | 6.93 | 0.72 | 0.72 | 0.77 |
| YOLOv3 | 47.21 | 2.60 | 2.59 | 2.72 |
| YOLOv4 | 109.38 | 3.58 | 3.61 | 4.18 |
| YOLOv4-tiny | 7.31 | 0.64 | 0.64 | 0.66 |
| BEiT-Base | 25.30 | 1.24 | 1.24 | 1.19 |
| BERT | 10.00 | 0.97 | 0.97 | 0.99 |
| SigLIP | 41.14 | 2.09 | 2.09 | 2.44
### 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
patchNaNs asserted CV_32F or CV_64F input, so 16-bit float arrays,
which can hold NaN too, could not be patched.
Add patchNaNs_16, the same bit test as the 32-bit kernel on 16-bit
words, with the infinity pattern of each format (0x7c00 for CV_16F,
0x7f80 for CV_16BF). getPatchNanFunc now takes the depth. The OpenCL
kernel only handles float and double, so other depths fall back to
the CPU path.
- The CV_Bool NOT kernel now computes x == 0 instead of x ^ 1, so a
non-0/1 byte (still true, as in convertTo) becomes 0 instead of 254.
The cvtest::logicOp reference does the same.
- bitwise_not no longer tries OpenCL for CV_Bool. It already ended up
on the CPU kernel, but only because memopTypeToStr() asserts on
CV_Bool and CV_OCL_RUN catches the exception.
- Core_Bitwise.not_bool also checks a UMat input and 255 bytes in both
the SIMD loop and the scalar tail.
The NOT kernel was picked by element size only, so CV_Bool ran the
same ~x kernel as CV_8U and turned 0/1 into 255/254. Both are non-zero,
so every element of ~mask counted as true. Pass the depth to
getNotFunc and use x ^ 1 for CV_Bool. Fix the same ~x in the
cvtest::logicOp reference, which made Core_Not expect 254.
Add a Core_Bitwise regression test.
dnn: derive the Resize scales from the given scales, not from the shapes - #30105
### 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 that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch (5.x)
- [x] There is a reference to the original bug report and related work (no pre-existing report; found by differential testing against ONNX Runtime, see *Problem*)
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable (companion PR: opencv/opencv_extra#1455)
- [x] The feature is well documented and sample code can be built with the project CMake
---
### Problem
`Resize` resamples with a step of `in/out` when the target size comes from the `scales` input,
but ONNX defines the step along an axis as `1/scale`. The two agree only while `in*scale` is an
integer, which is not the common case. A `1x2x4x5` input with `scales=[1,1,0.5,0.5]` produces a
`1x2x2x2` output, so the step along `W` is `2` (as `1/0.5`) and not `2.5` (as `5/2`):
| `Resize(nearest=False, mode=linear, coordinate_transformation_mode=half_pixel)` | ONNX Runtime 1.30 | before |
|---|---|---|
| `1x2x4x5` input, `scales=0.5`, first output row | `0.49208999 -0.11570000` | `0.28683999 -0.48815000` |
The error is not restricted to downscaling. Any non-integral `in*scale` is affected, e.g. a
7-wide input with `scale=1.5` (output 10) was sampled at `0.7` instead of `2/3`. `cubic`,
`pytorch_half_pixel`, `half_pixel_symmetric`, `tf_half_pixel_for_nn` and `asymmetric` are all
affected; the antialias filter support is stretched the same way, producing a `2.5`-pixel-wide
filter where `1/scale` asks for `2`.
### Root cause
A constant `scales` input is folded into the `zoom_factor_x`/`zoom_factor_y` layer parameters by
`ONNXImporter2::parseResize2` (`ninputs` is set to 1). `Resize2LayerImpl::forward` therefore never
saw the tensor and took the step from `updateOutSizeAndScale`, which derives it from the shapes:
```cpp
if (sizes.empty() && !scales.empty() && halfPixelCenters) // never true for folded scales
scaleHeight = 1.f / scales[hIdx];
...
scaleHeight = float(inpShape[2]) / outHeight; // in/out instead of 1/scale
```
The antialias branch had the same problem for its filter support, which it also read from
`scales` (empty in the folded case) or fell back to `outShape/inpShape`.
### Solution
The scales are resolved once, from the `scales` input or from the folded `zoom_factor_*`, and both
the step and the antialias filter use that value:
```cpp
if (sizes.empty() && !alignCorners && onnxScaleH > 0 && onnxScaleW > 0 &&
coordTransModeE != CoordTransMode::TF_CROP_AND_RESIZE)
{
scaleHeight = 1.f / onnxScaleH;
scaleWidth = 1.f / onnxScaleW;
}
```
`align_corners` keeps the step `updateOutSizeAndScale()` derives from the shapes, `(in - 1) / (out - 1)`
with the integer output length, which is what the operator definition and onnxruntime use:
| `Resize(align_corners, mode=linear)` | ONNX Runtime 1.29 | this PR |
|---|---|---|
| `1x1x2x4`, `scales=0.6`, output `1x1x1x2` | `1 4` | `1 4` |
| `1x1x2x4`, `scales=0.6`, output `1x1x3x3`, `mode=cubic` | `1 2.5 4 7 8.5 10 13 14.5 16` | same |
Two stored conformance references still carry the value produced by the ONNX reference
implementation while it divided by the unrounded `input * scale` ([onnx/onnx#8495](https://github.com/onnx/onnx/issues/8495)).
They are regenerated from onnxruntime 1.29 in opencv/opencv_extra#1455, which is what
`test_resize_downsample_scales_{linear,cubic}_align_corners` then compares against.
`tf_crop_and_resize` ignores the step entirely (its grid comes from the roi) and is untouched.
### Tests
Three accuracy tests in `modules/dnn/test/test_layers.cpp`, all on the folded-scale path with an
input whose `in*scale` is not integral, and each fails on the previous code:
| test | covers |
|---|---|
| `Layer_Test_Resize.downscale_uses_given_scales` | step = `1/scale` for `half_pixel`, bilinear |
| `Layer_Test_Resize.antialias_downscale_uses_given_scales` | antialias filter of support `1/scale` |
| `Layer_Test_Resize.align_corners_downscale` | step = `(in - 1) / (out - 1)` and exact corners |
The references are built from the operator definition: `src = (dst + 0.5)/scale - 0.5` for
`half_pixel`, the ONNX antialias triangle filter for the second, and `src = dst * (in - 1)/(out - 1)`
for `align_corners`.
### Validation
- `opencv_test_dnn`: 5204/5204, no regressions.
- `Test_ONNX_conformance.Layer_Test/test_resize_*`: 40/40 with opencv/opencv_extra#1455 applied,
including the antialias and `half_pixel_symmetric` cases that were already green.
- Differential sweep against ONNX Runtime 1.29/1.30 CPU: the failing `Resize` configurations
(`linear`/`cubic`, 6 coordinate transformation modes, `antialias`, `cubic_coeff_a` and
`exclude_outside` combinations) now agree; every other case in the sweep is unchanged.
- Not tested: Windows/MSVC, Clang, ARM/RISC-V, CUDA/OpenVINO/OpenCL targets (no access to those
configurations here). The patch only changes which scale the CPU kernels are given; the
`scaleWidth`/`scaleHeight` members are not consumed by the CUDA/CANN node builders, which keep
using `outHeight`/`outWidth` and the coordinate mode flags.
java: fix Mat get/put JNI for 0D/1D/ND Mats in OpenCV 5 - #29851#29851
## Summary
Fix incorrect behavior of Java `Mat.get()` / `Mat.put()` JNI bindings for
0D (scalar), 1D, and ND `cv::Mat` objects.
The Java JNI layer in `modules/java/generator/src/cpp/Mat.cpp` still assumed
essentially 2D row/col indexing in several get/put code paths. This caused
wrong results or failed access for scalar and 1D Mats, and incorrect bounds
handling for ND Mats accessed via index arrays.
This PR updates the native get/put helpers in `Mat.cpp` and adds regression
tests in `modules/core/misc/java/test/MatTest.java`.
## Problem (before this patch)
### 1. 0D (scalar) Mats
- `Mat::ptr(const int*)` requires `dims >= 1`, so idx-based paths that called
`m->ptr(idx.data())` directly (e.g. `nGetIdx`, `mat_copy_data`, `PUT_ITEM_IDX`)
could not access a true 0D Mat correctly.
- `idx2Offset()` always read `indices[0]` without checking `dims <= 0`.
- Row/col helpers always built a 2-element index `{row, col}` instead of an
empty index vector for 0D Mats.
Although OpenCV 5 supports 0D Mats at the C++ level, the Java wrapper did not
correctly implement idx-based access with an empty index array (`new int[]{}`).
This PR adds explicit JNI support for that case via `mat_elem_ptr()` and
related helpers.
**Example:** For `Mat m = new Mat(new int[]{}, CvType.CV_64F)` (`dims()==0`),
`m.put(new int[]{}, 42.0)` and `m.get(new int[]{}, buf)` could fail or access
the wrong memory.
### 2. 1D Mats (`dims() == 1`)
- Row/col get/put always converted `(row, col)` to `{row, col}` (length 2),
while a 1D Mat requires a single-element index vector.
- For a 1D Mat, OpenCV 5 represents the shape as `dims == rows == 1` and
`cols == total() == N`. The Java row/col access path must therefore interpret
`(row, col)` as the 1D element index represented by `col` (with `row == 0`),
converting internally to `{col}` via `row_col_to_idx()`.
**Example:** For `Mat m = new Mat(new int[]{10}, CvType.CV_32F)`, calling
`m.put(0, 3, values)` could behave incorrectly because native code treated
the access as `{0, 3}` instead of `{3}`.
### 3. ND Mats (`dims() > 2`) via row/col API
- Row/col get/put only checked `rows` and `cols`, without rejecting Mats with
`dims > 2`.
- ND Mats must be accessed via idx-based APIs; using row/col on them could
produce silently wrong results instead of failing early.
### 4. Idx-based API bounds checking
- Old code checked `size[i] <= idx[i]` but did not validate:
- `idx.length == dims`
- negative index values
- `nPutDIdx` computed the number of remaining elements with a per-dimension
product loop (`channels * (size[i] - idx[i]) * ...`). For ND Mats, this did
not correctly account for the current linear index position when determining
how many elements remain from the selected subarray onward. The fix uses
`(total() - idx2Offset(m, idx)) * channels()`, which matches the linear
layout used by `mat_copy_data()`.
## Changes
- Add `mat_elem_ptr()` to support 0D scalar Mats (`Mat::ptr(const int*)`
requires `dims >= 1`).
- Add `check_row_col_access()`, `check_idx_access()`, and `row_col_to_idx()`
to validate access and convert row/col indices according to OpenCV semantics.
- Update `idx2Offset()`, `offset2Idx()`, and `mat_copy_data()` for 0D/1D Mats.
- Route row/col get/put through `row_col_to_idx()` (1D: element index in `col`,
`row == 0`).
- Restrict row/col APIs to Mats with `dims <= 2`; ND Mats must use idx-based
APIs (`nGet*Idx`, `nPut*Idx`, `nGetIdx`, `nPutDIdx`).
- Fix remaining-element calculation in `nPutDIdx` to use `idx2Offset()`.
## Behavior notes
| API | 0D Mat (`dims==0`) | 1D Mat (`dims==1`) | 2D Mat | ND Mat (`dims>2`) |
|-----|-------------------|-------------------|--------|-------------------|
| `get/put(int[] idx, ...)` | supported (`idx.length == 0`; added by this PR) | supported (`idx.length == 1`) | supported | supported |
| `get/put(row, col, ...)` | supported (`row=0`, `col=0`) | supported (index in `col`, `row=0`) | supported | rejected at JNI layer return 0; |
| `get(row, col)` | supported | supported | supported | rejected at JNI layer return 0; |
| `get(int[] idx)` | supported | supported | supported | supported |
## Test plan
Added regression tests in `MatTest.java`:
- `testGetPut0DMat` — idx and row/col get/put on a scalar Mat (`new int[]{}`)
- `testGetPut1DMat` — idx and row/col get/put on `new Mat(new int[]{5}, ...)`
- `testGetPut1DMatDoubleArray` — bulk double put/get via idx on a 1D Mat
- `testGetPut3DMat` — row/col API rejected for 3D Mat; idx API works
### 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
core(doc): update introduction for OpenCV 5.1 - #30598
- Remove redundant highgui and videoio modules.
- Add geometry and ptcloud modules.
- Document new 8-bit floating-point types (CV_8F_E4M3FN and CV_8F_E4M3FNUZ).
### 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.
- [x] The feature is well documented and sample code can be built with the project CMake