Skip to content

fix #1830#1832

Merged
shimat merged 2 commits intomainfrom
fix_facedetector_yn_impl
Mar 1, 2026
Merged

fix #1830#1832
shimat merged 2 commits intomainfrom
fix_facedetector_yn_impl

Conversation

@shimat
Copy link
Owner

@shimat shimat commented Mar 1, 2026

Close #1830

Summary

Refactor FaceDetectorYN wrapper to follow the established conventions of this codebase, and fix the NO_OBJDETECT slim-build regression introduced by #1830.

Changes

C++ (OpenCvSharpExtern)

  • Renamed face_detector_yn.{h,cpp}objdetect_FaceDetectorYN.h
    • Inlined the implementation directly into the header, consistent with objdetect_QRCodeDetector.h, objdetect_HOGDescriptor.h, etc.
    • The separate .cpp file is removed; the header is now included from objdetect.cpp
  • Renamed functions to follow the module_ClassName_methodName convention:
    • cveFaceDetectorYNCreateobjdetect_FaceDetectorYN_create
    • cveFaceDetectorYNReleaseobjdetect_Ptr_FaceDetectorYN_delete
    • cveFaceDetectorYNDetectobjdetect_FaceDetectorYN_detect
    • Added objdetect_Ptr_FaceDetectorYN_get for cv::Ptr unwrapping
  • Changed signatures to return ExceptionStatus with BEGIN_WRAP/END_WRAP, matching all other wrappers
  • Used clone() helper for cv::Ptr ownership, consistent with features2d_SIFT_create etc.
  • Fixed NO_OBJDETECT build: the entire header is now guarded by #ifndef NO_OBJDETECT, so slim builds that exclude the objdetect module compile cleanly without stubs or undefined-type references

C# (OpenCvSharp)

  • Renamed NativeMethods_FaceDetectorYN.csNativeMethods_objdetect_FaceDetectorYN.cs
    • [DllImport] entries updated to match new function names and ExceptionStatus-based signatures
  • Rewrote FaceDetectorYN.cs to follow the SIFT / BRISK pattern:
    • Constructor is now private; replaced by a public static FaceDetectorYN Create(...) factory method
    • Memory management uses an inner Ptr class backed by objdetect_Ptr_FaceDetectorYN_get / objdetect_Ptr_FaceDetectorYN_delete, instead of a raw _sharedPtr field with manual lifetime tracking
    • All P/Invoke calls are wrapped with NativeMethods.HandleException(...)

Motivation

