diff --git a/src/OpenCvSharp/Internal/PInvoke/NativeMethods/NativeMethods_barcode.cs b/src/OpenCvSharp/Internal/PInvoke/NativeMethods/NativeMethods_barcode.cs new file mode 100644 index 000000000..8d15e9d6d --- /dev/null +++ b/src/OpenCvSharp/Internal/PInvoke/NativeMethods/NativeMethods_barcode.cs @@ -0,0 +1,66 @@ +using System.Diagnostics.Contracts; +using System.Runtime.InteropServices; +#pragma warning disable 1591 +#pragma warning disable CA1401 // P/Invokes should not be visible +#pragma warning disable CA1707 // Underscore +#pragma warning disable CA2101 // Specify marshaling for P/Invoke string arguments +#pragma warning disable IDE1006 // Naming style + + +namespace OpenCvSharp.Internal; + +static partial class NativeMethods +{ + + [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern ExceptionStatus barcode_BarcodeDetector_create( + [MarshalAs(UnmanagedType.LPStr)] string super_resolution_prototxt_path, + [MarshalAs(UnmanagedType.LPStr)] string super_resolution_caffe_model_path, + out IntPtr ptr + ); + + [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern ExceptionStatus barcode_BarcodeDetector_setDownsamplingThreshold( + IntPtr obj, + double thresh + ); + + [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern ExceptionStatus barcode_BarcodeDetector_setDetectorScales( + IntPtr obj, + IntPtr sizes + ); + + [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern ExceptionStatus barcode_BarcodeDetector_setGradientThreshold( + IntPtr obj, + double thresh + ); + + [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern ExceptionStatus barcode_Ptr_BarcodeDetector_get( + IntPtr ptr, + out IntPtr ret + ); + + [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern ExceptionStatus barcode_Ptr_BarcodeDetector_delete(IntPtr ptr); + + [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern ExceptionStatus barcode_BarcodeDetector_decodeWithType( + IntPtr obj, + IntPtr inputImage, + IntPtr points, + IntPtr infos, + IntPtr types + ); + + [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern ExceptionStatus barcode_BarcodeDetector_detectAndDecodeWithType( + IntPtr obj, + IntPtr inputImage, + IntPtr points, + IntPtr infos, + IntPtr types + ); +} diff --git a/src/OpenCvSharp/Modules/barcode/BarcodeDetector.cs b/src/OpenCvSharp/Modules/barcode/BarcodeDetector.cs new file mode 100644 index 000000000..8e9141e7a --- /dev/null +++ b/src/OpenCvSharp/Modules/barcode/BarcodeDetector.cs @@ -0,0 +1,147 @@ +using OpenCvSharp.Internal; +using OpenCvSharp.Internal.Vectors; + +namespace OpenCvSharp; + +/// +/// BarcodeDetector use a super resolution model. +/// super resolution model is applied to zoom in Barcode when it is small. +/// +public class BarcodeDetector : DisposableCvObject +{ + private Ptr? objectPtr; + + internal BarcodeDetector(IntPtr ptr) + { + objectPtr = new Ptr(ptr); + this.ptr = objectPtr.Get(); + } + + /// + /// Initialize the BarcodeDetector. + /// It includes one models, which are packaged with caffe format. + /// Therefore, there are prototxt and caffe models (In total, four paramenters). + /// + /// prototxt file path for the super resolution model + /// caffe file path for the super resolution model + /// + /// + public static BarcodeDetector Create( + string superResolutionPrototxtPath, + string superResolutionCaffeModelPath) + { + if (string.IsNullOrWhiteSpace(superResolutionPrototxtPath)) + throw new ArgumentException("empty string", nameof(superResolutionPrototxtPath)); + if (string.IsNullOrWhiteSpace(superResolutionCaffeModelPath)) + throw new ArgumentException("empty string", nameof(superResolutionCaffeModelPath)); + + NativeMethods.HandleException( + NativeMethods.barcode_BarcodeDetector_create( + superResolutionPrototxtPath, superResolutionCaffeModelPath, + out var ptr)); + + return new BarcodeDetector(ptr); + } + + /// + /// Set detector downsampling threshold. + /// + /// By default, the detect method resizes the input image to this limit if the smallest image size is is greater than the threshold. + /// Increasing this value can improve detection accuracy and the number of results at the expense of performance. + /// Correlates with detector scales.Setting this to a large value will disable downsampling. + /// + /// downsampling limit to apply (default 512). + public void SetDownsamplingThreshold(double thresh) + { + NativeMethods.HandleException( + NativeMethods.barcode_BarcodeDetector_setDownsamplingThreshold(ptr, thresh)); + GC.KeepAlive(this); + } + + /// + /// Set detector gradient magnitude threshold. + /// + /// Sets the coherence threshold for detected bounding boxes. + /// Increasing this value will generate a closer fitted bounding box width and can reduce false-positives. + /// Values between 16 and 1024 generally work, while too high of a value will remove valid detections. + /// + /// gradient magnitude threshold (default 64). + public void SetGradientThreshold(double thresh) + { + NativeMethods.HandleException( + NativeMethods.barcode_BarcodeDetector_setGradientThreshold(ptr, thresh)); + GC.KeepAlive(this); + } + + /// + /// Set detector box filter sizes. + /// + /// Adjusts the value and the number of box filters used in the detect step. + /// The filter sizes directly correlate with the expected line widths for a barcode.Corresponds to expected barcode distance. + /// If the downsampling limit is increased, filter sizes need to be adjusted in an inversely proportional way. + /// + /// box filter sizes, relative to minimum dimension of the image (default [0.01, 0.03, 0.06, 0.08]). + public void SetDetectorScales(IEnumerable sizes) + { + if (sizes is null) + throw new ArgumentNullException(nameof(sizes)); + using var sizesVec = new VectorOfFloat(sizes); + NativeMethods.HandleException( + NativeMethods.barcode_BarcodeDetector_setDetectorScales(ptr, sizesVec.CvPtr)); + GC.KeepAlive(this); + } + + /// + /// Both detects and decodes barcode. + /// To simplify the usage, there is a only API: detectAndDecode + /// + /// supports grayscale or color(BGR) image. + /// optional output vector of vertices of the found barcode rectangle. Will be empty if not found. + /// list of decoded string. + /// list of decoded types. + public void DetectAndDecode(InputArray inputImage, out Point2f[] points, out string[] results, out string[] types) + { + if (inputImage is null) + throw new ArgumentNullException(nameof(inputImage)); + inputImage.ThrowIfDisposed(); + + using var pointsVec = new VectorOfPoint2f(); + using var infos = new VectorOfString(); + using var resultTypes = new VectorOfString(); + NativeMethods.HandleException( + NativeMethods.barcode_BarcodeDetector_detectAndDecodeWithType( + ptr, inputImage.CvPtr, pointsVec.CvPtr, infos.CvPtr, resultTypes.CvPtr)); + + points = pointsVec.ToArray(); + results = infos.ToArray(); + types = resultTypes.ToArray(); + GC.KeepAlive(this); + GC.KeepAlive(inputImage); + } + + /// + protected override void DisposeManaged() + { + objectPtr?.Dispose(); + objectPtr = null; + base.DisposeManaged(); + } + + internal class Ptr(IntPtr ptr) : OpenCvSharp.Ptr(ptr) + { + public override IntPtr Get() + { + NativeMethods.HandleException( + NativeMethods.barcode_Ptr_BarcodeDetector_get(ptr, out var ret)); + GC.KeepAlive(this); + return ret; + } + + protected override void DisposeUnmanaged() + { + NativeMethods.HandleException( + NativeMethods.barcode_Ptr_BarcodeDetector_delete(ptr)); + base.DisposeUnmanaged(); + } + } +} diff --git a/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj b/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj index 9644d3992..d0f1e82b1 100644 --- a/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj +++ b/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj @@ -228,6 +228,7 @@ copy "$(SolutionDir)opencv_files\opencv_win_x64\x64\vc17\bin\opencv_videoio_ffmp + @@ -263,6 +264,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 b9c96c843..61f530d2b 100644 --- a/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj.filters +++ b/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj.filters @@ -100,6 +100,9 @@ Source Files + + Source Files + @@ -378,6 +381,9 @@ Header Files\imgproc + + Header Files + diff --git a/src/OpenCvSharpExtern/barcode.cpp b/src/OpenCvSharpExtern/barcode.cpp new file mode 100644 index 000000000..38e1e4cfe --- /dev/null +++ b/src/OpenCvSharpExtern/barcode.cpp @@ -0,0 +1 @@ +#include "barcode.h" diff --git a/src/OpenCvSharpExtern/barcode.h b/src/OpenCvSharpExtern/barcode.h new file mode 100644 index 000000000..430ad2369 --- /dev/null +++ b/src/OpenCvSharpExtern/barcode.h @@ -0,0 +1,65 @@ +#pragma once + +#include "include_opencv.h" + +CVAPI(ExceptionStatus) barcode_BarcodeDetector_create(const char *super_resolution_prototxt_path, + const char *super_resolution_caffe_model_path, cv::Ptr **returnValue) +{ + BEGIN_WRAP + cv::Ptr detector; + detector = cv::makePtr(super_resolution_prototxt_path, super_resolution_caffe_model_path); + *returnValue = clone(detector); + END_WRAP +} + +CVAPI(ExceptionStatus) barcode_BarcodeDetector_setDownsamplingThreshold(cv::barcode::BarcodeDetector *obj, double thresh) +{ + BEGIN_WRAP + obj->setDownsamplingThreshold(thresh); + END_WRAP +} + +CVAPI(ExceptionStatus) barcode_BarcodeDetector_setDetectorScales(cv::barcode::BarcodeDetector *obj, std::vector *sizes) +{ + BEGIN_WRAP + obj->setDetectorScales(*sizes); + END_WRAP +} + +CVAPI(ExceptionStatus) barcode_BarcodeDetector_setGradientThreshold(cv::barcode::BarcodeDetector *obj, double thresh) +{ + BEGIN_WRAP + obj->setGradientThreshold(thresh); + END_WRAP +} + + +CVAPI(ExceptionStatus) barcode_Ptr_BarcodeDetector_delete(cv::Ptr *obj) +{ + BEGIN_WRAP + delete obj; + END_WRAP +} + +CVAPI(ExceptionStatus) barcode_Ptr_BarcodeDetector_get(cv::Ptr *obj, cv::barcode::BarcodeDetector **returnValue) +{ + BEGIN_WRAP + *returnValue = obj->get(); + END_WRAP +} + +CVAPI(ExceptionStatus) barcode_BarcodeDetector_decodeWithType(cv::barcode::BarcodeDetector *obj, cv::_InputArray *inputImage, + std::vector *points, std::vector *detectorInfos, std::vector *detectorTypes) +{ + BEGIN_WRAP + obj->decodeWithType(*inputImage, *points, *detectorInfos, *detectorTypes); + END_WRAP +} + +CVAPI(ExceptionStatus) barcode_BarcodeDetector_detectAndDecodeWithType(cv::barcode::BarcodeDetector *obj, cv::_InputArray *inputImage, + std::vector *points, std::vector *detectorInfos, std::vector *detectorTypes) +{ + BEGIN_WRAP + obj->detectAndDecodeWithType(*inputImage, *detectorInfos, *detectorTypes, *points); + END_WRAP +} diff --git a/test/OpenCvSharp.Tests.Windows/OpenCvSharp.Tests.Windows.csproj b/test/OpenCvSharp.Tests.Windows/OpenCvSharp.Tests.Windows.csproj index d5f0cf966..12a44c7d9 100644 --- a/test/OpenCvSharp.Tests.Windows/OpenCvSharp.Tests.Windows.csproj +++ b/test/OpenCvSharp.Tests.Windows/OpenCvSharp.Tests.Windows.csproj @@ -20,16 +20,20 @@ - - - - - - - - - - + + + + + + + + + + + + + +