Skip to content

Add LINEMOD wrappers for rgbd module#2042

Open
shimat wants to merge 2 commits into
mainfrom
codex/issue-2018-linemod
Open

Add LINEMOD wrappers for rgbd module#2042
shimat wants to merge 2 commits into
mainfrom
codex/issue-2018-linemod

Conversation

@shimat

@shimat shimat commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • add native and managed wrappers for cv::linemod::Detector, Modality, ColorGradient, DepthNormal, and QuantizedPyramid
  • support template registration/matching, synthetic templates, modality/template inspection, and FileStorage persistence
  • add Codex AGENTS.md that shares the existing Copilot development instructions
  • add LINEMOD interop tests covering modality parameters, quantization, matching, synthetic templates, and serialization

This implements the LINEMOD portion of #2018. The KinFu family remains for follow-up PRs.

Testing

  • cmake --build src\build --config Release -j 8
  • dotnet build src\OpenCvSharp\OpenCvSharp.csproj -c Release --no-restore
  • dotnet test test\OpenCvSharp.Tests\OpenCvSharp.Tests.csproj -c Release --no-restore --filter FullyQualifiedName~LinemodTest

Summary by CodeRabbit

  • New Features

    • Added RGB-D LINEMOD support for feature extraction, template creation, object detection, and matching.
    • Added Color Gradient and Depth Normal modalities with configurable parameters.
    • Added template and match data types, detector statistics, class filtering, and synthetic templates.
    • Added serialization and deserialization for detector configurations and template classes.
  • Tests

    • Added coverage for modality processing, persistence, template management, and matching workflows.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds OpenCV RGB-D LINEMOD support across native exports, C# interop bindings, modality and detector wrappers, LINEMOD data types, persistence APIs, and integration tests.

Changes

RGB-D LINEMOD support

Layer / File(s) Summary
LINEMOD contracts and native bridge
src/OpenCvSharp/Modules/rgbd/LinemodTypes.cs, src/OpenCvSharpExtern/..., src/OpenCvSharp/Internal/PInvoke/...
Adds LINEMOD records, contrib header inclusion, native wrapper functions, and C# LibraryImport declarations.
Modality and quantized pyramid wrappers
src/OpenCvSharp/Modules/rgbd/LinemodModality.cs
Adds ColorGradient, DepthNormal, modality processing and persistence, quantized output, template extraction, and pyramid operations.
Detector creation, matching, and persistence
src/OpenCvSharp/Modules/rgbd/LinemodDetector.cs
Adds detector factories, template ingestion, matching, metadata queries, modality retrieval, and configuration/class serialization APIs.
LINEMOD integration tests
test/OpenCvSharp.Tests/rgbd/LinemodTest.cs
Tests modality parameters, quantization, serialization, template management, synthetic templates, matching, and detector persistence.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Application
  participant LinemodDetector
  participant NativeMethods
  participant OpenCVLINEMOD
  Application->>LinemodDetector: AddTemplate or Match
  LinemodDetector->>NativeMethods: Marshal sources and invoke binding
  NativeMethods->>OpenCVLINEMOD: Execute LINEMOD detector operation
  OpenCVLINEMOD-->>NativeMethods: Return templates, matches, and quantized images
  NativeMethods-->>LinemodDetector: Return native results
  LinemodDetector-->>Application: Return managed LINEMOD values
Loading

Possibly related issues

  • Issue 2018 — Directly covers the LINEMOD wrapping work implemented by this pull request.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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 accurately summarizes the main change: adding LINEMOD wrappers for the rgbd module.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ 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-2018-linemod

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 (2)
src/OpenCvSharp/Modules/rgbd/LinemodTypes.cs (1)

6-7: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

LinemodTemplate's generated equality is broken by the Features array.

Records auto-generate Equals/GetHashCode from their properties, but LinemodFeature[] compares by reference, not by content. Two templates with identical feature data will report as unequal (and hash differently) unless they share the exact same array instance — surprising for a record whose whole point is usually value semantics.