The original implementation was contributed by a third party (PR #1830) and fixed a real build failure, but its naming conventions, file layout, error-handling style, and memory-management pattern were inconsistent with the rest of the codebase. This PR retains the intent of the fix while bringing everything in line with the existing conventions.

Summary by CodeRabbit

  • Refactor
    • FaceDetectorYN now uses a static factory method for creation — call FaceDetectorYN.Create(...) instead of the constructor. Detection behavior remains the same.
  • Tests
    • Tests updated to use the new creation pattern and renamed accordingly.

@shimat shimat self-assigned this Mar 1, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 1, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4040e4f and 0cd76af.

📒 Files selected for processing (1)
  • test/OpenCvSharp.Tests/objdetect/FaceDetectorYNTest.cs

📝 Walkthrough

Walkthrough

Refactors FaceDetectorYN interop: removes old cve_* P/Invoke and C wrappers, adds objdetect_* C wrappers and new P/Invoke signatures, and converts the managed FaceDetectorYN to a Ptr-backed factory-based implementation with updated lifetime and detect flows.

Changes

Cohort / File(s) Summary
Removed legacy P/Invoke
src/OpenCvSharp/Internal/PInvoke/NativeMethods/objdetect/NativeMethods_FaceDetectorYN.cs
Deleted old cveFaceDetectorYN* DllImport declarations and associated native interop surface.
Added new P/Invoke
src/OpenCvSharp/Internal/PInvoke/NativeMethods/objdetect/NativeMethods_objdetect_FaceDetectorYN.cs
Introduced objdetect_FaceDetectorYN_create, objdetect_Ptr_FaceDetectorYN_delete, objdetect_Ptr_FaceDetectorYN_get, and objdetect_FaceDetectorYN_detect returning ExceptionStatus and using out/ref parameters.
Managed wrapper refactor
src/OpenCvSharp/Modules/objdetect/FaceDetectorYN.cs
Replaced public constructor with Create(...) factory; added internal Ptr wrapper for native cv::Ptr management; changed disposal to use DisposeManaged() and updated Detect() to use new pointer flow.
Removed old C++ wrappers
src/OpenCvSharpExtern/face_detector_yn.cpp, src/OpenCvSharpExtern/face_detector_yn.h
Deleted legacy C-style wrappers (cveFaceDetectorYNCreate/Detect/Release) and their header declarations.
Added new C++ wrappers
src/OpenCvSharpExtern/objdetect_FaceDetectorYN.h
Added objdetect_FaceDetectorYN_create, objdetect_Ptr_FaceDetectorYN_delete, objdetect_Ptr_FaceDetectorYN_get, and objdetect_FaceDetectorYN_detect with ExceptionStatus wrappers and NO_OBJDETECT guards.
Build/project updates
src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj, src/OpenCvSharpExtern/objdetect.cpp
Replaced references to old face_detector_yn files with objdetect_FaceDetectorYN.h and added its include in objdetect.cpp.
Tests updated
test/OpenCvSharp.Tests/objdetect/FaceDetectorYNTest.cs
Switched tests to use FaceDetectorYN.Create(...); renamed several test methods to new naming.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Test as Client/Test
    participant Managed as FaceDetectorYN (managed)
    participant PInvoke as NativeMethods (P/Invoke)
    participant Extern as OpenCvSharpExtern (C API)
    participant OpenCV as OpenCV::FaceDetectorYN

    Test->>Managed: FaceDetectorYN.Create(model, config, inputSize, ...)
    Managed->>PInvoke: objdetect_FaceDetectorYN_create(...)
    PInvoke->>Extern: call objdetect_FaceDetectorYN_create C wrapper
    Extern->>OpenCV: cv::FaceDetectorYN::create(...)
    OpenCV-->>Extern: cv::Ptr<cv::FaceDetectorYN> (wrapped)
    Extern-->>PInvoke: ExceptionStatus + out ptr
    PInvoke-->>Managed: return pointer
    Managed->>Managed: store Ptr wrapper
    Test->>Managed: Detect(image)
    Managed->>PInvoke: objdetect_Ptr_FaceDetectorYN_get(ptr)
    PInvoke->>Extern: objdetect_Ptr_FaceDetectorYN_get
    Extern->>OpenCV: return raw cv::FaceDetectorYN*
    Managed->>PInvoke: objdetect_FaceDetectorYN_detect(obj, image, faces, out rv)
    PInvoke->>Extern: call detect wrapper
    Extern->>OpenCV: obj->detect(...)
    OpenCV-->>Extern: faces
    Extern-->>PInvoke: ExceptionStatus + return value
    PInvoke-->>Managed: detection result
    Managed->>PInvoke: objdetect_Ptr_FaceDetectorYN_delete(ptr)  (on dispose)
    PInvoke->>Extern: delete cv::Ptr
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.53% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The PR title 'fix #1830' is vague and generic; it only references an issue number without conveying what the actual change accomplishes. Consider using a more descriptive title like 'Refactor FaceDetectorYN to follow repository conventions and fix NO_OBJDETECT compatibility' that summarizes the primary change.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR successfully addresses issue #1830 by refactoring FaceDetectorYN to accept NO_OBJDETECT, preventing build regressions in slimmed-down builds.
Out of Scope Changes check ✅ Passed All changes directly support the NO_OBJDETECT compatibility fix and repository convention alignment; test updates are appropriately scoped to the refactored API.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix_facedetector_yn_impl

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
src/OpenCvSharp/Internal/PInvoke/NativeMethods/objdetect/NativeMethods_objdetect_FaceDetectorYN.cs (1)

25-26: [Pure] attribute is incorrect on the delete method.

The objdetect_Ptr_FaceDetectorYN_delete method has side effects (memory deallocation), so the [Pure] attribute is semantically misleading. The [Pure] attribute indicates a method has no observable side effects, which is not the case for a delete operation.

Suggested fix
-    [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true, ExactSpelling = true)]
+    [DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true, ExactSpelling = true)]
     public static extern ExceptionStatus objdetect_Ptr_FaceDetectorYN_delete(IntPtr ptr);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/OpenCvSharp/Internal/PInvoke/NativeMethods/objdetect/NativeMethods_objdetect_FaceDetectorYN.cs`
around lines 25 - 26, The method declaration for
objdetect_Ptr_FaceDetectorYN_delete incorrectly has the [Pure] attribute despite
performing side effects (memory deallocation); remove the [Pure] attribute from
the extern method declaration so the signature only includes the DllImport and
other relevant attributes, ensuring objdetect_Ptr_FaceDetectorYN_delete no
longer claims purity.
src/OpenCvSharp/Modules/objdetect/FaceDetectorYN.cs (1)

81-86: Consider nulling ptr after disposing detectorPtr.

After detectorPtr?.Dispose() is called, the inherited ptr field still holds a raw pointer that becomes dangling. While detectorPtr is set to null, ptr remains set. If any code path accesses ptr after disposal (despite ThrowIfDisposed checks), it could lead to undefined behavior.

Suggested fix
     protected override void DisposeManaged()
     {
         detectorPtr?.Dispose();
         detectorPtr = null;
+        ptr = IntPtr.Zero;
         base.DisposeManaged();
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/OpenCvSharp/Modules/objdetect/FaceDetectorYN.cs` around lines 81 - 86, In
DisposeManaged of FaceDetectorYN, after calling detectorPtr?.Dispose() and
before/after nulling detectorPtr, also set the inherited raw pointer field ptr
to IntPtr.Zero (or null equivalent) so the dangling native pointer is cleared;
update DisposeManaged to null detectorPtr and then assign ptr = IntPtr.Zero to
prevent any access to a stale pointer (ensure this change preserves calls to
base.DisposeManaged and still allows ThrowIfDisposed to function correctly).
src/OpenCvSharpExtern/objdetect_FaceDetectorYN.h (1)

