diff --git a/src/OpenCvSharp/Internal/PInvoke/NativeMethods/objdetect/NativeMethods_FaceDetectorYN.cs b/src/OpenCvSharp/Internal/PInvoke/NativeMethods/objdetect/NativeMethods_FaceDetectorYN.cs new file mode 100644 index 0000000000..e6b8568835 --- /dev/null +++ b/src/OpenCvSharp/Internal/PInvoke/NativeMethods/objdetect/NativeMethods_FaceDetectorYN.cs @@ -0,0 +1,32 @@ +using System.Diagnostics.Contracts; +using System.Runtime.InteropServices; +using OpenCvSharp.Dnn; + +#pragma warning disable 1591 +#pragma warning disable CA1401 // P/Invokes should not be visible +#pragma warning disable CA2101 // Specify marshalling for P-Invoke string arguments (code analysis) +#pragma warning disable IDE1006 // Naming style + +namespace OpenCvSharp.Internal; + +public static partial class NativeMethods +{ + [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern IntPtr cveFaceDetectorYNCreate( + IntPtr model, + IntPtr config, + ref Size inputSize, + float scoreThreshold, + float nmsThreshold, + int topK, + Backend backendId, + Target targetId, + ref IntPtr sharedPtr + ); + + [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern int cveFaceDetectorYNDetect(IntPtr faceDetector, IntPtr image, IntPtr faces); + + [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern void cveFaceDetectorYNRelease(ref IntPtr faceDetector); +} diff --git a/src/OpenCvSharp/Modules/objdetect/FaceDetectorYN.cs b/src/OpenCvSharp/Modules/objdetect/FaceDetectorYN.cs new file mode 100644 index 0000000000..15bc89e783 --- /dev/null +++ b/src/OpenCvSharp/Modules/objdetect/FaceDetectorYN.cs @@ -0,0 +1,82 @@ +using OpenCvSharp.Dnn; +using OpenCvSharp.Internal; + +namespace OpenCvSharp; + +/// +/// DNN-based face detector +/// +public class FaceDetectorYN : DisposableCvObject +{ + /// + /// A pointer to the shared pointer to the unmanaged object + /// + private IntPtr _sharedPtr; + + /// + /// Creates an instance of this class with given parameters. + /// + /// The path to the requested model + /// The path to the config file for compatibility, which is not requested for ONNX models + /// The size of the input image + /// The threshold to filter out bounding boxes of score smaller than the given value + /// The threshold to suppress bounding boxes of IoU bigger than the given value + /// Keep top K bboxes before NMS + /// The id of backend + /// The id of target device + public FaceDetectorYN( + string model, + string config, + Size inputSize, + float scoreThreshold = 0.9f, + float nmsThreshold = 0.3f, + int topK = 5000, + Backend backendId = Backend.DEFAULT, + Target targetId = Target.CPU) + { + using StdString csModel = new(model); + using StdString csConfig = new(config); + + ptr = NativeMethods.cveFaceDetectorYNCreate( + csModel.CvPtr, + csConfig.CvPtr, + ref inputSize, + scoreThreshold, + nmsThreshold, + topK, + backendId, + targetId, + ref _sharedPtr + ); + } + + /// + /// A simple interface to detect face from given image. + /// + /// An image to detect + /// Detection results stored in a Mat + /// 1 if detection is successful, 0 otherwise. + public int Detect(Mat image, Mat faces) + { + ThrowIfDisposed(); + using InputArray iaImage = new(image); + using OutputArray oaFaces = new(faces); + int result = NativeMethods.cveFaceDetectorYNDetect(ptr, iaImage.CvPtr, oaFaces.CvPtr); + GC.KeepAlive(this); + return result; + } + + /// + /// Release the unmanaged memory associated with this FaceDetectorYN + /// + protected override void DisposeUnmanaged() + { + if (!IntPtr.Zero.Equals(_sharedPtr)) + { + NativeMethods.cveFaceDetectorYNRelease(ref _sharedPtr); + _sharedPtr = IntPtr.Zero; + } + + base.DisposeUnmanaged(); + } +} diff --git a/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj b/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj index bbcc1c87a7..3575194492 100644 --- a/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj +++ b/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj @@ -236,6 +236,7 @@ copy "$(SolutionDir)opencv_files\opencv_win_x64\x64\vc17\bin\opencv_videoio_ffmp + @@ -282,6 +283,7 @@ copy "$(SolutionDir)opencv_files\opencv_win_x64\x64\vc17\bin\opencv_videoio_ffmp + diff --git a/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj.filters b/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj.filters index 61f530d2bd..e383d676e8 100644 --- a/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj.filters +++ b/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj.filters @@ -103,6 +103,9 @@ Source Files + + Source Files + @@ -384,6 +387,9 @@ Header Files + + Header Files\objdetect + diff --git a/src/OpenCvSharpExtern/face_detector_yn.cpp b/src/OpenCvSharpExtern/face_detector_yn.cpp new file mode 100644 index 0000000000..a9ce7a4d81 --- /dev/null +++ b/src/OpenCvSharpExtern/face_detector_yn.cpp @@ -0,0 +1,54 @@ +#include "face_detector_yn.h" +#include +#include +#include +#include +#include +#include + +cv::FaceDetectorYN* cveFaceDetectorYNCreate( + cv::String* model, + cv::String* config, + CvSize* inputSize, + float scoreThreshold, + float nmsThreshold, + int topK, + int backendId, + int targetId, + cv::Ptr** sharedPtr) +{ +#ifdef HAVE_OPENCV_OBJDETECT + cv::Ptr ptr = cv::FaceDetectorYN::create( + *model, + *config, + *inputSize, + scoreThreshold, + nmsThreshold, + topK, + backendId, + targetId); + *sharedPtr = new cv::Ptr(ptr); + return (*sharedPtr)->get(); +#else + throw_no_objdetect(); +#endif +} + +void cveFaceDetectorYNRelease(cv::Ptr** faceDetector) +{ +#ifdef HAVE_OPENCV_OBJDETECT + delete* faceDetector; + *faceDetector = 0; +#else + throw_no_objdetect(); +#endif +} + +int cveFaceDetectorYNDetect(cv::FaceDetectorYN* faceDetector, cv::_InputArray* image, cv::_OutputArray* faces) +{ +#ifdef HAVE_OPENCV_OBJDETECT + return faceDetector->detect(*image, *faces); +#else + throw_no_objdetect(); +#endif +} diff --git a/src/OpenCvSharpExtern/face_detector_yn.h b/src/OpenCvSharpExtern/face_detector_yn.h new file mode 100644 index 0000000000..7edd4874ab --- /dev/null +++ b/src/OpenCvSharpExtern/face_detector_yn.h @@ -0,0 +1,34 @@ +#pragma once + +#ifndef NO_OBJDETECT + +// ReSharper disable IdentifierTypo +// ReSharper disable CppInconsistentNaming +// ReSharper disable CppNonInlineFunctionDefinitionInHeaderFile + +#include "my_functions.h" +#include +#include +#include +#include + +#ifndef _WINRT_DLL + +CVAPI(cv::FaceDetectorYN*) cveFaceDetectorYNCreate( + cv::String* model, + cv::String* config, + CvSize* inputSize, + float scoreThreshold, + float nmsThreshold, + int topK, + int backendId, + int targetId, + cv::Ptr** sharedPtr); + +CVAPI(void) cveFaceDetectorYNRelease(cv::Ptr** faceDetector); + +CVAPI(int) cveFaceDetectorYNDetect(cv::FaceDetectorYN* faceDetector, cv::_InputArray* image, cv::_OutputArray* faces); + +#endif + +#endif // NO_OBJDETECT