Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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
);
}
147 changes: 147 additions & 0 deletions src/OpenCvSharp/Modules/barcode/BarcodeDetector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
using OpenCvSharp.Internal;
using OpenCvSharp.Internal.Vectors;

namespace OpenCvSharp;

/// <summary>
/// BarcodeDetector use a super resolution model.
/// super resolution model is applied to zoom in Barcode when it is small.
/// </summary>
public class BarcodeDetector : DisposableCvObject
{
private Ptr? objectPtr;

internal BarcodeDetector(IntPtr ptr)
{
objectPtr = new Ptr(ptr);
this.ptr = objectPtr.Get();
}

/// <summary>
/// Initialize the BarcodeDetector.
/// It includes one models, which are packaged with caffe format.
/// Therefore, there are prototxt and caffe models (In total, four paramenters).
/// </summary>
/// <param name="superResolutionPrototxtPath">prototxt file path for the super resolution model</param>
/// <param name="superResolutionCaffeModelPath">caffe file path for the super resolution model</param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
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);
}

/// <summary>
/// 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.
/// </summary>
/// <param name="thresh">downsampling limit to apply (default 512).</param>
public void SetDownsamplingThreshold(double thresh)
{
NativeMethods.HandleException(
NativeMethods.barcode_BarcodeDetector_setDownsamplingThreshold(ptr, thresh));
GC.KeepAlive(this);
}

/// <summary>
/// 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.
/// </summary>
/// <param name="thresh">gradient magnitude threshold (default 64).</param>
public void SetGradientThreshold(double thresh)
{
NativeMethods.HandleException(
NativeMethods.barcode_BarcodeDetector_setGradientThreshold(ptr, thresh));
GC.KeepAlive(this);
}

/// <summary>
/// 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.
/// </summary>
/// <param name="sizes">box filter sizes, relative to minimum dimension of the image (default [0.01, 0.03, 0.06, 0.08]).</param>
public void SetDetectorScales(IEnumerable<float> 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);
}

/// <summary>
/// Both detects and decodes barcode.
/// To simplify the usage, there is a only API: detectAndDecode
/// </summary>
/// <param name="inputImage">supports grayscale or color(BGR) image.</param>
/// <param name="points">optional output vector of vertices of the found barcode rectangle. Will be empty if not found.</param>
/// <param name="results">list of decoded string.</param>
/// <param name="types">list of decoded types.</param>
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);
}

/// <inheritdoc />
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();
}
}
}
2 changes: 2 additions & 0 deletions src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ copy "$(SolutionDir)opencv_files\opencv_win_x64\x64\vc17\bin\opencv_videoio_ffmp
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="aruco.cpp" />
<ClCompile Include="barcode.cpp" />
<ClCompile Include="bgsegm.cpp" />
<ClCompile Include="calib3d.cpp" />
<ClCompile Include="core.cpp" />
Expand Down Expand Up @@ -263,6 +264,7 @@ copy "$(SolutionDir)opencv_files\opencv_win_x64\x64\vc17\bin\opencv_videoio_ffmp
</ItemGroup>
<ItemGroup>
<ClInclude Include="aruco.h" />
<ClInclude Include="barcode.h" />
<ClInclude Include="bgsegm.h" />
<ClInclude Include="calib3d.h" />
<ClInclude Include="calib3d_fisheye.h" />
Expand Down
6 changes: 6 additions & 0 deletions src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@
<ClCompile Include="wechat_qrcode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="barcode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="bgsegm.h">
Expand Down Expand Up @@ -378,6 +381,9 @@
<ClInclude Include="imgproc_LineSegmentDetector.h">
<Filter>Header Files\imgproc</Filter>
</ClInclude>
<ClInclude Include="barcode.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Source Files">
Expand Down
1 change: 1 addition & 0 deletions src/OpenCvSharpExtern/barcode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "barcode.h"
65 changes: 65 additions & 0 deletions src/OpenCvSharpExtern/barcode.h
Original file line number Diff line number Diff line change
@@ -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<cv::barcode::BarcodeDetector> **returnValue)
{
BEGIN_WRAP
cv::Ptr<cv::barcode::BarcodeDetector> detector;
detector = cv::makePtr<cv::barcode::BarcodeDetector>(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<float> *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<cv::barcode::BarcodeDetector> *obj)
{
BEGIN_WRAP
delete obj;
END_WRAP
}

CVAPI(ExceptionStatus) barcode_Ptr_BarcodeDetector_get(cv::Ptr<cv::barcode::BarcodeDetector> *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<cv::Point2f> *points, std::vector<std::string> *detectorInfos, std::vector<std::string> *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<cv::Point2f> *points, std::vector<std::string> *detectorInfos, std::vector<std::string> *detectorTypes)
{
BEGIN_WRAP
obj->detectAndDecodeWithType(*inputImage, *detectorInfos, *detectorTypes, *points);
END_WRAP
}
24 changes: 14 additions & 10 deletions test/OpenCvSharp.Tests.Windows/OpenCvSharp.Tests.Windows.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,20 @@
<ProjectReference Include="..\..\src\OpenCvSharp.Extensions\OpenCvSharp.Extensions.csproj" />
<ProjectReference Include="..\OpenCvSharp.Tests\OpenCvSharp.Tests.csproj" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net48' ">
<Reference Include="Microsoft.CSharp" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml" />
<Reference Include="WindowsBase" />
<Reference Include="System.Windows.Forms" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net48' ">
<Reference Include="Microsoft.CSharp" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml" />
<Reference Include="WindowsBase" />
<Reference Include="System.Windows.Forms" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0-windows' ">
<PackageReference Include="System.Drawing.Common" Version="8.0.11" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
Expand Down