42-48: Consider adding null check before dereferencing ptr.

The objdetect_Ptr_FaceDetectorYN_get function dereferences ptr without a null check. While the managed code should ensure valid pointers are passed, defensive programming could prevent crashes from invalid states.

Optional defensive fix
 CVAPI(ExceptionStatus) objdetect_Ptr_FaceDetectorYN_get(
     cv::Ptr<cv::FaceDetectorYN>* ptr, cv::FaceDetectorYN** returnValue)
 {
     BEGIN_WRAP
+    if (!ptr) {
+        *returnValue = nullptr;
+        return ExceptionStatus::Occurred;
+    }
     *returnValue = ptr->get();
     END_WRAP
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/OpenCvSharpExtern/objdetect_FaceDetectorYN.h` around lines 42 - 48, The
objdetect_Ptr_FaceDetectorYN_get function dereferences ptr without validation;
add checks in objdetect_Ptr_FaceDetectorYN_get to verify ptr is not null and
ptr->get() is not null before assigning to *returnValue, and if either is null
set *returnValue = nullptr and return the appropriate error ExceptionStatus (or
use the existing error handling macros used by BEGIN_WRAP/END_WRAP) so you avoid
undefined dereference in cv::Ptr<cv::FaceDetectorYN>* ptr and when calling
ptr->get().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@src/OpenCvSharp/Internal/PInvoke/NativeMethods/objdetect/NativeMethods_objdetect_FaceDetectorYN.cs`:
- Around line 25-26: The method declaration for
objdetect_Ptr_FaceDetectorYN_delete incorrectly has the [Pure] attribute despite
performing side effects (memory deallocation); remove the [Pure] attribute from
the extern method declaration so the signature only includes the DllImport and
other relevant attributes, ensuring objdetect_Ptr_FaceDetectorYN_delete no
longer claims purity.

In `@src/OpenCvSharp/Modules/objdetect/FaceDetectorYN.cs`:
- Around line 81-86: In DisposeManaged of FaceDetectorYN, after calling
detectorPtr?.Dispose() and before/after nulling detectorPtr, also set the
inherited raw pointer field ptr to IntPtr.Zero (or null equivalent) so the
dangling native pointer is cleared; update DisposeManaged to null detectorPtr
and then assign ptr = IntPtr.Zero to prevent any access to a stale pointer
(ensure this change preserves calls to base.DisposeManaged and still allows
ThrowIfDisposed to function correctly).

In `@src/OpenCvSharpExtern/objdetect_FaceDetectorYN.h`:
- Around line 42-48: The objdetect_Ptr_FaceDetectorYN_get function dereferences
ptr without validation; add checks in objdetect_Ptr_FaceDetectorYN_get to verify
ptr is not null and ptr->get() is not null before assigning to *returnValue, and
if either is null set *returnValue = nullptr and return the appropriate error
ExceptionStatus (or use the existing error handling macros used by
BEGIN_WRAP/END_WRAP) so you avoid undefined dereference in
cv::Ptr<cv::FaceDetectorYN>* ptr and when calling ptr->get().

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between df8e814 and 4040e4f.

📒 Files selected for processing (8)
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/objdetect/NativeMethods_FaceDetectorYN.cs
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/objdetect/NativeMethods_objdetect_FaceDetectorYN.cs
  • src/OpenCvSharp/Modules/objdetect/FaceDetectorYN.cs
  • src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj
  • src/OpenCvSharpExtern/face_detector_yn.cpp
  • src/OpenCvSharpExtern/face_detector_yn.h
  • src/OpenCvSharpExtern/objdetect.cpp
  • src/OpenCvSharpExtern/objdetect_FaceDetectorYN.h
💤 Files with no reviewable changes (3)
  • src/OpenCvSharp/Internal/PInvoke/NativeMethods/objdetect/NativeMethods_FaceDetectorYN.cs
  • src/OpenCvSharpExtern/face_detector_yn.h
  • src/OpenCvSharpExtern/face_detector_yn.cpp

@shimat shimat merged commit 769347a into main Mar 1, 2026
9 checks passed
@shimat shimat deleted the fix_facedetector_yn_impl branch March 1, 2026 13:04
@coderabbitai coderabbitai bot mentioned this pull request Mar 1, 2026
@cnayan
Copy link
Contributor

cnayan commented Mar 1, 2026

Please create a new release @shimat and thus new NuGet version. Thanks!

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.

2 participants