Skip to content

OpenCV 5.x API coverage: photo, text, saliency, shape, superres, ximgproc gaps - #2052

Merged
shimat merged 2 commits into
mainfrom
codex/issue-2015-coverage-sweep
Jul 16, 2026
Merged

shimat merged 2 commits into
mainfrom
codex/issue-2015-coverage-sweep

Conversation

@shimat

@shimat shimat commented Jul 16, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • superres: wire up SuperResolution.OpticalFlow (the native bridge and P/Invoke declarations already existed; only the C# property body was missing)
  • shape: ShapeContextDistanceExtractor.GetCostExtractor/GetTransformAlgorithm (setters already existed, getters didn't)
  • ximgproc: findEllipses, RadonTransform, ScanSegment, ContourFitting (+ fourierDescriptor/transformFD/contourSampling), DisparityFilter/DisparityWLSFilter, SparseMatchInterpolator/EdgeAwareInterpolator/RICInterpolator
    • StereoMatcher gains a generic Ptr_get, needed because createRightMatcher returns a base-typed Ptr<StereoMatcher> and DisparityFilter.Filter takes a StereoMatcher-shaped confidence path
  • photo: ColorCorrectionModel (cv::ccm) plus its 7 enums (CcmType, ColorCheckerType, ColorSpace, LinearizationType, DistanceType, InitialMethodType), and gammaCorrection
  • text: the ER-filter pipeline (ERFilter, ERFilterCallback, computeNMChannels, detectRegions) and the non-Tesseract OCR decoders (OCRHMMDecoder, OCRBeamSearchDecoder, OCRHolisticWordRecognizer)

Two things were scoped out, both because the underlying C++ shape can't be marshaled safely, not because they were skipped for convenience:

  • ERStat and the ERStat-vector overloads of erGrouping/MSERsToERStats: ERStat is a component-tree node with raw internal parent/child/next/prev pointers, so it isn't safely representable as a marshaled vector element. detectRegions (implemented here) covers the same end-to-end grouping use case using Point-based regions instead, so nothing is lost in practice.
  • Implementing ERFilter::Callback / OCRHMMDecoder::ClassifierCallback / OCRBeamSearchDecoder::ClassifierCallback in managed code: this would require a native-to-managed virtual dispatch trampoline, which this repo has no existing precedent for. ERFilter/OCRHMMDecoder/OCRBeamSearchDecoder are still fully constructible via the file-based classifier overloads and via the various load*Classifier* factories (wrapped as opaque *ClassifierCallback handles).

Bug found and fixed along the way

While adding test coverage for StaticSaliencySpectralResidual.Write/Read, the test crashed the process (STATUS_STACK_BUFFER_OVERRUN). Root cause: cv::saliency::Saliency inherits cv::Algorithm virtually, so a raw pointer obtained as e.g. StaticSaliencySpectralResidual* is not the same address as the cv::Algorithm* the compiler would produce via the correct virtual-base adjustment. The generic core_Algorithm_write/read bridge (typed as cv::Algorithm*) was silently given the wrong pointer value for every saliency class that used it. Fixed by giving StaticSaliencySpectralResidual, StaticSaliencyFineGrained, MotionSaliencyBinWangApr2014, and ObjectnessBING their own write/read bridges that call write()/read() on the pointer at its correct native concrete type.

Testing

  • cmake --build src/build --config Release --target OpenCvSharpExtern
  • dotnet build src/OpenCvSharp/OpenCvSharp.csproj -c Release
  • dotnet test test/OpenCvSharp.Tests/OpenCvSharp.Tests.csproj -c Release (full suite: 1552 total, 1526 passed, 26 skipped, 0 failed — no regressions)
  • Added focused coverage for every new API surface (ColorCorrectionModelTest, ERFilterTest, OCRDecoderTest, plus additions to XImgProcTest, ShapeContextDistanceExtractorTest, SuperResTest, and the saliency Read/Write regression tests for the crash above)

Closes #2015

Summary by CodeRabbit

  • New Features
    • Added photo color-correction tooling: new enums and ColorCorrectionModel, plus Cv2.GammaCorrection.
    • Added OCR/text detection APIs: ERFilter + callbacks, ER/NM modes, HMM/beam-search/holistic-word decoders, and strongly typed OCR engine/page segmentation options.
    • Expanded ximgproc coverage with new algorithms/wrappers (ellipses, Radon transform, contour fitting, disparity filtering, scan segments, and sparse-match interpolators).
    • Added saliency model persistence (Write/Read) and shape/optical-flow enhancements.
  • Tests
    • Added/extended test coverage for the new photo, text/OCR, saliency, shape, super-resolution, and ximgproc APIs.

…ge sweep

Implements the coverage gaps identified in #2015:
- superres: wire up SuperResolution.OpticalFlow (native bridge already existed)
- shape: ShapeContextDistanceExtractor.GetCostExtractor/GetTransformAlgorithm
- ximgproc: findEllipses, RadonTransform, ScanSegment, ContourFitting
  (+ fourierDescriptor/transformFD/contourSampling), DisparityFilter/
  DisparityWLSFilter, SparseMatchInterpolator/EdgeAwareInterpolator/
  RICInterpolator (StereoMatcher gains a generic Ptr_get for the
  createRightMatcher/DisparityFilter.Filter overloads that return/accept it)
- photo: ColorCorrectionModel (ccm) plus its 7 enums, and gammaCorrection
- text: the ER-filter pipeline (ERFilter/ERFilterCallback, computeNMChannels,
  detectRegions) and the non-Tesseract OCR decoders (OCRHMMDecoder,
  OCRBeamSearchDecoder, OCRHolisticWordRecognizer), scoped to file/classifier-
  based construction - implementing ClassifierCallback/ERFilter::Callback in
  managed code would need a native->managed virtual dispatch trampoline this
  repo has no precedent for. ERStat and the ERStat-vector overloads of
  erGrouping/MSERsToERStats are skipped: ERStat is a tree-node struct with
  internal parent/child/sibling pointers that isn't safely marshalable as a
  vector element: detectRegions covers the same end-to-end use case with
  Point-based regions instead.

While adding StaticSaliencySpectralResidual.Write/Read coverage, found that
it (and every other saliency class: StaticSaliencyFineGrained,
MotionSaliencyBinWangApr2014, ObjectnessBING) crashed when calling
Algorithm.Write/Read: cv::saliency::Saliency inherits cv::Algorithm
*virtually*, so the raw pointer these classes hand to the generic
core_Algorithm_write/read bridge (typed as cv::Algorithm*) is not the same
address as the correctly-adjusted pointer the compiler would produce from
the concrete type. Fixed by giving all four classes their own write/read
bridge that calls write()/read() on the pointer at its native concrete type.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c166a72c-8406-4eba-aab0-e1c28f04f0b2

📥 Commits

Reviewing files that changed from the base of the PR and between 604cd3a and 5d8101a.

📒 Files selected for processing (12)
  • src/OpenCvSharp/Modules/text/OCRBeamSearchDecoder.cs
  • src/OpenCvSharp/Modules/text/OCRHMMDecoder.cs
  • src/OpenCvSharp/Modules/text/OCRHolisticWordRecognizer.cs
  • src/OpenCvSharp/Modules/ximgproc/DisparityWLSFilter.cs
  • src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj
  • src/OpenCvSharpExtern/text_ERFilter.h
  • test/OpenCvSharp.Tests/saliency/MotionSaliencyTest.cs
  • test/OpenCvSharp.Tests/saliency/ObjectnessBINGTest.cs
  • test/OpenCvSharp.Tests/saliency/StaticSaliencyTest.cs
  • test/OpenCvSharp.Tests/text/ERFilterTest.cs
  • test/OpenCvSharp.Tests/text/OCRDecoderTest.cs
  • test/OpenCvSharp.Tests/ximgproc/XimgProcTest.cs
🚧 Files skipped from review as they are similar to previous changes (12)
  • test/OpenCvSharp.Tests/saliency/ObjectnessBINGTest.cs
  • src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj
  • src/OpenCvSharp/Modules/text/OCRHolisticWordRecognizer.cs
  • test/OpenCvSharp.Tests/text/OCRDecoderTest.cs
  • src/OpenCvSharp/Modules/ximgproc/DisparityWLSFilter.cs
  • test/OpenCvSharp.Tests/saliency/MotionSaliencyTest.cs
  • test/OpenCvSharp.Tests/saliency/StaticSaliencyTest.cs
  • test/OpenCvSharp.Tests/text/ERFilterTest.cs
  • src/OpenCvSharpExtern/text_ERFilter.h
  • src/OpenCvSharp/Modules/text/OCRHMMDecoder.cs
  • test/OpenCvSharp.Tests/ximgproc/XimgProcTest.cs
  • src/OpenCvSharp/Modules/text/OCRBeamSearchDecoder.cs

📝 Walkthrough

Walkthrough

The change expands OpenCV 5.x coverage across photo, text, saliency, shape, superres, and ximgproc modules with managed wrappers, native exports, P/Invoke bindings, build wiring, and tests.

Changes

OpenCV 5.x API coverage

Layer / File(s) Summary
Photo color correction APIs
src/OpenCvSharp/Modules/photo/*, src/OpenCvSharp/Cv2/Cv2_photo.cs, src/OpenCvSharp/Internal/PInvoke/NativeMethods/photo/*, src/OpenCvSharpExtern/photo*, test/OpenCvSharp.Tests/photo/*
Adds ColorCorrectionModel, supporting enums, gamma correction, native exports, interop bindings, persistence, and tests.
Saliency, shape, and superres bridges
src/OpenCvSharp/Modules/{saliency,shape,stereo,superres}/*, src/OpenCvSharp/Internal/PInvoke/NativeMethods/{saliency,shape,stereo,superres}/*, src/OpenCvSharpExtern/{saliency_*,shape_*,stereo_*,superres.h}
Adds concrete saliency serialization, shape component getters, native pointer factories, and SuperResolution.OpticalFlow.
Text detection and OCR APIs
src/OpenCvSharp/Modules/text/*, src/OpenCvSharp/Internal/PInvoke/NativeMethods/text/*, src/OpenCvSharpExtern/text*, test/OpenCvSharp.Tests/text/*
Adds ER filtering, OCR HMM/beam-search/holistic decoders, classifier callbacks, transition-table creation, typed OCR enums, and tests.
XImgProc algorithm wrappers
src/OpenCvSharp/Modules/ximgproc/*, src/OpenCvSharp/Internal/PInvoke/NativeMethods/ximgproc/*, src/OpenCvSharpExtern/ximgproc*, test/OpenCvSharp.Tests/ximgproc/*
Adds disparity filtering, contour fitting, scan segmentation, Radon and ellipse operations, sparse-match interpolators, native bridges, and tests.
Native build wiring
src/OpenCvSharpExtern/{photo.cpp,text.cpp,ximgproc.cpp,*.vcxproj*}
Includes the new native headers in translation units and Visual Studio project metadata.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant Cv2Text
  participant NativeMethods
  participant OpenCVText
  Caller->>Cv2Text: Create OCR decoder
  Cv2Text->>NativeMethods: Invoke decoder creation binding
  NativeMethods->>OpenCVText: Create native decoder
  OpenCVText-->>NativeMethods: Return decoder pointer
  NativeMethods-->>Cv2Text: Return managed handle
  Caller->>Cv2Text: Run image or image plus mask
  Cv2Text->>NativeMethods: Invoke OCR run binding
  NativeMethods->>OpenCVText: Run decoder and populate outputs
  OpenCVText-->>NativeMethods: Return text and component data
  NativeMethods-->>Cv2Text: Convert native outputs
  Cv2Text-->>Caller: Return OCR results
Loading

Possibly related issues

  • #2019 — Covers the photo, text, saliency, shape, superres, and ximgproc API additions implemented here.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 39.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: filling OpenCV 5.x API gaps across photo, text, saliency, shape, superres, and ximgproc.
Linked Issues check ✅ Passed The PR implements the requested module coverage and supporting enums/wrappers, with only the explicitly excluded unsafe ERStat/callback bridges missing.
Out of Scope Changes check ✅ Passed I see no clear unrelated changes; tests, bindings, project includes, and helper wrappers all support the OpenCV 5.x coverage work.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/issue-2015-coverage-sweep

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (2)
src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj (1)

186-190: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Sort header includes alphabetically for maintainability.

The newly added ximgproc headers are slightly out of alphabetical order. ximgproc_ContourFitting.h and ximgproc_DisparityFilter.h should be placed before ximgproc_EdgeBoxes.h.

♻️ Proposed refactor
-    <ClInclude Include="ximgproc_EdgeBoxes.h" />
-    <ClInclude Include="ximgproc_EdgeFilter.h" />
-    <ClInclude Include="ximgproc_FastLineDetector.h" />
-    <ClInclude Include="ximgproc_ContourFitting.h" />
-    <ClInclude Include="ximgproc_DisparityFilter.h" />
+    <ClInclude Include="ximgproc_ContourFitting.h" />
+    <ClInclude Include="ximgproc_DisparityFilter.h" />
+    <ClInclude Include="ximgproc_EdgeBoxes.h" />
+    <ClInclude Include="ximgproc_EdgeFilter.h" />
+    <ClInclude Include="ximgproc_FastLineDetector.h" />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj` around lines 186 - 190,
Reorder the ximgproc header entries in the project file alphabetically, placing
ximgproc_ContourFitting.h and ximgproc_DisparityFilter.h before
ximgproc_EdgeBoxes.h while preserving the remaining entries.
test/OpenCvSharp.Tests/saliency/MotionSaliencyTest.cs (1)

70-91: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Delete the temporary file after the test completes.

The test writes a file to the temporary directory but does not clean it up, which pollutes the environment over successive test runs. Consider wrapping the file operations in a try/finally block to ensure deletion.

♻️ Proposed refactor
     [Fact]
     public void ReadWrite()
     {
         // cv::saliency::Saliency inherits Algorithm virtually; this exercises the P/Invoke plumbing
         // that keeps the native pointer at its concrete type across the write/read call, rather than
         // reinterpreting it as cv::Algorithm* (which would corrupt memory - see StaticSaliencyTest's
         // SpectralResidual_ReadWrite for the full explanation).
         using var saliency = MotionSaliencyBinWangApr2014.Create();
         saliency.SetImagesize(64, 48);
 
         var fileName = Path.Combine(Path.GetTempPath(), "motion_saliency_bin_wang_apr2014_test.yml");
-        using (var fs = new FileStorage(fileName, FileStorage.Modes.Write))
-        {
-            fs.Write("marker", 1);
-            saliency.Write(fs);
-        }
-
-        using var fs2 = new FileStorage(fileName, FileStorage.Modes.Read);
-        var root = fs2.Root();
-        Assert.NotNull(root);
-        saliency.Read(root);
+        try
+        {
+            using (var fs = new FileStorage(fileName, FileStorage.Modes.Write))
+            {
+                fs.Write("marker", 1);
+                saliency.Write(fs);
+            }
+
+            using var fs2 = new FileStorage(fileName, FileStorage.Modes.Read);
+            var root = fs2.Root();
+            Assert.NotNull(root);
+            saliency.Read(root);
+        }
+        finally
+        {
+            if (File.Exists(fileName))
+            {
+                File.Delete(fileName);
+            }
+        }
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/OpenCvSharp.Tests/saliency/MotionSaliencyTest.cs` around lines 70 - 91,
Update the ReadWrite test around the fileName and FileStorage operations to
delete the generated temporary YAML file in a finally block, ensuring cleanup
even when writing or reading fails while preserving the existing assertions and
disposal behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/OpenCvSharp/Modules/text/OCRBeamSearchDecoder.cs`:
- Around line 84-152: The OCR Run overloads do not validate the decoder receiver
before invoking native code. Add ThrowIfDisposed() on the receiver at the start
of every Run overload in OCRBeamSearchDecoder.cs (84-152) and OCRHMMDecoder.cs
(83-151), alongside the existing Mat validation; apply the same receiver check
to every Run overload in OCRTesseract.cs and OCRHolisticWordRecognizer.cs.

In `@src/OpenCvSharp/Modules/text/OCRHolisticWordRecognizer.cs`:
- Around line 47-57: Add ThrowIfDisposed() at the beginning of both Run
overloads in src/OpenCvSharp/Modules/text/OCRHolisticWordRecognizer.cs:47-57 and
src/OpenCvSharp/Modules/text/OCRHolisticWordRecognizer.cs:90-103, before any
native invocation or Handle use; no other changes are required.

In `@src/OpenCvSharp/Modules/ximgproc/DisparityWLSFilter.cs`:
- Around line 62-168: Add GC.KeepAlive(this) after the native operations in the
Lambda, SigmaColor, LRCthresh, and DepthDiscontinuityRadius property accessors,
and in GetConfidenceMap and GetROI. Ensure each getter and setter places the
keep-alive call at the end of its block while preserving the existing return
values and disposal checks.

In `@src/OpenCvSharp/Modules/ximgproc/ScanSegment.cs`:
- Around line 92-100: The ScanSegment OutputArray wrappers lack readiness
validation before native writes and metadata synchronization afterward. In
ScanSegment.cs lines 92-100, update GetLabels to call
labelsOut.ThrowIfNotReady() before the native invocation and labelsOut.Fix()
after it; in lines 110-118, apply the same sequence to image around its native
call.

In `@src/OpenCvSharpExtern/text_ERFilter.h`:
- Around line 165-177: Update text_detectRegions_rects so a null filename is
converted to an empty string before constructing cv::String, while preserving
the provided filename when non-null. Apply the guard at the
cv::text::detectRegions call and leave the remaining arguments unchanged.

In `@test/OpenCvSharp.Tests/saliency/ObjectnessBINGTest.cs`:
- Around line 91-104: Update the serialization test around ObjectnessBING.Read
so the bing.Base value is changed after writing and before reading, then assert
that bing.Base is restored to the originally serialized value. Keep the existing
FileStorage write/read flow and marker serialization unchanged.

In `@test/OpenCvSharp.Tests/saliency/StaticSaliencyTest.cs`:
- Around line 74-85: Ensure temporary YAML files are deleted even when the
saliency read/write tests fail: wrap the file operations in
SpectralResidual_ReadWrite and FineGrained_ReadWrite with try/finally cleanup,
checking File.Exists(fileName) before deleting. Apply this to both affected
ranges in test/OpenCvSharp.Tests/saliency/StaticSaliencyTest.cs: lines 74-85 and
134-145.

In `@test/OpenCvSharp.Tests/text/OCRDecoderTest.cs`:
- Around line 21-29: Update OCRHMMDecoderCreate_MissingFile_Throws and the other
OCR missing-file tests to use Assert.Throws<OpenCVException> instead of
Assert.ThrowsAny<Exception>, ensuring they validate the expected native OpenCV
failure rather than unrelated binding or load errors. Add an exception-message
assertion only if the missing-file text is stable across supported OpenCV
versions.

In `@test/OpenCvSharp.Tests/ximgproc/XimgProcTest.cs`:
- Around line 484-486: Update the XImgProc.TransformFD test call to assign the
Mat.Eye(...) result to a local Mat using declaration before passing it as the
transform matrix, ensuring the temporary native resource is disposed while
preserving the existing assertion and fdContour setting.

---

Nitpick comments:
In `@src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj`:
- Around line 186-190: Reorder the ximgproc header entries in the project file
alphabetically, placing ximgproc_ContourFitting.h and ximgproc_DisparityFilter.h
before ximgproc_EdgeBoxes.h while preserving the remaining entries.

In `@test/OpenCvSharp.Tests/saliency/MotionSaliencyTest.cs`:
- Around line 70-91: Update the ReadWrite test around the fileName and
FileStorage operations to delete the generated temporary YAML file in a finally
block, ensuring cleanup even when writing or reading fails while preserving the
existing assertions and disposal behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4804ceff-7eb8-419d-83cf-9d4d671e6b2d

📥 Commits

Reviewing files that changed from the base of the PR and between 6126849 and 604cd3a.

📒 Files selected for processing (95)
  • src/OpenCvSharp/Cv2/Cv2_photo.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/photo/NativeMethods_photo_ColorCorrectionModel.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/saliency/NativeMethods_saliency_MotionSaliencyBinWangApr2014.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/saliency/NativeMethods_saliency_ObjectnessBING.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/saliency/NativeMethods_saliency_StaticSaliencyFineGrained.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/saliency/NativeMethods_saliency_StaticSaliencySpectralResidual.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/shape/NativeMethods_shape_ShapeDistanceExtractor.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/shape/NativeMethods_shape_ShapeTransformer.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/stereo/NativeMethods_stereo_StereoMatcher.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/superres/NativeMethods_superres_DenseOpticalFlowExt.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/text/NativeMethods_text_ERFilter.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/text/NativeMethods_text_OCRBeamSearchDecoder.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/text/NativeMethods_text_OCRHMMDecoder.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/text/NativeMethods_text_OCRHolisticWordRecognizer.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/ximgproc/NativeMethods_ximgproc.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/ximgproc/NativeMethods_ximgproc_ContourFitting.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/ximgproc/NativeMethods_ximgproc_DisparityFilter.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/ximgproc/NativeMethods_ximgproc_ScanSegment.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/ximgproc/NativeMethods_ximgproc_SparseMatchInterpolator.cs
  • src/OpenCvSharp/Modules/photo/CcmType.cs
  • src/OpenCvSharp/Modules/photo/ColorCheckerType.cs
  • src/OpenCvSharp/Modules/photo/ColorCorrectionModel.cs
  • src/OpenCvSharp/Modules/photo/ColorSpace.cs
  • src/OpenCvSharp/Modules/photo/DistanceType.cs
  • src/OpenCvSharp/Modules/photo/InitialMethodType.cs
  • src/OpenCvSharp/Modules/photo/LinearizationType.cs
  • src/OpenCvSharp/Modules/saliency/MotionSaliencyBinWangApr2014.cs
  • src/OpenCvSharp/Modules/saliency/ObjectnessBING.cs
  • src/OpenCvSharp/Modules/saliency/StaticSaliencyFineGrained.cs
  • src/OpenCvSharp/Modules/saliency/StaticSaliencySpectralResidual.cs
  • src/OpenCvSharp/Modules/shape/HistogramCostExtractor.cs
  • src/OpenCvSharp/Modules/shape/ShapeContextDistanceExtractor.cs
  • src/OpenCvSharp/Modules/shape/ShapeTransformer.cs
  • src/OpenCvSharp/Modules/stereo/StereoMatcher.cs
  • src/OpenCvSharp/Modules/superres/BroxOpticalFlow.cs
  • src/OpenCvSharp/Modules/superres/DenseOpticalFlowExt.cs
  • src/OpenCvSharp/Modules/superres/DualTVL1OpticalFlow.cs
  • src/OpenCvSharp/Modules/superres/FarnebackOpticalFlow.cs
  • src/OpenCvSharp/Modules/superres/PyrLKOpticalFlow.cs
  • src/OpenCvSharp/Modules/superres/SuperResolution.cs
  • src/OpenCvSharp/Modules/text/ClassifierType.cs
  • src/OpenCvSharp/Modules/text/Cv2.Text.cs
  • src/OpenCvSharp/Modules/text/DecoderMode.cs
  • src/OpenCvSharp/Modules/text/ERFilter.cs
  • src/OpenCvSharp/Modules/text/ERFilterCallback.cs
  • src/OpenCvSharp/Modules/text/ERFilterNMMode.cs
  • src/OpenCvSharp/Modules/text/ErGroupingModes.cs
  • src/OpenCvSharp/Modules/text/OCRBeamSearchDecoder.cs
  • src/OpenCvSharp/Modules/text/OCRBeamSearchDecoderClassifierCallback.cs
  • src/OpenCvSharp/Modules/text/OCRHMMDecoder.cs
  • src/OpenCvSharp/Modules/text/OCRHMMDecoderClassifierCallback.cs
  • src/OpenCvSharp/Modules/text/OCRHolisticWordRecognizer.cs
  • src/OpenCvSharp/Modules/text/OCRTesseract.cs
  • src/OpenCvSharp/Modules/text/OcrEngineMode.cs
  • src/OpenCvSharp/Modules/text/PageSegMode.cs
  • src/OpenCvSharp/Modules/ximgproc/ContourFitting.cs
  • src/OpenCvSharp/Modules/ximgproc/Cv2.XImgProc.cs
  • src/OpenCvSharp/Modules/ximgproc/DisparityFilter.cs
  • src/OpenCvSharp/Modules/ximgproc/DisparityWLSFilter.cs
  • src/OpenCvSharp/Modules/ximgproc/EdgeAwareInterpolator.cs
  • src/OpenCvSharp/Modules/ximgproc/RICInterpolator.cs
  • src/OpenCvSharp/Modules/ximgproc/ScanSegment.cs
  • src/OpenCvSharp/Modules/ximgproc/SparseMatchInterpolator.cs
  • src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj
  • src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj.filters
  • src/OpenCvSharpExtern/photo.cpp
  • src/OpenCvSharpExtern/photo_ColorCorrectionModel.h
  • src/OpenCvSharpExtern/saliency_MotionSaliencyBinWangApr2014.h
  • src/OpenCvSharpExtern/saliency_ObjectnessBING.h
  • src/OpenCvSharpExtern/saliency_StaticSaliencyFineGrained.h
  • src/OpenCvSharpExtern/saliency_StaticSaliencySpectralResidual.h
  • src/OpenCvSharpExtern/shape_ShapeDistanceExtractor.h
  • src/OpenCvSharpExtern/shape_ShapeTransformer.h
  • src/OpenCvSharpExtern/stereo_StereoMatcher.h
  • src/OpenCvSharpExtern/superres.h
  • src/OpenCvSharpExtern/text.cpp
  • src/OpenCvSharpExtern/text_ERFilter.h
  • src/OpenCvSharpExtern/text_OCRBeamSearchDecoder.h
  • src/OpenCvSharpExtern/text_OCRHMMDecoder.h
  • src/OpenCvSharpExtern/text_OCRHolisticWordRecognizer.h
  • src/OpenCvSharpExtern/ximgproc.cpp
  • src/OpenCvSharpExtern/ximgproc.h
  • src/OpenCvSharpExtern/ximgproc_ContourFitting.h
  • src/OpenCvSharpExtern/ximgproc_DisparityFilter.h
  • src/OpenCvSharpExtern/ximgproc_ScanSegment.h
  • src/OpenCvSharpExtern/ximgproc_SparseMatchInterpolator.h
  • test/OpenCvSharp.Tests/photo/ColorCorrectionModelTest.cs
  • test/OpenCvSharp.Tests/saliency/MotionSaliencyTest.cs
  • test/OpenCvSharp.Tests/saliency/ObjectnessBINGTest.cs
  • test/OpenCvSharp.Tests/saliency/StaticSaliencyTest.cs
  • test/OpenCvSharp.Tests/shape/ShapeContextDistanceExtractorTest.cs
  • test/OpenCvSharp.Tests/superres/SuperResTest.cs
  • test/OpenCvSharp.Tests/text/ERFilterTest.cs
  • test/OpenCvSharp.Tests/text/OCRDecoderTest.cs
  • test/OpenCvSharp.Tests/ximgproc/XimgProcTest.cs

Comment on lines +84 to +152
public override void Run(
Mat image,
out string outputText,
out Rect[] componentRects,
out string?[] componentTexts,
out float[] componentConfidences,
ComponentLevels componentLevel = ComponentLevels.Word)
{
ArgumentNullException.ThrowIfNull(image);
image.ThrowIfDisposed();

using var outputTextString = new StdString();
using var componentRectsVector = new StdVector<Rect>();
using var componentTextsVector = new VectorOfString();
using var componentConfidencesVector = new StdVector<float>();
NativeMethods.HandleException(
NativeMethods.text_OCRBeamSearchDecoder_run1(
Handle,
image.CvPtr,
outputTextString.CvPtr,
componentRectsVector.CvPtr,
componentTextsVector.CvPtr,
componentConfidencesVector.CvPtr,
(int)componentLevel));
outputText = outputTextString.ToString();
componentRects = componentRectsVector.ToArray();
componentTexts = componentTextsVector.ToArray();
componentConfidences = componentConfidencesVector.ToArray();

GC.KeepAlive(image);
}

/// <inheritdoc />
public override void Run(
Mat image,
Mat mask,
out string outputText,
out Rect[] componentRects,
out string?[] componentTexts,
out float[] componentConfidences,
ComponentLevels componentLevel = ComponentLevels.Word)
{
ArgumentNullException.ThrowIfNull(image);
ArgumentNullException.ThrowIfNull(mask);
image.ThrowIfDisposed();
mask.ThrowIfDisposed();

using var outputTextString = new StdString();
using var componentRectsVector = new StdVector<Rect>();
using var componentTextsVector = new VectorOfString();
using var componentConfidencesVector = new StdVector<float>();
NativeMethods.HandleException(
NativeMethods.text_OCRBeamSearchDecoder_run2(
Handle,
image.CvPtr,
mask.CvPtr,
outputTextString.CvPtr,
componentRectsVector.CvPtr,
componentTextsVector.CvPtr,
componentConfidencesVector.CvPtr,
(int)componentLevel));
outputText = outputTextString.ToString();
componentRects = componentRectsVector.ToArray();
componentTexts = componentTextsVector.ToArray();
componentConfidences = componentConfidencesVector.ToArray();

GC.KeepAlive(image);
GC.KeepAlive(mask);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Files:\n'
git ls-files 'src/OpenCvSharp/Modules/text/OCRBeamSearchDecoder.cs' 'src/OpenCvSharp/Modules/text/OCRHMMDecoder.cs' 'src/OpenCvSharp/Modules/**/OCR*.cs' 'src/OpenCvSharp/Modules/**/Algorithm*.cs' 'src/OpenCvSharp/**/*.cs' | sed -n '1,200p'

printf '\nClass outlines:\n'
ast-grep outline src/OpenCvSharp/Modules/text/OCRBeamSearchDecoder.cs --view expanded || true
printf '\n---\n'
ast-grep outline src/OpenCvSharp/Modules/text/OCRHMMDecoder.cs --view expanded || true

printf '\nNearby Run methods with ThrowIfDisposed:\n'
rg -n "ThrowIfDisposed\\(\\)" src/OpenCvSharp/Modules/text src/OpenCvSharp/Modules | sed -n '1,200p'

Repository: shimat/opencvsharp

Length of output: 31548


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'BaseOCR:\n'
sed -n '1,220p' src/OpenCvSharp/Modules/text/BaseOCR.cs

printf '\nOCRBeamSearchDecoder:\n'
sed -n '1,220p' src/OpenCvSharp/Modules/text/OCRBeamSearchDecoder.cs

printf '\nOCRHMMDecoder:\n'
sed -n '1,220p' src/OpenCvSharp/Modules/text/OCRHMMDecoder.cs

printf '\nOCRTesseract:\n'
sed -n '1,180p' src/OpenCvSharp/Modules/text/OCRTesseract.cs

printf '\nOCRHolisticWordRecognizer:\n'
sed -n '1,180p' src/OpenCvSharp/Modules/text/OCRHolisticWordRecognizer.cs

Repository: shimat/opencvsharp

Length of output: 29066


Add ThrowIfDisposed() to every OCR Run overload.

These wrappers validate Mat inputs but skip the receiver disposal check before native calls.

  • src/OpenCvSharp/Modules/text/OCRBeamSearchDecoder.cs
  • src/OpenCvSharp/Modules/text/OCRHMMDecoder.cs
  • src/OpenCvSharp/Modules/text/OCRTesseract.cs
  • src/OpenCvSharp/Modules/text/OCRHolisticWordRecognizer.cs
📍 Affects 2 files
  • src/OpenCvSharp/Modules/text/OCRBeamSearchDecoder.cs#L84-L152 (this comment)
  • src/OpenCvSharp/Modules/text/OCRHMMDecoder.cs#L83-L151
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/OpenCvSharp/Modules/text/OCRBeamSearchDecoder.cs` around lines 84 - 152,
The OCR Run overloads do not validate the decoder receiver before invoking
native code. Add ThrowIfDisposed() on the receiver at the start of every Run
overload in OCRBeamSearchDecoder.cs (84-152) and OCRHMMDecoder.cs (83-151),
alongside the existing Mat validation; apply the same receiver check to every
Run overload in OCRTesseract.cs and OCRHolisticWordRecognizer.cs.

Source: Coding guidelines

Comment thread src/OpenCvSharp/Modules/text/OCRHolisticWordRecognizer.cs
Comment thread src/OpenCvSharp/Modules/ximgproc/DisparityWLSFilter.cs
Comment on lines +92 to +100
public virtual void GetLabels(OutputArray labelsOut)
{
ThrowIfDisposed();

NativeMethods.HandleException(
NativeMethods.ximgproc_ScanSegment_getLabels(Handle, labelsOut.Proxy));

GC.KeepAlive(labelsOut.Source);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Missing validation and synchronization for OutputArray buffers. When C++ writes to or reallocates an OutputArray, the wrapper must be validated beforehand with ThrowIfNotReady() and its internal dimensions/pointers must be updated afterward with Fix(). Omitting Fix() causes the returned Mat in C# to appear empty or carry stale metadata. Based on learnings, InputArray/OutputArray-appropriate mechanisms should be used for validation.

  • src/OpenCvSharp/Modules/ximgproc/ScanSegment.cs#L92-L100: add labelsOut.ThrowIfNotReady(); before the native call and labelsOut.Fix(); after it.
  • src/OpenCvSharp/Modules/ximgproc/ScanSegment.cs#L110-L118: add image.ThrowIfNotReady(); before the native call and image.Fix(); after it.
📍 Affects 1 file
  • src/OpenCvSharp/Modules/ximgproc/ScanSegment.cs#L92-L100 (this comment)
  • src/OpenCvSharp/Modules/ximgproc/ScanSegment.cs#L110-L118
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/OpenCvSharp/Modules/ximgproc/ScanSegment.cs` around lines 92 - 100, The
ScanSegment OutputArray wrappers lack readiness validation before native writes
and metadata synchronization afterward. In ScanSegment.cs lines 92-100, update
GetLabels to call labelsOut.ThrowIfNotReady() before the native invocation and
labelsOut.Fix() after it; in lines 110-118, apply the same sequence to image
around its native call.

Source: Learnings

Comment thread src/OpenCvSharpExtern/text_ERFilter.h
Comment thread test/OpenCvSharp.Tests/saliency/ObjectnessBINGTest.cs Outdated
Comment thread test/OpenCvSharp.Tests/saliency/StaticSaliencyTest.cs
Comment thread test/OpenCvSharp.Tests/text/OCRDecoderTest.cs
Comment thread test/OpenCvSharp.Tests/ximgproc/XimgProcTest.cs
@shimat shimat self-assigned this Jul 16, 2026
- add ThrowIfDisposed() to every OCRHMMDecoder/OCRBeamSearchDecoder/
  OCRHolisticWordRecognizer Run overload before touching the native handle
- add GC.KeepAlive(this) to DisparityWLSFilter's property accessors and
  GetConfidenceMap/GetROI, matching the belt-and-suspenders pattern already
  used elsewhere (Mat, SparseMat, SimpleBlobDetector, ImageCollection)
- guard text_detectRegions_rects against a null filename before wrapping it
  in cv::String
- strengthen the OCR/ER-filter missing-file tests to assert the specific
  OpenCVException the native side actually throws, instead of Exception
- delete the temporary FileStorage files the saliency Read/Write regression
  tests write to the temp directory
- materialize the Mat.Eye(...) MatExpr passed to TransformFD into a local
  so it isn't finalizer-collected
- fix ximgproc header include ordering in the vcxproj

Not applied: the suggestion to add ThrowIfNotReady()/Fix() calls in
ScanSegment.GetLabels/GetLabelContourMask - neither method exists anywhere
in this codebase, so this would not compile.

Not applied: the suggestion to change ObjectnessBING.Base before Read and
assert it reverts - ObjectnessBING never overrides Algorithm::read/write
(confirmed against opencv_contrib source), so nothing is actually restored;
asserting a round-trip here would be asserting something untrue.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@shimat

shimat commented Jul 16, 2026

Copy link
Copy Markdown
Owner Author

Pushed a follow-up commit addressing CodeRabbit's review:

  • Added ThrowIfDisposed() to every OCR decoder Run overload, GC.KeepAlive(this) to DisparityWLSFilter's accessors, a null-filename guard in text_detectRegions_rects, tightened the missing-file tests to assert OpenCVException specifically, cleaned up the saliency regression tests' temp files, fixed the Mat.Eye(...) temporary leak in the ContourFitting/TransformFD test, and reordered the new ximgproc_*.h includes in the vcxproj alphabetically.
  • Did not apply two suggestions that don't hold up against this codebase:
    • ScanSegment.GetLabels/GetLabelContourMask: the suggested ThrowIfNotReady()/Fix() calls don't exist anywhere in this repo (grep confirms zero hits) - applying them would not compile.
    • ObjectnessBINGTest.ReadWrite: the suggested "change Base before Read, assert it reverts" would fail, because ObjectnessBING never overrides Algorithm::read/write (confirmed against the opencv_contrib source) - there's nothing to restore, so the round-trip it asks for doesn't happen. Added a comment explaining this instead.

Re: the failing macOS (arm64) job - unrelated to this PR. The xUnit run itself reports Passed! - Failed: 0, Passed: 1410, ... Total: 1492 before the process crashes with SIGSEGV. The crash report backtrace is entirely inside cv::dynafu::WarpField::applyWarp on a parallel_for_ worker thread, which is the rgbd/dynafu module this PR never touches (this exact crash family was already worked around once in e6416f8 for a different DynaFu test).

shimat added a commit that referenced this pull request Jul 16, 2026
- redesign FacemarkTrain.GetData(void*): the generic raw-pointer binding is
  removed entirely (it was unreferenced) in favor of a typed
  FacemarkAAM.GetData(out Point2f[] s0), since FacemarkAAM is the only
  concrete algorithm that populates anything through it (FacemarkLBF's
  override ignores the pointer and always returns false)
- reuse the Combine helper in StandardCollector.GetResultsMap, matching
  GetResults, instead of a separate Zip/ToDictionary conversion

While fixing the GetData exposure, found that FacemarkAAM/FacemarkLBF/
FacemarkKazemi (like the saliency classes fixed in #2052) crash when calling
Algorithm.Write/Read: cv::face::Facemark inherits cv::Algorithm *virtually*,
so the raw pointer these classes hand to the generic core_Algorithm_write/
read bridge (typed as cv::Algorithm*) is not the same address as the
correctly-adjusted pointer the compiler would produce from the concrete
type. Fixed by giving all three classes their own write/read bridge that
calls write()/read() on the pointer at its native concrete type, plus
regression tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@shimat
shimat merged commit 9d393e1 into main Jul 16, 2026
14 checks passed
@shimat
shimat deleted the codex/issue-2015-coverage-sweep branch July 16, 2026 06:31
@shimat shimat added the enhancement New feature or improvement to OpenCvSharp label Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or improvement to OpenCvSharp

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OpenCV 5.x API coverage: photo, text, saliency, shape, superres, ximgproc gaps

1 participant