Skip to content

Polish ConnectedComponents wrappers (doc fix + eager-copy / round-trip efficiency) - #1999

Merged
shimat merged 2 commits into
mainfrom
fix/connected-components-polish-1985
Jul 3, 2026
Merged

shimat merged 2 commits into
mainfrom
fix/connected-components-polish-1985

Conversation

@shimat

@shimat shimat commented Jul 3, 2026 •

Copy link
Copy Markdown
Owner

Summary

Addresses the polish items from #1985 for the ConnectedComponents family wrappers.

  • Fixed the LabelCount XML doc: it is the full label count including the background label (N), not "the number of labels - 1".
  • FilterByLabel(s) / GetLabelMask now wrap the managed Labels buffer via the existing zero-copy Mat.FromPixelData and compare directly against a Scalar (Cv2.Compare(labelsView, new Scalar(label), ...)), removing the extra full-size scalar-filled comparison Mat the old code allocated.
  • RenderBlobs now reads straight from the plain int[,] buffer and writes via Mat.AsRows<T> (zero-P/Invoke-per-element row access) instead of going through the generic Mat<Vec3b> indexer, avoiding per-pixel indexer overhead.
  • Documented that Blobs[0] is the background blob.
  • Added an optional ltype parameter to ConnectedComponentsEx so callers can opt into CV_16U labels (halves the native label image's memory footprint during the native call, at the cost of a 65535 label limit), matching what the native API already supports. The result is still always widened to a plain int[,] for Labels.

ConnectedComponents intentionally stays a plain (non-IDisposable) type: an earlier version of this PR made it retain the native label Mat for lazy materialization, but that forced IDisposable onto every caller for a convenience API that previously never needed disposal. Labels is still eagerly materialized to a managed int[,] in ConnectedComponentsEx, same as before.

Closes #1985.

Test plan

  • dotnet build for OpenCvSharp and OpenCvSharp.Tests — no warnings/errors.
  • dotnet test --filter FullyQualifiedName~ConnectedComponents — all pass, including a new test covering the CV_16U ltype option.
  • dotnet test --filter FullyQualifiedName~ImgProc — full ImgProc suite (243 tests) passes.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Connected component results now let you choose the output label image type (including 16-bit labels) when running ConnectedComponentsEx.
  • Bug Fixes
    • Rendering blobs and filtering by label were updated to correctly handle the supported label types.
  • Tests
    • Added a new test covering 16-bit label output (RunWithCv16ULabelType) and validating label count and dimensions.

Fixes issue #1985:
- Fix LabelCount XML doc (it is the full label count including
  background, not "count - 1").
- Document that Blobs[0] is the background blob.
- ConnectedComponentsEx now keeps the native label Mat and defers
  materializing the managed Labels array until it is actually
  accessed, instead of always eagerly copying it.
- FilterByLabels/GetLabelMask compare directly against the native
  label Mat, removing the managed round-trip through int[,] and
  Mat.FromPixelData.
- RenderBlobs iterates via Mat.AsRows instead of the generic
  indexer, avoiding per-pixel indexer overhead.
- Add an optional ltype parameter to ConnectedComponentsEx so
  callers can opt into CV_16U labels to halve the native label
  image's memory footprint.

ConnectedComponents now implements IDisposable to release the
retained native label image.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@shimat shimat self-assigned this Jul 3, 2026
@coderabbitai

coderabbitai Bot commented Jul 3, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

ConnectedComponentsEx now accepts an optional label output type, including CV_16U, and converts labels through a widening helper. ConnectedComponents updates label-based masking and blob rendering to use the existing label buffer more directly. Tests add CV_16U coverage.

Changes

ConnectedComponents label type and buffer handling

Layer / File(s) Summary
ConnectedComponentsEx label type
src/OpenCvSharp/Cv2/Cv2_imgproc.cs
Adds optional ltype, validates CV_32S or CV_16U, runs connected components with the selected type, and converts labels through a helper.
Label masking and blob rendering
src/OpenCvSharp/Modules/imgproc/ConnectedComponent.cs
Updates label mask generation, label filtering, blob rendering, and related docs to work from the labels buffer and background label 0.
CV_16U test coverage
test/OpenCvSharp.Tests/imgproc/ConnectedComponentsTest.cs
Adds a test that runs ConnectedComponentsEx with MatType.CV_16U and checks the output shape and count.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant Cv2
  participant OpenCvNative
  participant Helper

  Caller->>Cv2: ConnectedComponentsEx(image, connectivity, ccltype, ltype)
  Cv2->>Cv2: validate label type
  Cv2->>OpenCvNative: ConnectedComponentsWithStatsWithAlgorithm(...)
  OpenCvNative-->>Cv2: labelsMat, stats, centroids
  Cv2->>Helper: ToInt32RectangularArray(labelsMat, labelType)
  Helper-->>Cv2: int[,]
  Cv2-->>Caller: ConnectedComponents
Loading

Possibly related PRs

  • shimat/opencvsharp#1818: Also changes connected-components label handling around GetLabelMask and Cv2.Compare, which overlaps with the label-mask path updated here.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning It covers round-trip removal, background docs, RenderBlobs, and CV_16U support, but still eagerly materializes labels and doesn't fix the LabelCount XML doc. Add the LabelCount doc fix and either keep labels native until needed or let callers choose lazy materialization for ConnectedComponentsEx.
✅ Passed checks (4 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed No unrelated files or features are introduced beyond ConnectedComponents polish and a regression test.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the ConnectedComponents wrapper polish and the doc/efficiency focus of the changes.
✨ 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 fix/connected-components-polish-1985

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: 1

🧹 Nitpick comments (1)
test/OpenCvSharp.Tests/imgproc/ConnectedComponentsTest.cs (1)

31-49: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor: missing buffer non-emptiness check.

Unlike the Run test (Line 22), this test doesn't assert cc.Labels.GetBuffer() is non-empty for the CV_16U path. Not a blocker, but keeping parity would strengthen coverage for the new lazy-materialization path.

🤖 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/imgproc/ConnectedComponentsTest.cs` around lines 31 -
49, Add the missing non-empty buffer assertion in the ConnectedComponentsEx
CV_16U test to match the existing Run test coverage. In RunWithCv16ULabelType,
after verifying cc.Labels dimensions, also assert that cc.Labels.GetBuffer() is
not empty so the lazy-materialization path is covered consistently. Keep the
change focused on the ConnectedComponentsTest and the cc.Labels access in the
new test.
🤖 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/imgproc/ConnectedComponent.cs`:
- Line 24: Add a disposal guard to the native-backed accessors in
ConnectedComponent so they fail fast with ObjectDisposedException instead of
reading freed Mat memory. Update Labels and the other entry points mentioned in
this class, including RenderBlobs, GetLabelMask, and the FilterBy* methods, to
call a shared ThrowIfDisposed-style check before touching labelsMat or any
native-backed state. Use the ConnectedComponent members to locate the affected
paths and ensure the guard runs regardless of whether labelsCache has already
been populated.

---

Nitpick comments:
In `@test/OpenCvSharp.Tests/imgproc/ConnectedComponentsTest.cs`:
- Around line 31-49: Add the missing non-empty buffer assertion in the
ConnectedComponentsEx CV_16U test to match the existing Run test coverage. In
RunWithCv16ULabelType, after verifying cc.Labels dimensions, also assert that
cc.Labels.GetBuffer() is not empty so the lazy-materialization path is covered
consistently. Keep the change focused on the ConnectedComponentsTest and the
cc.Labels access in the new test.
🪄 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: a68fc6ab-bb0c-4130-8e83-4ab9e567cc33

📥 Commits

Reviewing files that changed from the base of the PR and between e27b400 and bd9a7be.

📒 Files selected for processing (3)
  • src/OpenCvSharp/Cv2/Cv2_imgproc.cs
  • src/OpenCvSharp/Modules/imgproc/ConnectedComponent.cs
  • test/OpenCvSharp.Tests/imgproc/ConnectedComponentsTest.cs

Comment thread src/OpenCvSharp/Modules/imgproc/ConnectedComponent.cs Outdated
Retaining the native label Mat for lazy materialization forced
ConnectedComponents to become IDisposable, which regressed the
convenience API's ergonomics (every caller now had to remember to
dispose). Revert to eager conversion of the label image to a plain
managed int[,] in ConnectedComponentsEx, as before.

FilterByLabels/GetLabelMask still avoid the previous full-size
scalar-filled comparison Mat: they wrap the managed Labels buffer
via the existing zero-copy Mat.FromPixelData and compare directly
against a Scalar. RenderBlobs still avoids the generic indexer,
reading straight from the int[,] buffer and writing via
Mat.AsRows. The CV_16U ltype option is preserved, widening to
int[,] once during construction.

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

@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.

🧹 Nitpick comments (1)
src/OpenCvSharp/Cv2/Cv2_imgproc.cs (1)

2239-2241: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add test coverage for the invalid-ltype validation path.

The new ArgumentException guard for ltype (must be CV_32S/CV_16U) has no corresponding test verifying it throws for an unsupported type (e.g. CV_8U).

🤖 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/Cv2/Cv2_imgproc.cs` around lines 2239 - 2241, Add test
coverage for the new invalid ltype validation in Cv2_imgproc.Cv2 connected to
the labelType guard: add a test that calls the relevant imgproc API with an
unsupported ltype such as CV_8U and asserts an ArgumentException is thrown with
the ltype parameter name. Place the test alongside the existing Cv2 imgproc
tests that cover label-type behavior so the new CV_32S/CV_16U check is verified
for failure cases.
🤖 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.

Nitpick comments:
In `@src/OpenCvSharp/Cv2/Cv2_imgproc.cs`:
- Around line 2239-2241: Add test coverage for the new invalid ltype validation
in Cv2_imgproc.Cv2 connected to the labelType guard: add a test that calls the
relevant imgproc API with an unsupported ltype such as CV_8U and asserts an
ArgumentException is thrown with the ltype parameter name. Place the test
alongside the existing Cv2 imgproc tests that cover label-type behavior so the
new CV_32S/CV_16U check is verified for failure cases.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 27e04dda-9b83-4eb9-8467-b9a286eba202

📥 Commits

Reviewing files that changed from the base of the PR and between bd9a7be and 7b70140.

📒 Files selected for processing (3)
  • src/OpenCvSharp/Cv2/Cv2_imgproc.cs
  • src/OpenCvSharp/Modules/imgproc/ConnectedComponent.cs
  • test/OpenCvSharp.Tests/imgproc/ConnectedComponentsTest.cs

@shimat
shimat merged commit d3bb1f3 into main Jul 3, 2026
14 checks passed
@shimat
shimat deleted the fix/connected-components-polish-1985 branch July 3, 2026 15:23
@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.

ConnectedComponents wrappers: polish (doc fix + eager-copy / round-trip efficiency)

1 participant