♻️ Suggested fix: override equality members explicitly
-public sealed record LinemodTemplate(int Width, int Height, int PyramidLevel, LinemodFeature[] Features);
+public sealed record LinemodTemplate(int Width, int Height, int PyramidLevel, LinemodFeature[] Features)
+{
+    public bool Equals(LinemodTemplate? other) =>
+        other is not null &&
+        Width == other.Width && Height == other.Height && PyramidLevel == other.PyramidLevel &&
+        Features.AsSpan().SequenceEqual(other.Features);
+
+    public override int GetHashCode()
+    {
+        var hash = new HashCode();
+        hash.Add(Width); hash.Add(Height); hash.Add(PyramidLevel);
+        foreach (var f in Features) hash.Add(f);
+        return hash.ToHashCode();
+    }
+}
🤖 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/rgbd/LinemodTypes.cs` around lines 6 - 7, Update
LinemodTemplate’s equality implementation to compare Features element-by-element
and compute a matching content-based hash, while retaining Width, Height, and
PyramidLevel in value comparison. Override the generated equality members
explicitly so identical feature data is equal even when stored in different
array instances.
src/OpenCvSharp/Modules/rgbd/LinemodDetector.cs (1)

9-36: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated SetSafeHandle construction logic.

The private LinemodDetector(IntPtr ptr), the parameterless LinemodDetector(), and the modalities/tPyramid constructor each build their own OpenCvPtrSafeHandle with the same delete delegate. Route the public constructors through the private one to keep the disposal wiring in one place.

♻️ Suggested refactor
-    public LinemodDetector()
-    {
-        NativeMethods.HandleException(NativeMethods.rgbd_linemod_Detector_newEmpty(out var ptr));
-        SetSafeHandle(new OpenCvPtrSafeHandle(ptr, true,
-            static p => NativeMethods.HandleException(NativeMethods.rgbd_linemod_Detector_delete(p))));
-    }
+    public LinemodDetector() : this(CreateEmpty()) { }
+
+    private static IntPtr CreateEmpty()
+    {
+        NativeMethods.HandleException(NativeMethods.rgbd_linemod_Detector_newEmpty(out var ptr));
+        return ptr;
+    }

     public LinemodDetector(IEnumerable<LinemodModality> modalities, IEnumerable<int> tPyramid)
+        : this(CreateNative(modalities, tPyramid, out var mods))
     {
-        ArgumentNullException.ThrowIfNull(modalities);
-        ArgumentNullException.ThrowIfNull(tPyramid);
-        var mods = modalities.ToArray();
-        var steps = tPyramid.ToArray();
-        if (mods.Length == 0 || steps.Length == 0)
-            throw new ArgumentException("At least one modality and pyramid sampling step are required.");
-        var pointers = mods.Select(m => m.SmartPtr).ToArray();
-        NativeMethods.HandleException(NativeMethods.rgbd_linemod_Detector_new(
-            pointers, pointers.Length, steps, steps.Length, out var ptr));
-        SetSafeHandle(new OpenCvPtrSafeHandle(ptr, true,
-            static p => NativeMethods.HandleException(NativeMethods.rgbd_linemod_Detector_delete(p))));
         foreach (var mod in mods) GC.KeepAlive(mod);
     }
🤖 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/rgbd/LinemodDetector.cs` around lines 9 - 36,
Centralize disposal-handle setup in the private LinemodDetector(IntPtr ptr)
constructor. Update the parameterless and modalities/tPyramid constructors to
delegate to it after creating the native detector pointer, removing their
duplicated SetSafeHandle/OpenCvPtrSafeHandle construction while preserving
validation, native creation, and GC.KeepAlive 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/rgbd/LinemodModality.cs`:
- Around line 52-78: Add ThrowIfDisposed() at the start of Modality.Process,
Read, and Write, before accessing Handle or invoking native methods; apply the
same check to the ColorGradient.Parameters and DepthNormal.Parameters getters.
Preserve the existing argument validation, native calls, and KeepAlive behavior.

---

Nitpick comments:
In `@src/OpenCvSharp/Modules/rgbd/LinemodDetector.cs`:
- Around line 9-36: Centralize disposal-handle setup in the private
LinemodDetector(IntPtr ptr) constructor. Update the parameterless and
modalities/tPyramid constructors to delegate to it after creating the native
detector pointer, removing their duplicated SetSafeHandle/OpenCvPtrSafeHandle
construction while preserving validation, native creation, and GC.KeepAlive
behavior.

In `@src/OpenCvSharp/Modules/rgbd/LinemodTypes.cs`:
- Around line 6-7: Update LinemodTemplate’s equality implementation to compare
Features element-by-element and compute a matching content-based hash, while
retaining Width, Height, and PyramidLevel in value comparison. Override the
generated equality members explicitly so identical feature data is equal even
when stored in different array instances.
🪄 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: 88a59fac-f496-4328-83bd-1d867924e459

📥 Commits

Reviewing files that changed from the base of the PR and between 5c9eced and a933219.

📒 Files selected for processing (9)
  • AGENTS.md
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/rgbd/NativeMethods_rgbd_linemod.cs
  • src/OpenCvSharp/Modules/rgbd/LinemodDetector.cs
  • src/OpenCvSharp/Modules/rgbd/LinemodModality.cs
  • src/OpenCvSharp/Modules/rgbd/LinemodTypes.cs
  • src/OpenCvSharpExtern/include_opencv.h
  • src/OpenCvSharpExtern/rgbd.cpp
  • src/OpenCvSharpExtern/rgbd_linemod.h
  • test/OpenCvSharp.Tests/rgbd/LinemodTest.cs

Comment on lines +52 to +78
/// <summary>Forms a quantized image pyramid from a source image.</summary>
public QuantizedPyramid Process(Mat src, Mat? mask = null)
{
ArgumentNullException.ThrowIfNull(src);
src.ThrowIfDisposed();
mask?.ThrowIfDisposed();
NativeMethods.HandleException(NativeMethods.rgbd_linemod_Modality_process(
Handle, src.Handle, mask?.Handle ?? OpenCvSafeHandle.Null, out var ptr));
GC.KeepAlive(src); GC.KeepAlive(mask);
return new QuantizedPyramid(ptr);
}

/// <summary>Loads modality parameters from a file node.</summary>
public void Read(FileNode node)
{
ArgumentNullException.ThrowIfNull(node);
NativeMethods.HandleException(NativeMethods.rgbd_linemod_Modality_read(Handle, node.Handle));
GC.KeepAlive(node);
}

/// <summary>Writes modality parameters to file storage.</summary>
public void Write(FileStorage storage)
{
ArgumentNullException.ThrowIfNull(storage);
NativeMethods.HandleException(NativeMethods.rgbd_linemod_Modality_write(Handle, storage.Handle));
GC.KeepAlive(storage);
}

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

Missing ThrowIfDisposed() before native calls.

Process, Read, Write, and the ColorGradient/DepthNormal Parameters getters access Handle and invoke native P/Invoke calls without checking disposal state, unlike Name (line 44-45) and every method in QuantizedPyramid (lines 167, 176, 188) in this same file. Calling these on a disposed modality will pass a stale/invalid handle to native code instead of raising a clean ObjectDisposedException.

🛡️ Proposed fix
     public QuantizedPyramid Process(Mat src, Mat? mask = null)
     {
+        ThrowIfDisposed();
         ArgumentNullException.ThrowIfNull(src);
         src.ThrowIfDisposed();
         mask?.ThrowIfDisposed();
         ...
     public void Read(FileNode node)
     {
+        ThrowIfDisposed();
         ArgumentNullException.ThrowIfNull(node);
         ...
     public void Write(FileStorage storage)
     {
+        ThrowIfDisposed();
         ArgumentNullException.ThrowIfNull(storage);
         ...
     private (float Weak, nuint Count, float Strong) Parameters
     {
         get
         {
+            ThrowIfDisposed();
             NativeMethods.HandleException(NativeMethods.rgbd_linemod_ColorGradient_get(

(apply the analogous change to DepthNormal.Parameters.)

As per path instructions: "use the documented Algorithm ownership, disposal, P/Invoke, null-checking, disposal-checking, KeepAlive, OutputArray Fix, and vector-return patterns."

Also applies to: 95-103, 129-137

🤖 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/rgbd/LinemodModality.cs` around lines 52 - 78, Add
ThrowIfDisposed() at the start of Modality.Process, Read, and Write, before
accessing Handle or invoking native methods; apply the same check to the
ColorGradient.Parameters and DepthNormal.Parameters getters. Preserve the
existing argument validation, native calls, and KeepAlive behavior.

Source: Path instructions

@shimat shimat self-assigned this Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant