Fix typos in tutorial documentation #29299
This PR fixes spelling typos across several tutorial documentation files (dnn, calib3d, objdetect, app, js_tutorials), including `export=dowload` -> `export=download` in the DNN text-spotting tutorial's Google Drive URLs.
Documentation-only change; no functional code is affected.
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 (4.x).
[x] Documentation-only change; no accuracy/performance tests or opencv_extra patch are applicable.
Improving Parallelism and Memory Access Efficiency for Hough Transform Accumulator #29059
### 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
# [Optimization] Improving Parallelism and Memory Access Efficiency for Hough Transform Accumulator
## Overview / Motivation
The original implementation mainly rely on single‑threaded nested loops, which do not fully utilize the computational power of modern multi‑core CPUs. There is also room for improvement in memory access patterns and branch prediction. **Without altering any core mathematical logic or ensuring result consistency**, this work improves the execution efficiency of these two processes by introducing `cv::parallel_for_` and refactoring data access patterns.
---
## Detailed Changes
* **Original Code Analysis**: The original code uses a double loop – the outer loop scans the image for edge points (`if image[...] != 0`), and the inner loop iterates over all angles, computes the radius, and writes to the global `accum` array. This pattern is hard to parallelize directly because different threads writing to the same accumulator would cause **data races**. Moreover, the sparse conditional branch inside the loop is extremely unfriendly to CPU branch prediction.
* **Optimization Strategy (Sparse Extraction → Parallel over Angles)**:
1. **Sparse Feature Extraction**: First, pre‑scan the image in a single thread, extract the coordinates (`x`, `y`) and values of all non‑zero pixels (edge points) into a contiguous `std::vector` (pre‑allocate 10% of the image size to reduce dynamic reallocation overhead).
2. **Switch the Parallel Dimension**: Instead of splitting the image region, change the parallelization dimension to **angle (`numangle`)**. Use `cv::parallel_for_` to assign different angle ranges to different threads.
3. **Conflict‑free Memory Writes**: Because the `accum` array is strictly partitioned by angle `n` in memory, threads assigned to different angles write to completely non‑overlapping memory blocks in the global `accum`.
---
## Correctness Testing
Correctness tests are based on the provided `opencv_test`. For the Hough tests, no failing test cases were observed.
---
## Performance Benchmarks
> The following tests were run on Intel(R) Core(TM) i9‑14900HX @ 2.2GHz / Windows 11 (WSL: Ubuntu) with GCC 13.3.0.
Using `opencv_perf` tests that include Hough, the results are as follows:
| Test Case | 1st mean | 5th mean | Diff |
|-----------|----------|----------|------|
| `PerfHoughCircles.Basic` | 4.75 | 4.91 | +3.4% |
| `PerfHoughCircles2.ManySmallCircles` | 56.76 | 59.37 | +4.6% |
| `PerfHoughCircles4f.Basic` | 4.14 | 4.03 | -2.7% |
#### II. `OCL_HoughLines` (Standard Hough Line, OCL wrapper, actually executed on CPU)
| Parameters (size, rho, theta) | 1st mean | 5th mean | Diff |
|-------------------------------|----------|----------|------|
| (640×480, 0.1, 0.01745) | 2.57 | 3.21 | +24.9% |
| (640×480, 1, 0.1) | 0.18 | 0.21 | +16.7% |
| (1920×1080, 0.1, 0.01745)|12.27 |15.55 | +26.7% |
| (1920×1080, 1, 0.1) | 0.69 | 0.99 | +43.5% |
| (3840×2160, 0.1, 0.01745)|28.43 |34.78 | +22.3% |
| (3840×2160, 1, 0.1) | 2.15 | 3.51 | +63.3% |
#### III. `OCL_HoughLinesP` (Probabilistic Hough Line)
| Image and parameters (rho, theta) | 1st mean | 5th mean | Diff |
|------------------------------------|----------|----------|------|
| pic5.png, 0.1, 0.01745 | 1.20 | 1.22 | +1.7% |
| pic5.png, 1, 0.01745 | 1.03 | 0.92 | -10.7% |
| a1.png, 0.1, 0.01745 | 8.71 | 9.32 | +7.0% |
| a1.png, 1, 0.01745 | 6.29 | 6.68 | +6.2% |
#### IV. Standard Hough Line (CPU implementation, non‑OCL) `Image_RhoStep_ThetaStep_Threshold_HoughLines`
| Parameters (image, rho, theta, thresh) | 1st mean | 5th mean | Diff |
|-----------------------------------------|----------|----------|------|
| pic5.png, 1, 0.01, 0.5 | 2.19 | 0.82 | **-62.6%** |
| pic5.png, 10, 0.01, 0.5 | 2.08 | 0.53 | **-74.5%** |
| pic5.png, 1, 0.1, 0.5 | 0.24 | 0.15 | -37.5% |
| a1.png, 1, 0.01, 0.5 | 16.06 | 2.65 | **-83.5%** |
| a1.png, 10, 0.01, 0.5 | 17.05 | 1.92 | **-88.7%** |
| a1.png, 1, 0.1, 0.5 | 1.82 | 1.00 | -45.1% |
#### V. Floating‑Point Hough Line (`...HoughLines3f`)
| Parameters (image, rho, theta, thresh) | 1st mean | 5th mean | Diff |
|-----------------------------------------|----------|----------|------|
| pic5.png, 1, 0.01, 0.5 | 1.97 | 0.86 | **-56.3%** |
| pic5.png, 10, 0.01, 0.5 | 1.66 | 0.54 | **-67.5%** |
| a1.png, 1, 0.01, 0.5 | 18.52 | 2.59 | **-86.0%** |
| a1.png, 10, 0.01, 0.5 | 16.30 | 2.05 | **-87.4%** |
| a1.png, 1, 0.1, 0.5 | 1.72 | 0.97 | -43.6% |
### Conclusion
- **Circle detection, probabilistic Hough line**: Differences between the two runs are very small (within ±11%), indicating stable performance.
- **`OCL_HoughLines`**: The parallel test is generally 10%~63% slower than the serial one, but still within a reasonable fluctuation range. Special handling was attempted but did not bring significant improvement and slightly reduced the gains in the subsequent two groups, so it was left unchanged after comprehensive consideration.
- **CPU standard Hough line (non‑OCL)**: The parallel test is significantly faster than the serial one (up to 88% faster), demonstrating that parallel optimization can bring obvious improvements.
By the way at last, I am extremely grateful to the maintainers for helping me test the last PR. However, since I was unable to obtain the development board, I was unable to continue modifying the previous RVV optimization.
Fix speed regression in Aruco identify #29267
### 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
samples: add color-coded bounding boxes for multi QR code detection #29281
Improves the existing qrcode.py sample by adding color-coded bounding boxes when multiple QR codes are detected simultaneously.
Previously all QR codes were drawn with the same green color, making it hard to distinguish between them visually.
This change adds a QR_COLORS palette so each detected QR code gets a unique color, improving visual clarity for multi-QR detection.
Co-authored-by: Ayush Gupta <gupta.ayushg@gmail.com>
core(opengl): fix memory leak in OpenCL extensions gathering #28981
## Problem
Fixes#28980
In `modules/core/src/opengl.cpp`, inside `initializeContextFromGL()`, a `char[]` buffer is allocated to query OpenCL device extensions:
```cpp
extensions = new char[extensionSize];
status = clGetDeviceInfo(..., extensions, &extensionSize);
if (status != CL_SUCCESS)
continue; // leaks `extensions`
```
When `clGetDeviceInfo()` fails, `continue` skips the corresponding `delete[]` on the success path, causing the allocated buffer to leak.
Additionally, the `catch (...)` block also bypasses cleanup, so any thrown exception leaks the buffer as well.
## Fix
Replace the raw `char*` allocation with `std::unique_ptr<char[]>`.
This ensures the buffer is automatically released on all exit paths, including:
- normal execution
- early `continue`
- exception handling paths
## 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`).
- [x] There is a reference to the original bug report and related work, if applicable.
- [x] Accuracy/performance tests and test data in `opencv_extra` are included, if applicable.
- [x] The feature/change is documented and sample code can be built with the project CMake configuration, if applicable.
imgproc: optimize EMD (Earth Mover's Distance) solver performance #29194
### imgproc: optimize EMD solver performance using O(V) spanning tree traversal
---
This PR significantly optimizes the performance of the Earth Mover's Distance (`cv::EMD`) solver in `modules/imgproc/src/emd_new.cpp`.
Specifically, it refactors the dual-variable calculation in `EMDSolver::findBasicVars()` from a naive $O((N+M)^2)$ linked-list scanning approach to an optimized $O(N+M)$ BFS tree traversal utilizing existing adjacency lists, leading to a massive speedup.
---
#### Technical Details & Core Bottleneck Fixed
1. **Algorithmic Complexity Reduction in `findBasicVars()`:**
- **Before**: The original implementation solved the dual variables $u_i$ and $v_j$ by traversing the entire unmarked rows (`u0_head`) or columns (`v0_head`) linked-lists and invoking `getIsX(i, j)` inside nested loops to find connected basic variables. This resulted in an $O((N+M)^2)$ complexity per simplex iteration. For a scale of $2000 \times 2000$, this performed up to $16,000,000$ operations per iteration.
- **After**: Since `EMDSolver` already maintains the adjacency lists of the basic variables tree (`rows_x` and `cols_x`), we can traverse the spanning tree in linear time. This PR implements a dual-queue BFS tree traversal. The complexity per iteration is drastically reduced to $O(N+M)$, performing at most $4000$ operations per iteration.
2. **Cache Locality & Pointer-Chasing Elimination:**
- Replaced pointer-chasing on dynamically-allocated linked lists with contiguous, stack-allocated array queues (`cv::AutoBuffer`), significantly improving CPU L1/L2 cache hit rates and enabling hardware prefetching.
---
#### Performance Benchmarks
Below is the benchmark comparison evaluated on a standard CPU.
#### Test 1: dims = 64
| Scale ($N, M$) | Original EMD (ms) | Optimized EMD (This PR) | Speedup |
| :--- | :--- | :--- | :--- |
| **100** | 5.473 | 3.419 | **1.60x** |
| **500** | 381.871 | 244.355 | **1.56x** |
| **1000** | 1893.053 | 1369.016 | **1.38x** |
| **2000** | 11387.792 | 8331.221 | **1.37x** |
#### Test 2: dims = 3
| Scale ($N, M$) | Original EMD (ms) | Optimized EMD (This PR) | Speedup |
| :--- | :--- | :--- | :--- |
| **100** | 4.433 | 3.042 | **1.46x** |
| **500** | 365.762 | 259.735 | **1.41x** |
| **1000** | 1989.400 | 1421.952 | **1.40x** |
| **2000** | 12731.836 | 7952.210 | **1.60x** |
*(Note: The exact performance figures may vary slightly depending on the compiler and test machine.)*
---
#### Verification
- All existing tests in `opencv_test_imgproc` (including EMD tests) pass successfully. No regressions were introduced.
---
### 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
The relative neighborhood graph (RNG) is a subgraph of the Delaunay
triangulation, so only Delaunay edges are candidates for RNG membership.
The previous implementation tested all N^2 pairs against all N points,
giving O(N^3). The new implementation builds the Delaunay triangulation
with Subdiv2D (O(N log N)), then checks only those ~3N edges for the RNG
lune-emptiness condition, reducing computeRNG to O(N^2) in the worst case
and much better in practice for regular grids.
Added synthetic-grid accuracy tests for both symmetric and asymmetric
patterns across several sizes, and a perf test parameterized by grid size.
core: fix inverted continuity check in cvReshapeMatND() #29132
### Pull Request Readiness Checklist
See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request
- [√] I agree to contribute to the project under Apache 2 License.
- [√] 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
imgproc: fix missing tipLength validation in arrowedLine #29191
### Pull Request Description
**Issue/Bug:**
Currently, the `cv::arrowedLine` function in `modules/imgproc/src/drawing.cpp` lacks boundary validation for the `tipLength` parameter. Passing an invalid ratio (e.g., negative values or values > 1.0) leads to mathematically distorted arrowhead coordinates being silently passed to the underlying `line()` drawing function, resulting in severely deformed output without any warning.
**Solution:**
Added a `CV_Assert` to enforce the geometric contract of `tipLength`, ensuring it strictly falls within the logical bounds `(0.0, 1.0]`. This adheres to the fail-fast principle and prevents silent geometric failures.
**Testing:**
Successfully built the project locally and added a dedicated regression test (`arrowedLine_tipLength_validation`) using Google Test in `modules/imgproc/test/test_drawing.cpp`. Tested with boundary values (e.g., `tipLength = 1.5` and `-0.5`), and the assertion correctly intercepts the invalid parameters before rasterization.
*(Note: This contribution is part of a university engineering project evaluating open-source workflow and C++ robustness.)*
Enable collectContours in detect_blob.cpp and draw the per-blob
contours returned by getBlobContours(), so the sample exercises the
public contour-collection API added in #21942.
Refs #25904
The first conversion to Lab or Luv lazily builds a softfloat lookup table, and that build was doing about 108000 software emulated pow calls plus a fully serial 33x33x33 cube loop. This memoizes applyGamma over the 33 grid values and runs the cube loop with parallel_for_, cutting the first call from around 110 ms to around 25 ms on my machine. The per point computation is unchanged so the tables stay bit exact.
Defer the u8→i16 widening (vzext) in the pre-screen phase until after
the quick-reject check passes. This avoids 5 unnecessary widen
operations per pixel-strip when the pre-screen rejects (which happens
~70-80% of the time at the default threshold=20).
The approach uses u8mf2 (same VL as i16m1) for the pre-screen
comparison with vssubu/vsaddu for bounds and vmsgtu for unsigned
comparison. When the pre-screen passes, the already-loaded u8mf2
variables are widened to i16m1 for the score computation, reusing
the same data without redundant memory loads.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The is_simple check used mask.empty() after the default mask
had already been created, making it always false. This caused
the fast path (floodFill_CnIR) to be dead code — every call
went through the slower gradient-based path (floodFillGrad_CnIR).
Fix: save _mask.empty() result before auto-creating the default
mask and use it for the is_simple check.
Reenable ICV and fix#29166#29183
Fixing https://github.com/opencv/opencv/issues/29166 and return back the 2026.0.0 ICV.
Tests are passed locally on Windows machine. Feel free to check if they are passed in bigger test systems.
### 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
imgcodecs: fix Apple conversions build without AVFoundation #29138Fixes#28553.
This PR fixes Apple imgcodecs conversion builds when AVFoundation is disabled or unavailable on older macOS SDKs.
Changes:
- Guard AVFoundation import with HAVE_AVFOUNDATION.
- Use older macOS-compatible framework imports when ImageIO is unavailable.
- Add __bridge compatibility for older Objective-C++ compilers.
- Use NSMakeSize for older macOS instead of passing CGSize to NSImage API.
Testing:
- Not tested locally: no macOS environment available.
- Patch follows the fix confirmed in #28555 discussion.
Fixing python wrapper around ECCParameters to include itersPerLevel #29148
### 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
### 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
<!-- Note!!! If you are an automated agent, we have a special process for you: add 🤖🤖🤖 to the end of the PR title. -->
### Summary
This PR improves SIMD coverage for masked `cv::accumulate()` on 4-channel images.
The existing masked accumulate SIMD implementation has special paths for `cn == 1` and `cn == 3`, while 4-channel images fall back to the general implementation. This PR adds `cn == 4` SIMD paths using OpenCV Universal Intrinsics.
Compare link:
https://github.com/opencv/opencv/compare/4.x...feitianduowen:opencv:4.x
Modified files:
- `modules/imgproc/src/accum.simd.hpp`
- Add masked `cn == 4` SIMD paths for:
- `CV_32FC4 -> CV_32FC4`
- `CV_8UC4 -> CV_32FC4`
- `modules/video/test/test_accum.cpp`
- Add deterministic correctness regression tests for the new masked 4-channel accumulate paths.
- `modules/imgproc/perf/perf_accumulate.cpp`
- Add performance coverage for masked 4-channel accumulate.
imgproc: add SIMD paths for masked 4-channel accumulate #29094
### Implementation
The new SIMD branches are added in:
- `modules/imgproc/src/accum.simd.hpp`
They handle:
- `src`: `CV_32FC4`, `dst`: `CV_32FC4`, `mask`: `CV_8UC1`
- `src`: `CV_8UC4`, `dst`: `CV_32FC4`, `mask`: `CV_8UC1`
For the `CV_32FC4` path, the implementation uses `v_load_deinterleave`, applies the pixel mask to all 4 channels, accumulates into `dst`, and stores the result with `v_store_interleave`.
For the `CV_8UC4 -> CV_32FC4` path, the implementation loads 4 interleaved uchar channels, applies the pixel mask, widens the values to float, accumulates into `dst`, and stores the results back as interleaved `CV_32FC4`.
The masked SIMD block is guarded with:
```cpp
if (x <= len - cVectorWidth)
{
...
}
```
This check ensures that SIMD setup and vector operations are only executed when at least one full vector iteration can run. For very small inputs or tail-only cases, the function skips SIMD initialization and lets the existing scalar fallback handle the data through `acc_general_(src, dst, mask, len, cn, x)`.
This keeps tail handling unchanged and avoids unnecessary SIMD initialization when the vector loop would be skipped.
### Accuracy tests
Added a deterministic regression test in:
* `modules/video/test/test_accum.cpp`
New test:
```bash
Video_Acc.accuracy_32FC4_masked_cn4
Video_Acc.accuracy_8UC4_to_32FC4_masked_cn4
```
Test commands:
```bash
opencv_test_video --gtest_filter=Video_Acc.accuracy_32FC4_masked_cn4
opencv_test_video --gtest_filter=Video_Acc.accuracy_8UC4_to_32FC4_masked_cn4
opencv_test_video --gtest_filter="Video_Acc.*:Video_AccSquared.*:Video_AccProduct.*:Video_RunningAvg.*"
```
The filtered accumulate-related tests passed locally.
I added dedicated deterministic tests instead of only extending the existing randomized accumulate tests because this PR only changes the masked `cv::accumulate()` paths for specific 4-channel type combinations. It does not add `cn == 4` SIMD coverage for `accumulateSquare`, `accumulateProduct`, or `accumulateWeighted`.
The existing base accumulate tests are shared by several accumulation functions. Extending the common randomized channel selection to include `cn == 4` would also affect tests for functions that are not optimized by this PR. The new deterministic tests directly cover the modified paths:
* `cv::accumulate(src, dst, mask)`
* `CV_32FC4 -> CV_32FC4`
* `CV_8UC4 -> CV_32FC4`
* `mask`: `CV_8UC1`
The test also covers small sizes and non-vector-multiple sizes, so both the new SIMD path and the existing scalar tail fallback are exercised.
### Performance tests
Added performance coverage in:
* `modules/imgproc/perf/perf_accumulate.cpp`
Perf command:
```bash
opencv_perf_imgproc --gtest_filter="*AccumulateMask32FC4*" --perf_min_samples=1000 --perf_force_samples=1000
opencv_perf_imgproc --gtest_filter="*AccumulateMask8UC4To32FC4*" --perf_min_samples=1000 --perf_force_samples=1000
```
Test environment:
* Release build
* AVX2 enabled
* IPP disabled
* OpenCL disabled
* Windows MinGW build
Performance results:
`CV_32FC4 -> CV_32FC4`
| Size | Before median | After median | Speedup |
| --------- | ------------- | ------------ | ------- |
| 1920x1080 | 3.07 ms | 2.74 ms | 1.12x |
| 1280x720 | 0.84 ms | 0.73 ms | 1.15x |
| 640x480 | 0.17 ms | 0.16 ms | 1.06x |
| 320x240 | 0.04 ms | 0.04 ms | ~1.00x |
`CV_8UC4 -> CV_32FC4`
| Size | Before median | After median | Speedup |
| --------- | ------------- | ------------ | ------- |
| 1920x1080 | 6.09 ms | 1.75 ms | 3.48x |
| 1280x720 | 2.69 ms | 0.82 ms | 3.28x |
| 640x480 | 0.96 ms | 0.28 ms | 3.43x |
| 320x240 | 0.24 ms | 0.06 ms | 4.00x |
| 127x61 | 0.02 ms | 0.01 ms | 2.00x |
### Build and test commands
The following commands were run from Windows `cmd.exe`.
```sh
cmake -S . -B build_release -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON -DBUILD_PERF_TESTS=OFF -DBUILD_EXAMPLES=OFF -DWITH_IPP=OFF -DWITH_OPENCL=OFF -DCMAKE_C_FLAGS=-mstackrealign -DCMAKE_CXX_FLAGS=-mstackrealign
cmake --build build_release --target opencv_test_video -j 4
build_release\bin\opencv_test_video.exe --gtest_filter=Video_Acc.accuracy_32FC4_masked_cn4
build_release\bin\opencv_test_video.exe --gtest_filter=Video_Acc.accuracy_8UC4_to_32FC4_masked_cn4
build_release\bin\opencv_test_video.exe --gtest_filter=Video_Acc.*:Video_AccSquared.*:Video_AccProduct.*:Video_RunningAvg.*
```
Accuracy test commands passed locally.
For the performance comparison, I kept the new perf test in `modules/imgproc/perf/perf_accumulate.cpp` and only reverted `modules/imgproc/src/accum.simd.hpp` to measure the baseline. Then I restored the SIMD patch and measured the optimized version.
Baseline measurement:
```sh
git diff -- modules/imgproc/src/accum.simd.hpp > accum_cn4_simd.patch
git checkout -- modules/imgproc/src/accum.simd.hpp
mkdir perf_logs
cmake -S . -B build_perf_before -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=ON -DBUILD_EXAMPLES=OFF -DWITH_IPP=OFF -DWITH_OPENCL=OFF -DCMAKE_C_FLAGS=-mstackrealign -DCMAKE_CXX_FLAGS=-mstackrealign > perf_logs\before_cmake_config.txt 2>&1
cmake --build build_perf_before --target opencv_perf_imgproc -j 4 > perf_logs\before_build.txt 2>&1
build_perf_before\bin\opencv_perf_imgproc.exe --gtest_filter=*AccumulateMask32FC4* --perf_min_samples=1000 --perf_force_samples=1000 > perf_logs\before_perf.txt 2>&1
```
```sh
git diff -- modules/imgproc/src/accum.simd.hpp > accum_cn4_u8_simd.patch
git checkout -- modules/imgproc/src/accum.simd.hpp
cmake -S . -B build_perf_before_u8 -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=ON -DBUILD_EXAMPLES=OFF -DWITH_IPP=OFF -DWITH_OPENCL=OFF -DCMAKE_C_FLAGS=-mstackrealign -DCMAKE_CXX_FLAGS=-mstackrealign
cmake --build build_perf_before_u8 --target opencv_perf_imgproc -j 4
build_perf_before_u8\bin\opencv_perf_imgproc.exe --gtest_filter=*AccumulateMask8UC4To32FC4* --perf_min_samples=1000 --perf_force_samples=1000 > perf_logs\before_perf1.txt 2>&1
```
Optimized measurement:
```sh
git apply accum_cn4_simd.patch
cmake -S . -B build_perf_after -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=ON -DBUILD_EXAMPLES=OFF -DWITH_IPP=OFF -DWITH_OPENCL=OFF -DCMAKE_C_FLAGS=-mstackrealign -DCMAKE_CXX_FLAGS=-mstackrealign > perf_logs\after_cmake_config.txt 2>&1
cmake --build build_perf_after --target opencv_perf_imgproc -j 4 > perf_logs\after_build.txt 2>&1
build_perf_after\bin\opencv_perf_imgproc.exe --gtest_filter=*AccumulateMask32FC4* --perf_min_samples=500 --perf_force_samples=500 > perf_logs\after_perf.txt 2>&1
```
```sh
git apply accum_cn4_u8_simd.patch
cmake -S . -B build_perf_after_u8 -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=ON -DBUILD_EXAMPLES=OFF -DWITH_IPP=OFF -DWITH_OPENCL=OFF -DCMAKE_C_FLAGS=-mstackrealign -DCMAKE_CXX_FLAGS=-mstackrealign
cmake --build build_perf_after_u8 --target opencv_perf_imgproc -j 4
build_perf_after_u8\bin\opencv_perf_imgproc.exe --gtest_filter=*AccumulateMask8UC4To32FC4* --perf_min_samples=1000 --perf_force_samples=1000 > perf_logs\after_perf1.txt 2>&1
```
Performance comparison was measured by keeping the new perf tests and only reverting modules/imgproc/src/accum.simd.hpp for the baseline run.
`-mstackrealign` was used for the MinGW Windows build to avoid stack-alignment issues with AVX code generation during local testing.
### Notes
The implementation keeps the existing scalar fallback path unchanged. SIMD is used only for the newly covered masked `cn == 4` vectorizable part, and any remaining tail elements are still handled by `acc_general_()`.
The improvement is most visible on larger images. Small images are dominated by overhead and do not always show meaningful speedup.