core: fix wasm SIMD float rounding - #30213
Summary
- Fix rounding in the WebAssembly SIMD implementation of `v_round(const v_float32x4&)`.
- Add regression tests for positive and negative halfway values.
Motivation
The previous implementation added `0.5` before truncating, which caused incorrect results for some negative values and halfway cases.
This change uses `wasm_f32x4_nearest` before converting the result to integers, providing round-to-nearest, ties-to-even behavior while preserving the existing saturating conversion.
Testing
- git diff --check passed.
- WebAssembly SIMD tests have not been run yet because Emscripten is not available in my current environment.
Pull Request Readiness Checklist
- [x] I agree to contribute to the project under the 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 (`4.x`).
- [ ] Reference to the original bug report and related work.
- [ ] Accuracy/performance tests and test data in `opencv_extra`, if applicable.
- [ ] Documentation and sample code, if applicable.
Related work: OpenCV 5.x rounding fix in [[PR #30007](https://github.com/opencv/opencv/pull/30007)](https://github.com/opencv/opencv/pull/30007).
videoio(ffmpeg): fix black frames for interlaced video 🤖🤖🤖 - #30300
Merge with https://github.com/opencv/opencv_extra/pull/1435
### Summary
With FFmpeg 8+, swscale rejects converting a frame flagged as interlaced into the progressive destination frame. The error returned by `sws_scale_frame()` was ignored, so `VideoCapture::read()` returned true with black frames.
The fix copies the interlaced/top-field-first flags from the source frame onto the destination frame (like FFmpeg's scale filter, which keeps the source field flags), and makes `retrieveFrame()` fail if `sws_scale_frame()` still returns an error.
Fixes#30299
### Testing
- macOS arm64, FFmpeg 9.0.2 / swscale 10.1.102.
- New test `videoio_ffmpeg.interlaced_frame_conversion_30299` (embedded fixture) fails before the change and passes after.
- Full `opencv_test_videoio` with opencv_extra testdata: 561/561 pass.
- The reporter's 5-frame tff clip now reads identical content to the progressive clip.
### Notes / limitations
- The error branch has no direct test, because the field-flag fix removes the only deterministic trigger.
- `VideoCapture::read()` still returns true with a reused non-empty Mat when retrieve fails. This is pre-existing behaviour for all backends and is not changed here.
- Older FFmpeg without `AV_FRAME_FLAG_INTERLACED` is unaffected.
Prepared with AI assistance (Claude Code); reviewed and tested by me.
### 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.
(Accuracy test included with an embedded fixture; no opencv_extra patch needed.)
- [ ] The feature is well documented and sample code can be built with the project CMake
(N/A: bug fix, no new API.)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
x2 is computed from the disparity value and was used as an index into
disp2cost and disp2buf without a range check, in both the CV_16S and the
CV_32S cost branches. A disparity outside the range given by minDisparity and
numberOfDisparities made x2 negative or not less than cols.
Skip such pixels in the reverse mapping pass. The final consistency pass
already bounds-checks the mapped columns.
Fixes#25367
dnn: fix blobRectsToImageRects when the image is not resized - #30243
### 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. No existing report covers this case; reproduction is below. Related: #26085, #30042.
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable. Accuracy test added; no test data needed.
- [ ] The feature is well documented and sample code can be built with the project CMake. Not applicable to this bug fix.
### Problem
`Image2BlobParams::blobRectToImageRect()` and `blobRectsToImageRects()` return `Rect(0, 0, 0, 0)` for every rect when `Image2BlobParams::size` equals the image size, in all three padding modes. With `size` left empty (the default, which `blobFromImageWithParams()` treats as "keep the image size"), the mapping divides by zero and returns `INT_MIN` coordinates. Running a 640x640 detector on 640x640 frames is enough to hit the first case.
```python
import cv2 as cv
p = cv.dnn.Image2BlobParams()
p.size = (640, 640)
p.paddingmode = cv.dnn.DNN_PMODE_LETTERBOX
print(p.blobRectToImageRect((10, 20, 30, 40), (640, 640)))
# (0, 0, 0, 0), expected (10, 20, 30, 40)
p.size = (0, 0)
print(p.blobRectToImageRect((10, 20, 30, 40), (640, 480)))
# (-2147483648, -2147483648, -2147483648, -2147483648), expected (10, 20, 30, 40)
```
Observed with the `opencv-python` 5.0.0 wheel and with a 4.x build at `802cf95aa3`. The function is identical on 4.x and has been since it was added in #24539 (4.9.0).
### Cause
`blobFromImagesWithParams()` replaces an empty `size` with the image size and applies no resize, crop or padding when the two sizes match. `blobRectsToImageRects()` only handles the `size != imgSize` branch: when the sizes match, the output keeps the zero rects created by `rImg.resize()`, and an empty `size` goes into the resize formulas as a zero divisor.
### Change
`blobRectsToImageRects()` now follows the same two rules as `blobFromImagesWithParams()`: an empty `size` means the image size, and when the sizes match, blob and image coordinates are the same, so the input rects are returned. The resize, crop-center and letterbox mappings are unchanged.
The new test covers both cases for all three padding modes. It also checks that the blob built with the same parameters is pixel-identical to the image, which is what makes returning the input rects correct here.
#30042 (5.x feature PR) contains an equivalent pass-through for the equal-size case as part of a larger Model API change; this is the standalone fix for 4.x, including the empty-size case.
### Testing
Built `opencv_test_dnn` and the Python bindings from this branch (head `d90164465c`, base 4.x `802cf95aa3`) on Ubuntu 26.04 (WSL2), GCC 15.2, Ninja, `BUILD_LIST=dnn,python3,ts`.
- `opencv_test_dnn --gtest_filter=blobRectToImageRect*`: 4 passed. On base `802cf95aa3` the new `blobRectToImageRect.no_resize` fails in all six mode/size combinations (`[0 x 0 from (0, 0)]` for equal sizes, `INT_MIN` for empty size); the blob pixel-identity assertion passes there too.
- `opencv_test_dnn --gtest_filter='blob*:*Image2Blob*:*imagesFromBlob*'`: 11 passed.
- `modules/dnn/misc/python/test/test_dnn.py`: 10 passed, including all `blob*` tests; 6 model tests failed only because their opencv_extra files are not present locally (`dnn/googlenet_0.png`, `dnn/opencv_face_detector.prototxt`, ...).
- The Python reproducer above prints `(10, 20, 30, 40)` for both cases with this branch.
- No compiler warnings in the touched files; `git diff --check` clean.
- Full `opencv_test_dnn` was not run (needs opencv_extra test data).
imgproc: preserve phaseCorrelate inputs when windowing - #30281
`phaseCorrelate()` currently performs a shallow copy of input matrices provided they already match the optimal DFT size. This is unsafe when a window is supplied because the in-place multiplication would overwrite the contents pointed to by the input matrices' data pointers.
This PR makes the `phaseCorrelate()` function use separate storage for applying the window. This keeps the inputs read-only (while keeping the path behavior the same as the padded case). This PR also adds a regression test for DFT-optimal and padded sizes with `CV_32F` and `CV_64F` types. The test cases include input/window preservation, ROIs, same source headers, and equivalent shift/response results.
### 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
imgcodecs: validate animation encoding parameter lists - #30282
`imwriteanimation()` and `imencodeanimation()` forward encoding parameters without the structural checks used by all the ordinary image encoding APIs.
This PR adds the same key/value-pair and maximum-count check before the functions call the animation encoder. It also adds a test that checks odd-length and over-limit parameter lists are rejected while empty and valid parameter lists still encode and decode correctly.
Related work: #22830 and #27769.
### 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
- [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
Merge pull request #30210 from Kumataro:validateAvailableCodecs
imgcodecs(tiff): validate codec availability - #30210
If a specified compression schema is not available, fallback to LZW (or NONE if LZW is also unavailable).
(e.g. currently bundled libtiff is not configured to support LZMA, ZSTD, and WEBP compression.)
### 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
imgproc: fix out-of-bounds read in OpenCL color kernels for 3-channel input 🤖🤖🤖 - #30180
YUV2RGB, RGB2YCrCb, YCrCb2RGB and the PIX_PER_WI_X != 2 path of
RGB2YUV_YV12_IYUV load each source pixel with vload4 but only use the
first three components. With SCN == 3 the load of the last pixel reads
one element past the end of the source buffer, which may result in a
GPU page fault.
Use vload3, as RGB2YUV already does, and drop the now unused
DATA_TYPE_4 macro.
The same issue is fixed in RGB2XYZ, XYZ2RGB, BGR2Lab, Lab2BGR, RGB2HSV,
HSV2RGB, RGB2HLS, HLS2RGB and RGB2RGB5x5, which load each source pixel
with vload4 but only use the first three components when SCN == 3.
### 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
Adding IMWRITE_TIFF_COMPRESSION_LEVEL - #30165
For some compression schemes (DEFLATE, ZSTD), libtiff supports a TIFFTAG_ZIPQUALITY. This PR adds an IMWRITE_TIFF_COMPRESSION_LEVEL param to set it.
- [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
I don't know what kind of automatic tests could be relevant.
I just checked that
1) the param is honoured
2) for some basic mats, level 1 gives lower compression than level 9
3) level -1 (default) gives a compression ratio between levels 1 and 9 (actually seems to be 6, as expected)
But I am not sure that 2) and 3) are generally guaranteed by the compression scheme for any data, so is it relevant to make a test assert on that ?
video: fix TrackerVit input scalefactor computed as Scalar - #30168Fixes#30164
### Problem
`TrackerVitImpl` computes the input normalisation as
i2bp.scalefactor = (1.0 / parameters.stdvalue) * (1 / 255.0);
`operator/(double, Scalar)` is the quaternion inverse (`conj(b) * a / |b|^2`), not an elementwise reciprocal. With the default `stdvalue = (0.229, 0.224, 0.225)` the applied scalefactor is `(0.00586, -0.00573, -0.00576)` instead of `(0.01712, 0.01751, 0.01743)`: channels 1 and 2 are sign-flipped and all three are about 1/3 of the intended magnitude. This was introduced in 4.11 when the elementwise `(dst - mean) / std` was replaced with `Image2BlobParams`.
### Fix
Compute `1 / (255 * std)` per channel in a small helper used by both constructors. A zero std entry (the unused 4th channel by default) maps to 0.
### Tests
`vittrack.accuracy_vittrack` on the `tracking/bag` sequence, measured locally on macOS ARM64 (4.x and 5.x):
| | min IoU | mean IoU |
|---|---|---|
| before | 0.642 | 0.757 |
| after | 0.682 | 0.776 |
On other CI platforms (x64, Windows, no-HAL) the minimum IoU with the fix is 0.658, so the existing 0.64 threshold is kept.
### 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
RVV: add fused HAL implementation for rotate - #30057
## Pull Request Readiness Checklist
See details at [https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request](https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request)
- [x] I agree to contribute to the project under the 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 (`4.x`).
- [x] Accuracy tests are included and performance results are provided below.
## Summary
This PR adds an RVV HAL implementation for `cv_hal_rotate90` and fuses the transpose and flip operations used by 90-degree and 270-degree rotations into a single vectorized pass.
The previous path composes transpose and flip operations, which requires an intermediate image and additional memory traffic. The new RVV path loads several source rows, builds RVV vector tuples, and writes directly to the final rotated positions with strided segmented stores.
## Implementation details
- Registers `cv_hal_rotate90` in the RISC-V RVV core HAL.
- Processes 1-, 2-, and 8-byte elements in blocks of eight source rows using `vssseg8e8`, `vssseg8e16`, and `vssseg8e64`.
- Processes 4-byte elements in blocks of four source rows using `vssseg4e32`.
- Uses positive or negative destination strides to implement clockwise and counter-clockwise rotation without a separate flip pass.
- Uses dynamic VL and strided vector stores for remaining rows and non-multiple tails.
- Supports padded/non-contiguous source rows through `src_step` and `dst_step`.
- Returns `CV_HAL_ERROR_NOT_IMPLEMENTED` for aliased input/output and unsupported element sizes, preserving the existing OpenCV fallback behavior.
- Keeps the existing RVV flip path for 180-degree rotation when safe.
- For 1-byte 180-degree rotation with `VLMAX > 256`, uses 16-bit gather indices with `vrgatherei16` to avoid index wraparound in the existing 8-bit gather path.
- Includes compatibility helpers for Clang versions earlier than 18 that do not provide the required vector tuple creation intrinsics.
The directly accelerated total element sizes are 1, 2, 4, and 8 bytes. Other sizes, including common 3- and 6-byte pixel formats, fall back to the existing implementation.
## Test environment
```text
Build type: Release
Compiler: GCC 14.2.0
ISA flags: -march=rv64gcv
RISCV_RVV_SCALABLE: ON
CPU_BASELINE_REQUIRE: RVV
QEMU: 8.2.2, RVV 1.0
```
## Accuracy tests
The new `Core_Rotate.OddSizesAndPaddedRows` test and the existing randomized rotate test passed under QEMU RVV at VLEN 128, 256, 512, and 1024.
## Performance tests
Performance was measured with `opencv_perf_core` under the environment described above. Detailed performance results are provided in the comment below.
These measurements are intended to show the relative difference between identical baseline and optimized builds under QEMU. Absolute performance should be confirmed on RISC-V hardware.
fix(python): set module metadata on generated functions - #30135Fixes#19349.
Generated Python functions such as `cv2.GaussianBlur` expose `__module__ = None`, so `inspect.getmodule()` returns `None`.
Pass the defining module name to `PyCFunction_NewEx` during registration. The existing `PySafeObject` wrapper manages the string reference. Function definitions, call flags, `__self__` and namespace ownership stay unchanged.
The tests cover both expressions from the ticket and module lookup, native-callable classification and pickle identity for the root, `cv2.utils` and `cv2.utils.nested`. The expected ticket output is:
```text
cv2
<built-in function GaussianBlur>
```
CPython represents native extension functions as `BuiltinFunctionType`, including `math.sin`. This patch preserves that representation while supplying the missing module metadata. See the [Python C API documentation](https://docs.python.org/3.13/c-api/structures.html#c.PyCFunction_Type).
### Validation
- Compiled isolated checks using the pristine and patched `createSubmodule` and `init_submodule` code and the unchanged `PySafeObject` wrapper. Root and nested call, constant, native type, representation and pickle controls pass on both. The pristine module assertion fails with `None`; patched module metadata and `inspect.getmodule()` pass. These checks use an echo callback and validate registration, rather than an OpenCV kernel.
- The ticket regression fails with `None != 'cv2'` against the installed OpenCV 4.12.0 binary. Three existing namespace and class-alias tests and four native-function representation controls pass against that binary and Python's standard library.
- `py -3.13 -m py_compile modules/python/test/test_misc.py` and `git diff --check` pass.
I have not built the full checkout locally. The [current-head CI workflow](https://github.com/opencv/opencv/actions/runs/37276602842) is awaiting maintainer approval (`action_required`) with no jobs yet. The updated binding tests have not run in CI. On the previous head, `8600aa69`, the Python suite reported 291 tests with 18 skips and `test_function_module` passed. The new ticket regression was added afterward, so those results do not validate it. An earlier macOS x64 native stitching test aborted with exit 134 outside this patch; its maintainer-triggered rerun was queued before this update.
### Pull Request Readiness Checklist
See 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
The regressions use existing Python functions and require no external test data or performance benchmark.
- The feature-documentation and sample-build item does not apply to this metadata bug fix.
### AI assistance disclosure
AI assistance disclosure: AI-assisted development tools were used during investigation and implementation. The reported tests were run against the final diff.
python: mark documented None output arrays as optional in typing stubs 🤖🤖🤖 - #30139Fixes#30138
The generated Python stubs type several output arrays as required, although OpenCV's own Python samples and tutorials pass `None` for them and the function allocates the output. These arrays are `InputOutputArray`/`OutputArray` parameters without a C++ default, so the stub generator does not add `| None`. As a result, mypy rejects correct code with `No overload variant ... matches [call-overload]`.
This PR adds `make_optional_arg` entries to `NODES_TO_REFINE` in `modules/python/src2/typing_stubs_generation/api_refinement.py`, the same approach as #28470 (`calibrateCamera`) and #27564:
| Function | Argument |
|---|---|
| `calcOpticalFlowPyrLK` | `nextPts` |
| `calcOpticalFlowFarneback` | `flow` |
| `normalize` | `dst` |
| `kmeans` | `bestLabels` |
| `drawKeypoints` | `outImage` |
| `drawMatches` | `outImg` |
| `drawMatchesKnn` | `outImg` |
`None` is only valid at runtime when the corresponding flag is not set (`OPTFLOW_USE_INITIAL_FLOW`, `KMEANS_USE_INITIAL_LABELS`, `DrawMatchesFlags_DRAW_OVER_OUTIMG`). Like `distCoeffs` in #28470, the change only widens the accepted type and does not change bindings or runtime behaviour.
### Verification
- I ran `gen2.py` from this branch and from `4.x` (62587ae) using the CMake-generated `gen_python_config.json`. The only differences in the generated `cv2/__init__.pyi` are 16 signatures (Mat and UMat overloads for each function; `drawMatches` has two C++ overloads). In each one, the listed argument changes from `cv2.typing.MatLike` / `UMat` to `... | None`. With a fixed `PYTHONHASHSEED` no other file differs; without it, the import order in `cv2/typing/__init__.py` varies from run to run because `generation.py` iterates a set, independently of this change.
- mypy 2.4.0 (MYPYPATH pointing at the generated stubs) on the 7 calls from #30138, for example `cv2.calcOpticalFlowPyrLK(prev, curr, pts, None)` and `cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX)`: all 7 fail with `call-overload` on the base stubs, and mypy reports no errors for these calls on the patched stubs (the generated stubs have some pre-existing internal errors, unchanged by this PR). The same calls run correctly with `opencv-python-headless` 4.14.0.94 and 5.0.0.93.
- No C++ or binding code changes. No regression test is added, because the repository has no existing test for the stub generator or `api_refinement.py` to extend.
_Prepared with AI assistance (Claude Code); I reviewed the change and the verification results._
**Update:** Added a second commit: `NODES_TO_REFINE` entries whose function, class or namespace is absent from the build (e.g. `video` or `calib3d` disabled via `BUILD_LIST`) are now skipped instead of aborting stub generation, as the `dnn`/`cuda` refinements already do. This also fixes the pre-existing failure for builds without `calib3d`. A wrong argument name in a present function still raises `RuntimeError`; a misspelled function name is now skipped like an absent one. Builds without `features2d` still fail for a separate reason (the `Feature2D` aliases in `predefined_types.py`), which I'll address in a follow-up.
### 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
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Fix int32 to double precision loss on ARM NEON - #30115
Fixes https://github.com/opencv/opencv/issues/30114
int32 to float64 conversion on **NEON went through a lossy int32 -> float32 -> float64 round trip**. float32's 24-bit mantissa silently corrupts any value above 2^24, causing `BigData_Imgproc_DistanceTransform.large_image_12218` to fail on ARM64 NEON builds.
Added a directed test (`test_cvt64_int32_precision`) covering large int32 magnitudes on both halves of the register, and confirmed the existing `BigData_Imgproc_DistanceTransform.large_image_12218` test now passes.
### 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
With hardware decoding, retrieveFrame() downloads the GPU frame into a new
AVFrame with av_hwframe_transfer_data(). That call copies the pixel data
only: colorspace, color_range, color_primaries, color_trc and
chroma_location are left unspecified in the system memory copy.
With swscale >= 8.12.100 the color conversion goes through
sws_scale_frame(), which configures itself from the properties of the source
frame. Given unspecified properties it falls back to BT.601 limited range, so
hardware-decoded frames are converted with the wrong matrix whatever the
stream signals, and full range streams additionally lose contrast. Software
decoding is not affected, the decoder output carries the properties.
fftools/ffmpeg_dec.c handles this by calling av_frame_copy_props() right
after the transfer; do the same. A failure is only logged: it can only be an
allocation failure on side data, and the picture itself is still valid.
With swscale < 8.12.100 the conversion context is initialized without the
frame properties, so this change has no effect on that path.
Measured on Windows x64 with the OpenCV 5.0.0 FFmpeg wrapper built by the
opencv_3rdparty MinGW recipe against FFmpeg n8.1.3 (libswscale 9.5.103),
D3D11VA decoding, on two synthetic BT.709 H.264 samples:
ffmpeg -f lavfi -i testsrc2=size=1280x720:rate=30 -t 2 -c:v libx264 \
-pix_fmt yuv420p -color_range tv -colorspace bt709 \
-color_primaries bt709 -color_trc bt709 bt709_tv.mp4
ffmpeg -f lavfi -i testsrc2=size=1280x720:rate=30 -t 2 -c:v libx264 \
-pix_fmt yuvj420p -color_range pc -colorspace bt709 \
-color_primaries bt709 -color_trc bt709 bt709_pc.mp4
Frame 0 is compared with a reference built from the same static FFmpeg
libraries: software decode, lossless repack to NV12 (the D3D11VA download
format), av_frame_copy_props(), then sws_scale_frame() to BGR24 exactly as
retrieveFrame() does.
sample before (mean / max abs diff) after
bt709_tv.mp4 7.424 / 94 bit-exact
bt709_pc.mp4 3.286 / 101 bit-exact
Before the patch the output is bit-exact with the same reference built
without the frame properties, which confirms the cause. Software decoding
output is unchanged (bit-exact before and after). Two real H.264 recordings
(BT.709, full and limited range) behave the same way.
Hardware and software decoding still do not produce identical pictures after
this patch: swscale converts NV12 and yuv420p differently around sharp chroma
edges. That difference exists with the same properties outside OpenCV too
and is not addressed here.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
video: add validation for OPTFLOW_USE_INITIAL_FLOW in calcOpticalFlowFarneback - #30086
Add explicit parameter check for initial flow in `calcOpticalFlowFarneback`.
When `OPTFLOW_USE_INITIAL_FLOW` flag is passed but the `flow` matrix is empty/missing, this provides a descriptive runtime error instead of non-deterministic behavior or garbage values.
Fixes#7276.
### 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 (`4.x`).
- [x] There is a reference to the original bug report (#7276).
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable.
- [x] The feature is well documented and sample code can be built with the project CMake.
calib3d: support non-contiguous calibration point vectors - #30013
calibrateCamera rejects valid non-contiguous point-vector Mats due to the calibration data collector validating them with checkVector's default continuity requirement and then assuming linear contiguous storage. As a result, an Nx1 Point3f/Point2f ROI fails while an equivalent continuous matrix with same shape/type/values succeeds.
This PR adds a test comparing continuous and ROI-backed calibration inputs, with the test verifying equivalent RMS, camera matrix, and distortion coefficients, and that the caller's ROI backing data and padding are left unchanged. Allow non-contiguous point vectors during validation, and clone only non-contiguous inputs before the existing linear copy path. Continuous inputs are no-copy'd as is.
### 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
SequenceTypeNode and ClassTypeNode always format as _typing.Sequence[...]
and _typing.Type[...], but ContainerTypeNode only reports the typing
import as required when compatible_to_runtime_usage is set. Stubs for
modules that use these nodes without any other _typing usage (e.g.
cv2/videoio_registry) reference _typing without importing it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
add ARMPL HAL backend for cv::invert(DECOMP_LU) - #30035
## Summary
- Adds an ARM Performance Library (ArmPL) HAL backend for cv::invert under DECOMP_LU (cv_hal_LU32f / cv_hal_LU64f), replacing OpenCV's default LU decomposition path with ArmPL's LAPACKE_sgesv / LAPACKE_dgesv for float and double matrices on AArch64.
## Changes
**hal/armpl/include/armpl_hal_core.hpp:**
- Declare armpl_hal_LU32f / armpl_hal_LU64f and register them as cv_hal_LU32f / cv_hal_LU64f.
hal/armpl/src/armpl_hal_core.cpp:
- Add armpl_lu() function (works for both float and double), that does the LU decomposition of the matrix:
- If a right-hand side b is given, then LAPACKE_sgesv/dgesv is called.
- If no right-hand side is given, it only factorizes the matrix using LAPACKE_sgetrf/dgetrf
- Fall back to OpenCV's default (non-HAL) implementation for small matrices (m < 100).
## Performance Benchmarks
<img width="1001" height="105" alt="image" src="https://github.com/user-attachments/assets/ba18378c-24da-4d20-9819-3b4398cad6e2" />
<img width="1002" height="105" alt="image" src="https://github.com/user-attachments/assets/ff33d421-b95d-4fca-aad0-ab7bc035d49b" />
<img width="999" height="108" alt="image" src="https://github.com/user-attachments/assets/d4abb57e-6be0-4ea1-9894-d30074c9429c" />