diff --git a/.gitignore b/.gitignore
index 8db36956e..dc02f824b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -129,6 +129,11 @@ work_dirs/
/cmake-build-debug*
/cmake-build-release*
+# c#
+.vs/
+obj/
+bin/
+
# install directory
/install
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 69b30a9f6..990052e36 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,6 +28,7 @@ set(MMDEPLOY_TARGET_DEVICES
"cpu" CACHE STRING "MMDeploy's target devices")
set(MMDEPLOY_TARGET_BACKENDS "" CACHE STRING "MMDeploy's target inference engines")
set(MMDEPLOY_CODEBASES "all" CACHE STRING "select OpenMMLab's codebases")
+set(MMDEPLOY_BUILD_SDK_CSHARP_API "build MMDeployExtern.dll for C# API" OFF)
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "choose 'Release' as default build type" FORCE)
diff --git a/csrc/apis/c/CMakeLists.txt b/csrc/apis/c/CMakeLists.txt
index 9cb94ebbd..0c2957ca1 100644
--- a/csrc/apis/c/CMakeLists.txt
+++ b/csrc/apis/c/CMakeLists.txt
@@ -46,3 +46,14 @@ endforeach ()
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/common.h
DESTINATION include/c)
+
+if (MMDEPLOY_BUILD_SDK_CSHARP_API)
+ # build MMDeployExtern.dll just for csharp nuget package.
+ # no Installation for c/c++ package.
+ file(GLOB SRCS "*.c" "*.cpp")
+ add_library(MMDeployExtern SHARED ${SRCS})
+ target_compile_definitions(MMDeployExtern PRIVATE -DMMDEPLOY_API_EXPORTS=1)
+ mmdeploy_load_static(MMDeployExtern MMDeployStaticModules)
+ mmdeploy_load_dynamic(MMDeployExtern MMDeployDynamicModules)
+ target_link_libraries(MMDeployExtern PRIVATE MMDeployLibs)
+endif()
diff --git a/csrc/apis/csharp/MMDeploy.sln b/csrc/apis/csharp/MMDeploy.sln
new file mode 100644
index 000000000..accd1cb56
--- /dev/null
+++ b/csrc/apis/csharp/MMDeploy.sln
@@ -0,0 +1,50 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31729.503
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MMDeploy", "MMDeploy\MMDeploy.csproj", "{3DC914EB-A8FB-4A89-A7CF-7DF9CC5284A6}"
+EndProject
+
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3DC914EB-A8FB-4A89-A7CF-7DF9CC5284A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3DC914EB-A8FB-4A89-A7CF-7DF9CC5284A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3DC914EB-A8FB-4A89-A7CF-7DF9CC5284A6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {3DC914EB-A8FB-4A89-A7CF-7DF9CC5284A6}.Debug|x64.Build.0 = Debug|Any CPU
+ {3DC914EB-A8FB-4A89-A7CF-7DF9CC5284A6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {3DC914EB-A8FB-4A89-A7CF-7DF9CC5284A6}.Debug|x86.Build.0 = Debug|Any CPU
+ {3DC914EB-A8FB-4A89-A7CF-7DF9CC5284A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3DC914EB-A8FB-4A89-A7CF-7DF9CC5284A6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3DC914EB-A8FB-4A89-A7CF-7DF9CC5284A6}.Release|x64.ActiveCfg = Release|Any CPU
+ {3DC914EB-A8FB-4A89-A7CF-7DF9CC5284A6}.Release|x64.Build.0 = Release|Any CPU
+ {3DC914EB-A8FB-4A89-A7CF-7DF9CC5284A6}.Release|x86.ActiveCfg = Release|Any CPU
+ {3DC914EB-A8FB-4A89-A7CF-7DF9CC5284A6}.Release|x86.Build.0 = Release|Any CPU
+ {661A4295-68CF-41C6-85B8-B11748113A6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {661A4295-68CF-41C6-85B8-B11748113A6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {661A4295-68CF-41C6-85B8-B11748113A6F}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {661A4295-68CF-41C6-85B8-B11748113A6F}.Debug|x64.Build.0 = Debug|Any CPU
+ {661A4295-68CF-41C6-85B8-B11748113A6F}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {661A4295-68CF-41C6-85B8-B11748113A6F}.Debug|x86.Build.0 = Debug|Any CPU
+ {661A4295-68CF-41C6-85B8-B11748113A6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {661A4295-68CF-41C6-85B8-B11748113A6F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {661A4295-68CF-41C6-85B8-B11748113A6F}.Release|x64.ActiveCfg = Release|Any CPU
+ {661A4295-68CF-41C6-85B8-B11748113A6F}.Release|x64.Build.0 = Release|Any CPU
+ {661A4295-68CF-41C6-85B8-B11748113A6F}.Release|x86.ActiveCfg = Release|Any CPU
+ {661A4295-68CF-41C6-85B8-B11748113A6F}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {5E63FEFB-A55D-4BEB-83B8-7D0E5A59EBF7}
+ EndGlobalSection
+EndGlobal
diff --git a/csrc/apis/csharp/MMDeploy/.editorconfig b/csrc/apis/csharp/MMDeploy/.editorconfig
new file mode 100644
index 000000000..2a769013f
--- /dev/null
+++ b/csrc/apis/csharp/MMDeploy/.editorconfig
@@ -0,0 +1,110 @@
+[*.cs]
+csharp_style_var_for_built_in_types=true:silent
+csharp_style_var_when_type_is_apparent=true:silent
+csharp_style_var_elsewhere=true:silent
+
+##
+## StyleCop.Analyzers
+##
+
+# Using directive should appear within a namespace declaration
+dotnet_diagnostic.SA1200.severity = None
+
+# XML comment analysis is disabled due to project configuration
+dotnet_diagnostic.SA0001.severity = None
+
+# The file header is missing or not located at the Top of the file
+dotnet_diagnostic.SA1633.severity = None
+
+# Use string.Empty for empty strings
+dotnet_diagnostic.SA1122.severity = None
+
+# Variable '_' should begin with lower-case letter
+dotnet_diagnostic.SA1312.severity = None
+
+# Parameter '_' should begin with lower-case letter
+dotnet_diagnostic.SA1313.severity = None
+
+# Elements should be documented
+dotnet_diagnostic.SA1600.severity = None
+
+# Prefix local calls with this
+dotnet_diagnostic.SA1101.severity = None
+
+# 'public' members should come before 'private' members
+dotnet_diagnostic.SA1202.severity = None
+
+# Comments should contain text
+dotnet_diagnostic.SA1120.severity = None
+
+# Constant fields should appear before non-constant fields
+dotnet_diagnostic.SA1203.severity = None
+
+# Field '_blah' should not begin with an underscore
+dotnet_diagnostic.SA1309.severity = None
+
+# Use trailing comma in multi-line initializers
+dotnet_diagnostic.SA1413.severity = None
+
+# A method should not follow a class
+dotnet_diagnostic.SA1201.severity = None
+
+# Elements should be separated by blank line
+dotnet_diagnostic.SA1516.severity = None
+
+# The parameter spans multiple lines
+dotnet_diagnostic.SA1118.severity = None
+
+# Static members should appear before non-static members
+dotnet_diagnostic.SA1204.severity = None
+
+# Put constructor initializers on their own line
+dotnet_diagnostic.SA1128.severity = None
+
+# Opening braces should not be preceded by blank line
+dotnet_diagnostic.SA1509.severity = None
+
+# The parameter should begin on the line after the previous parameter
+dotnet_diagnostic.SA1115.severity = None
+
+# File name should match first type name
+dotnet_diagnostic.SA1649.severity = None
+
+# File may only contain a single type
+dotnet_diagnostic.SA1402.severity = None
+
+# Enumeration items should be documented
+dotnet_diagnostic.SA1602.severity = None
+
+# Element should not be on a single line
+dotnet_diagnostic.SA1502.severity = None
+
+# Closing parenthesis should not be preceded by a space
+dotnet_diagnostic.SA1009.severity = None
+
+# Closing parenthesis should be on line of last parameter
+dotnet_diagnostic.SA1111.severity = None
+
+# Braces should not be ommitted
+dotnet_diagnostic.SA1503.severity = None
+
+# The name of a C# element does not begin with an upper-case letter
+# dotnet_diagnostic.SA1300.severity = None
+
+# The name of a public or internal field in C# does not begin with an upper-case letter
+# dotnet_diagnostic.SA1307.severity = None
+
+# The code uses one of the basic C# types, but does not use the built-in alias for the type
+# dotnet_diagnostic.SA1121.severity = None
+
+# Two or more attributes appeared within the same set of square brackets.
+dotnet_diagnostic.SA1133.severity = None
+
+# The C# code contains a region.
+dotnet_diagnostic.SA1124.severity = None
+
+# The parameters to a C# method or indexer call or declaration span across multiple lines, but the first parameter does not start on the line after the opening bracket.
+dotnet_diagnostic.SA1116.severity = None
+
+# The parameters to a C# method or indexer call or declaration are not all on the same line or each on a separate line.
+dotnet_diagnostic.SA1117.severity = None
diff --git a/csrc/apis/csharp/MMDeploy/APIs/Classifier.cs b/csrc/apis/csharp/MMDeploy/APIs/Classifier.cs
new file mode 100644
index 000000000..5bdb15544
--- /dev/null
+++ b/csrc/apis/csharp/MMDeploy/APIs/Classifier.cs
@@ -0,0 +1,135 @@
+using System.Collections.Generic;
+
+namespace MMDeploy
+{
+ ///
+ /// Single classification result of a picture.
+ /// A picture may contains multiple reuslts.
+ ///
+ public struct Label
+ {
+ ///
+ /// Id.
+ ///
+ public int Id;
+
+ ///
+ /// Score.
+ ///
+ public float Score;
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// id.
+ /// score.
+ public Label(int id, float score)
+ {
+ Id = id;
+ Score = score;
+ }
+ }
+
+ ///
+ /// Output of Classifier.
+ ///
+ public struct ClassifierOutput
+ {
+ ///
+ /// Classification results for single image.
+ ///
+ public List Results;
+
+ ///
+ /// Add result to single image.
+ ///
+ /// id.
+ /// score.
+ public void Add(int id, float score)
+ {
+ if (Results == null)
+ {
+ Results = new List();
+ }
+
+ Results.Add(new Label(id, score));
+ }
+
+ ///
+ /// Gets number of output.
+ ///
+ public int Count
+ {
+ get { return (Results == null) ? 0 : Results.Count; }
+ }
+ }
+
+ ///
+ /// classifier.
+ ///
+ public class Classifier : DisposableObject
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// model path.
+ /// device name.
+ /// deviceId.
+ public Classifier(string modelPath, string deviceName, int deviceId)
+ {
+ ThrowException(NativeMethods.mmdeploy_classifier_create_by_path(modelPath, deviceName, deviceId, out _handle));
+ }
+
+ ///
+ /// Get label information of each image in a batch.
+ ///
+ /// input mats.
+ /// Results of each input mat.
+ public List Apply(Mat[] mats)
+ {
+ List output = new List();
+ unsafe
+ {
+ Label* results = null;
+ int* resultCount = null;
+ fixed (Mat* _mats = mats)
+ {
+ ThrowException(NativeMethods.mmdeploy_classifier_apply(_handle, _mats, mats.Length, &results, &resultCount));
+ }
+
+ FormatResult(mats.Length, resultCount, results, ref output, out var total);
+ ReleaseResult(results, resultCount, total);
+ }
+
+ return output;
+ }
+
+ private unsafe void FormatResult(int matCount, int* resultCount, Label* results, ref List output, out int total)
+ {
+ total = 0;
+ for (int i = 0; i < matCount; i++)
+ {
+ ClassifierOutput outi = default;
+ for (int j = 0; j < resultCount[i]; j++)
+ {
+ outi.Add(results->Id, results->Score);
+ results++;
+ total++;
+ }
+
+ output.Add(outi);
+ }
+ }
+
+ private unsafe void ReleaseResult(Label* results, int* resultCount, int count)
+ {
+ NativeMethods.mmdeploy_classifier_release_result(results, resultCount, count);
+ }
+
+ ///
+ protected override void ReleaseHandle()
+ {
+ NativeMethods.mmdeploy_classifier_destroy(_handle);
+ }
+ }
+}
diff --git a/csrc/apis/csharp/MMDeploy/APIs/Detector.cs b/csrc/apis/csharp/MMDeploy/APIs/Detector.cs
new file mode 100644
index 000000000..584c63aa8
--- /dev/null
+++ b/csrc/apis/csharp/MMDeploy/APIs/Detector.cs
@@ -0,0 +1,234 @@
+using System;
+using System.Collections.Generic;
+
+namespace MMDeploy
+{
+#pragma warning disable 0649
+ ///
+ /// mm_instance_mask_t of c code.
+ ///
+ internal unsafe struct CInstanceMask
+ {
+ public char* Data;
+ public int Height;
+ public int Width;
+ }
+
+ ///
+ /// mm_detect_t of c code.
+ ///
+ internal unsafe struct CDetect
+ {
+ public int LabelId;
+ public float Score;
+ public Rect BBox;
+ public CInstanceMask* Mask;
+ }
+#pragma warning restore 0649
+
+ ///
+ /// Instance mask.
+ ///
+ public struct InstanceMask
+ {
+ ///
+ /// Height.
+ ///
+ public int Height;
+
+ ///
+ /// Width.
+ ///
+ public int Width;
+
+ ///
+ /// Raw data.
+ ///
+ public byte[] Data;
+ internal unsafe InstanceMask(CInstanceMask* mask)
+ {
+ Height = mask->Height;
+ Width = mask->Width;
+ Data = new byte[Height * Width];
+ fixed (byte* data = this.Data)
+ {
+ Buffer.MemoryCopy(mask->Data, data, Height * Width, Height * Width);
+ }
+ }
+ }
+
+ ///
+ /// Single detection result of a picture.
+ /// A picture may contains multiple reuslts.
+ ///
+ public struct Detect
+ {
+ ///
+ /// Label id.
+ ///
+ public int LabelId;
+
+ ///
+ /// Score.
+ ///
+ public float Score;
+
+ ///
+ /// Bounding box.
+ ///
+ public Rect BBox;
+
+ ///
+ /// Whether has mask.
+ ///
+ public bool HasMask;
+
+ ///
+ /// Mask.
+ ///
+ public InstanceMask Mask;
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// label id.
+ /// score.
+ /// bounding box.
+ public Detect(int labelId, float score, Rect bbox)
+ {
+ LabelId = labelId;
+ Score = score;
+ BBox = bbox;
+ HasMask = false;
+ Mask = default;
+ }
+
+ internal unsafe Detect(CDetect* result) : this(result->LabelId, result->Score, result->BBox)
+ {
+ if (result->Mask != null)
+ {
+ HasMask = true;
+ CInstanceMask* mask = result->Mask;
+ Mask = new InstanceMask(mask);
+ }
+ }
+ }
+
+ ///
+ /// Output of Detector.
+ ///
+ public struct DetectorOutput
+ {
+ ///
+ /// Detection results for single image.
+ ///
+ public List Results;
+
+ ///
+ /// Init Reuslts.
+ ///
+ public void Init()
+ {
+ if (Results == null)
+ {
+ Results = new List();
+ }
+ }
+
+ ///
+ /// Add result to single image.
+ ///
+ /// label id.
+ /// score.
+ /// bounding box.
+ public void Add(int labelId, float score, Rect bbox)
+ {
+ Init();
+ Results.Add(new Detect(labelId, score, bbox));
+ }
+
+ internal unsafe void Add(CDetect* result)
+ {
+ Init();
+ Results.Add(new Detect(result));
+ }
+
+ ///
+ /// Gets number of output.
+ ///
+ public int Count
+ {
+ get { return (Results == null) ? 0 : Results.Count; }
+ }
+ }
+
+ ///
+ /// Detector.
+ ///
+ public class Detector : DisposableObject
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// model path.
+ /// device name.
+ /// device id.
+ public Detector(string modelPath, string deviceName, int deviceId)
+ {
+ ThrowException(NativeMethods.mmdeploy_detector_create_by_path(modelPath, deviceName, deviceId, out _handle));
+ }
+
+ ///
+ /// Get information of each image in a batch.
+ ///
+ /// input mats.
+ /// Results of each input mat.
+ public List Apply(Mat[] mats)
+ {
+ List output = new List();
+
+ unsafe
+ {
+ CDetect* results = null;
+ int* resultCount = null;
+ fixed (Mat* _mats = mats)
+ {
+ ThrowException(NativeMethods.mmdeploy_detector_apply(_handle, _mats, mats.Length, &results, &resultCount));
+ }
+
+ FormatResult(mats.Length, resultCount, results, ref output, out var total);
+ ReleaseResult(results, resultCount, total);
+ }
+
+ return output;
+ }
+
+ private unsafe void FormatResult(int matCount, int* resultCount, CDetect* results, ref List output, out int total)
+ {
+ total = 0;
+ for (int i = 0; i < matCount; i++)
+ {
+ DetectorOutput outi = default;
+ for (int j = 0; j < resultCount[i]; j++)
+ {
+ outi.Add(results);
+ results++;
+ total++;
+ }
+
+ output.Add(outi);
+ }
+ }
+
+ private unsafe void ReleaseResult(CDetect* results, int* resultCount, int count)
+ {
+ NativeMethods.mmdeploy_detector_release_result(results, resultCount, count);
+ }
+
+ ///
+ protected override void ReleaseHandle()
+ {
+ NativeMethods.mmdeploy_detector_destroy(_handle);
+ }
+ }
+}
diff --git a/csrc/apis/csharp/MMDeploy/APIs/DisposableObject.cs b/csrc/apis/csharp/MMDeploy/APIs/DisposableObject.cs
new file mode 100644
index 000000000..b0ab35b0e
--- /dev/null
+++ b/csrc/apis/csharp/MMDeploy/APIs/DisposableObject.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace MMDeploy
+{
+ ///
+ /// Base class which manages its own memory.
+ ///
+ public class DisposableObject : IDisposable
+ {
+#pragma warning disable SA1401 // Fields should be private
+ ///
+ /// Handle pointer.
+ ///
+ protected IntPtr _handle;
+#pragma warning restore SA1401 // Fields should be private
+
+ private bool _disposed = false;
+
+ ///
+ /// Gets a value indicating whether this instance has been disposed.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Close handle.
+ ///
+ public void Close()
+ {
+ Dispose();
+ }
+
+ ///
+ /// Releases the resources.
+ ///
+ private void Dispose(bool disposing)
+ {
+ if (_disposed)
+ {
+ return;
+ }
+
+ if (disposing)
+ {
+ // Free any other managed objects here.
+ ReleaseManaged();
+ }
+
+ // Free any unmanaged objects here.
+ ReleaseHandle();
+
+ _handle = IntPtr.Zero;
+
+ _disposed = true;
+ }
+
+ ///
+ /// Releases managed resources.
+ ///
+ protected virtual void ReleaseManaged()
+ {
+ }
+
+ ///
+ /// Releases unmanaged resources.
+ ///
+ protected virtual void ReleaseHandle()
+ {
+ Marshal.FreeHGlobal(_handle);
+ }
+
+ ///
+ /// Finalizes an instance of the class.
+ ///
+ ~DisposableObject()
+ {
+ Dispose(false);
+ }
+
+ ///
+ /// Throw exception is result is not zero.
+ ///
+ /// function return value.
+ protected static void ThrowException(int result)
+ {
+ if (result != 0)
+ {
+ throw new Exception(result.ToString());
+ }
+ }
+ }
+}
diff --git a/csrc/apis/csharp/MMDeploy/APIs/PoseDetector.cs b/csrc/apis/csharp/MMDeploy/APIs/PoseDetector.cs
new file mode 100644
index 000000000..4e750c1f4
--- /dev/null
+++ b/csrc/apis/csharp/MMDeploy/APIs/PoseDetector.cs
@@ -0,0 +1,199 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace MMDeploy
+{
+#pragma warning disable 0649
+ internal unsafe struct CPoseDetect
+ {
+ public Pointf* Point;
+ public float* Score;
+ public int Length;
+ }
+#pragma warning restore 0649
+
+ ///
+ /// Single detection result of a bbox.
+ /// A picture may contains multiple reuslts.
+ ///
+ public struct PoseDetect
+ {
+ ///
+ /// Keypoins.
+ ///
+ public List Points;
+
+ ///
+ /// Scores.
+ ///
+ public List Scores;
+
+ ///
+ /// Init points and scores if empty.
+ ///
+ private void Init()
+ {
+ if (Points == null || Scores == null)
+ {
+ Points = new List();
+ Scores = new List();
+ }
+ }
+
+ ///
+ /// Add single keypoint to list.
+ ///
+ /// Keypoint.
+ /// Score.
+ public void Add(Pointf point, float score)
+ {
+ Init();
+ Points.Add(point);
+ Scores.Add(score);
+ }
+
+ internal unsafe void Add(Pointf* point, float score)
+ {
+ Init();
+ Points.Add(new Pointf(point->X, point->Y));
+ }
+ }
+
+ ///
+ /// Output of PoseDetector.
+ ///
+ public struct PoseDetectorOutput
+ {
+ ///
+ /// Pose detection results for single image.
+ ///
+ public List Results;
+
+ ///
+ /// Gets number of output.
+ ///
+ public int Count
+ {
+ get { return (Results == null) ? 0 : Results.Count; }
+ }
+
+ ///
+ /// Result for box level.
+ ///
+ /// Box res.
+ public void Add(PoseDetect boxRes)
+ {
+ if (Results == null)
+ {
+ Results = new List();
+ }
+
+ Results.Add(boxRes);
+ }
+ }
+
+ ///
+ /// PoseDetector.
+ ///
+ public class PoseDetector : DisposableObject
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// model path.
+ /// device name.
+ /// device id.
+ public PoseDetector(string modelPath, string deviceName, int deviceId)
+ {
+ ThrowException(NativeMethods.mmdeploy_pose_detector_create_by_path(modelPath, deviceName, deviceId, out _handle));
+ }
+
+ ///
+ /// Get information of each image in a batch.
+ ///
+ /// input mats.
+ /// bounding boxes..
+ /// bounding boxes count for each image.
+ /// Results of each input mat.
+ public List Apply(Mat[] mats, Rect[] bboxes, int[] bboxCount)
+ {
+ List output = new List();
+
+ unsafe
+ {
+ CPoseDetect* results = null;
+ fixed (Mat* _mats = mats)
+ fixed (Rect* _bboxes = bboxes)
+ fixed (int* _bboxCount = bboxCount)
+ {
+ ThrowException(NativeMethods.mmdeploy_pose_detector_apply_bbox(_handle, _mats, mats.Length, _bboxes, _bboxCount, &results));
+ FormatResult(mats.Length, _bboxCount, results, ref output, out var total);
+ ReleaseResult(results, total);
+ }
+ }
+
+ return output;
+ }
+
+ ///
+ /// Get information of each image in a batch.
+ ///
+ /// Input mats.
+ /// Results of each input mat.
+ public List Apply(Mat[] mats)
+ {
+ List output = new List();
+ unsafe
+ {
+ CPoseDetect* results = null;
+ fixed (Mat* _mats = mats)
+ {
+ ThrowException(NativeMethods.mmdeploy_pose_detector_apply(_handle, _mats, mats.Length, &results));
+ }
+
+ int[] _bbox_count = Enumerable.Repeat(1, mats.Length).ToArray();
+ fixed (int* bbox_count = _bbox_count)
+ {
+ FormatResult(mats.Length, bbox_count, results, ref output, out var total);
+ ReleaseResult(results, total);
+ }
+ }
+
+ return output;
+ }
+
+ private unsafe void FormatResult(int matCount, int* bboxCount, CPoseDetect* results, ref List output, out int total)
+ {
+ total = 0;
+ for (int i = 0; i < matCount; i++)
+ {
+ PoseDetectorOutput outi = default;
+ for (int j = 0; j < bboxCount[i]; j++)
+ {
+ PoseDetect boxRes = default;
+ for (int k = 0; k < results->Length; k++)
+ {
+ boxRes.Add(results->Point[k], results->Score[k]);
+ }
+
+ outi.Add(boxRes);
+ results++;
+ total++;
+ }
+
+ output.Add(outi);
+ }
+ }
+
+ private unsafe void ReleaseResult(CPoseDetect* results, int count)
+ {
+ NativeMethods.mmdeploy_pose_detector_release_result(results, count);
+ }
+
+ ///
+ protected override void ReleaseHandle()
+ {
+ NativeMethods.mmdeploy_pose_detector_destroy(_handle);
+ }
+ }
+}
diff --git a/csrc/apis/csharp/MMDeploy/APIs/Restorer.cs b/csrc/apis/csharp/MMDeploy/APIs/Restorer.cs
new file mode 100644
index 000000000..2d2730c60
--- /dev/null
+++ b/csrc/apis/csharp/MMDeploy/APIs/Restorer.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections.Generic;
+
+namespace MMDeploy
+{
+ ///
+ /// Output of Restorer.
+ ///
+ public struct RestorerOutput
+ {
+ ///
+ /// Height.
+ ///
+ public int Height;
+
+ ///
+ /// Width.
+ ///
+ public int Width;
+
+ ///
+ /// Raw data.
+ ///
+ public byte[] Data;
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// height.
+ /// width.
+ /// data.
+ public RestorerOutput(int height, int width, byte[] data)
+ {
+ Height = height;
+ Width = width;
+ Data = new byte[height * width * 3];
+ Array.Copy(data, Data, data.Length);
+ }
+
+ internal unsafe RestorerOutput(Mat* result)
+ {
+ Height = result->Height;
+ Width = result->Width;
+ Data = new byte[Height * Width * 3];
+ int nbytes = Height * Width * 3;
+ fixed (byte* data = this.Data)
+ {
+ Buffer.MemoryCopy(result->Data, data, nbytes, nbytes);
+ }
+ }
+ }
+
+ ///
+ /// Restorer.
+ ///
+ public class Restorer : DisposableObject
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// model path.
+ /// device name.
+ /// device id.
+ public Restorer(string modelPath, string deviceName, int deviceId)
+ {
+ ThrowException(NativeMethods.mmdeploy_restorer_create_by_path(modelPath, deviceName, deviceId, out _handle));
+ }
+
+ ///
+ /// Get information of each image in a batch.
+ ///
+ /// input mats.
+ /// Results of each input mat.
+ public List Apply(Mat[] mats)
+ {
+ List output = new List();
+ unsafe
+ {
+ Mat* results = null;
+ fixed (Mat* _mats = mats)
+ {
+ ThrowException(NativeMethods.mmdeploy_restorer_apply(_handle, _mats, mats.Length, &results));
+ }
+
+ FormatResult(mats.Length, results, ref output, out var total);
+ ReleaseResult(results, total);
+ }
+
+ return output;
+ }
+
+ private unsafe void FormatResult(int matCount, Mat* results, ref List output, out int total)
+ {
+ total = 0;
+ for (int i = 0; i < matCount; i++)
+ {
+ output.Add(new RestorerOutput(results));
+ results++;
+ total++;
+ }
+ }
+
+ private unsafe void ReleaseResult(Mat* results, int count)
+ {
+ NativeMethods.mmdeploy_restorer_release_result(results, count);
+ }
+
+ ///
+ protected override void ReleaseHandle()
+ {
+ NativeMethods.mmdeploy_restorer_destroy(_handle);
+ }
+ }
+}
diff --git a/csrc/apis/csharp/MMDeploy/APIs/Segmentor.cs b/csrc/apis/csharp/MMDeploy/APIs/Segmentor.cs
new file mode 100644
index 000000000..6470a2d8a
--- /dev/null
+++ b/csrc/apis/csharp/MMDeploy/APIs/Segmentor.cs
@@ -0,0 +1,133 @@
+using System;
+using System.Collections.Generic;
+
+namespace MMDeploy
+{
+#pragma warning disable 0649
+ internal unsafe struct CSegment
+ {
+ public int Height;
+ public int Width;
+ public int Classes;
+ public int* Mask;
+ }
+#pragma warning restore 0649
+
+ ///
+ /// Output of Segmentor.
+ ///
+ public struct SegmentorOutput
+ {
+ ///
+ /// Height of image.
+ ///
+ public int Height;
+
+ ///
+ /// Width if image.
+ ///
+ public int Width;
+
+ ///
+ /// Number of classes.
+ ///
+ public int Classes;
+
+ ///
+ /// Mask data.
+ ///
+ public int[] Mask;
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// height.
+ /// width.
+ /// classes.
+ /// mask.
+ public SegmentorOutput(int height, int width, int classes, int[] mask)
+ {
+ Height = height;
+ Width = width;
+ Classes = classes;
+ Mask = new int[Height * Width];
+ Array.Copy(mask, this.Mask, mask.Length);
+ }
+
+ internal unsafe SegmentorOutput(CSegment* result)
+ {
+ Height = result->Height;
+ Width = result->Width;
+ Classes = result->Classes;
+ Mask = new int[Height * Width];
+ int nbytes = Height * Width * sizeof(int);
+ fixed (int* data = this.Mask)
+ {
+ Buffer.MemoryCopy(result->Mask, data, nbytes, nbytes);
+ }
+ }
+ }
+
+ ///
+ /// Segmentor.
+ ///
+ public class Segmentor : DisposableObject
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// model path.
+ /// device name.
+ /// device id.
+ public Segmentor(string modelPath, string deviceName, int deviceId)
+ {
+ ThrowException(NativeMethods.mmdeploy_segmentor_create_by_path(modelPath, deviceName, deviceId, out _handle));
+ }
+
+ ///
+ /// Get information of each image in a batch.
+ ///
+ /// input mats.
+ /// Results of each input mat.
+ public List Apply(Mat[] mats)
+ {
+ List output = new List();
+ unsafe
+ {
+ CSegment* results = null;
+ fixed (Mat* _mats = mats)
+ {
+ ThrowException(NativeMethods.mmdeploy_segmentor_apply(_handle, _mats, mats.Length, &results));
+ }
+
+ FormatResult(mats.Length, results, ref output, out var total);
+ ReleaseResult(results, total);
+ }
+
+ return output;
+ }
+
+ private unsafe void FormatResult(int matCount, CSegment* results, ref List output, out int total)
+ {
+ total = 0;
+ for (int i = 0; i < matCount; i++)
+ {
+ SegmentorOutput outi = new SegmentorOutput(results);
+ results++;
+ total++;
+ output.Add(outi);
+ }
+ }
+
+ private unsafe void ReleaseResult(CSegment* results, int count)
+ {
+ NativeMethods.mmdeploy_segmentor_release_result(results, count);
+ }
+
+ ///
+ protected override void ReleaseHandle()
+ {
+ NativeMethods.mmdeploy_segmentor_destroy(_handle);
+ }
+ }
+}
diff --git a/csrc/apis/csharp/MMDeploy/APIs/TextDetector.cs b/csrc/apis/csharp/MMDeploy/APIs/TextDetector.cs
new file mode 100644
index 000000000..958e62902
--- /dev/null
+++ b/csrc/apis/csharp/MMDeploy/APIs/TextDetector.cs
@@ -0,0 +1,213 @@
+using System;
+using System.Collections.Generic;
+
+namespace MMDeploy
+{
+ ///
+ /// Box.
+ ///
+ public struct TextBox
+ {
+ ///
+ /// P1.
+ ///
+ public Pointf P1;
+
+ ///
+ /// P2.
+ ///
+ public Pointf P2;
+
+ ///
+ /// P3.
+ ///
+ public Pointf P3;
+
+ ///
+ /// P4.
+ ///
+ public Pointf P4;
+
+ ///
+ /// Get reference Pi.
+ ///
+ /// ith point.
+ /// Pi reference.
+ public Pointf this[int i]
+ {
+ readonly get
+ {
+ return i switch
+ {
+ 0 => P1,
+ 1 => P2,
+ 2 => P3,
+ 3 => P4,
+ _ => throw new ArgumentOutOfRangeException(nameof(i))
+ };
+ }
+ set
+ {
+ switch (i)
+ {
+ case 0: P1 = value; break;
+ case 1: P2 = value; break;
+ case 2: P3 = value; break;
+ case 3: P4 = value; break;
+ default: throw new ArgumentOutOfRangeException(nameof(i));
+ }
+ }
+ }
+ }
+
+ ///
+ /// Single detection result of a picture.
+ /// A picture may contains multiple reuslts.
+ ///
+ public struct TextDetect
+ {
+ ///
+ /// Bounding box.
+ ///
+ public TextBox BBox;
+
+ ///
+ /// Score.
+ ///
+ public float Score;
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// score.
+ /// bbox.
+ public TextDetect(TextBox bbox, float score)
+ {
+ BBox = bbox;
+ Score = score;
+ }
+
+ internal unsafe TextDetect(TextDetect* result)
+ {
+ Score = result->Score;
+ BBox = default;
+ for (int i = 0; i < 4; i++)
+ {
+ BBox[i] = result->BBox[i];
+ }
+ }
+ }
+
+ ///
+ /// Output of DetectorOutput.
+ ///
+ public struct TextDetectorOutput
+ {
+ ///
+ /// Detection results for single image.
+ ///
+ public List Results;
+
+ private void Init()
+ {
+ if (Results == null)
+ {
+ Results = new List();
+ }
+ }
+
+ ///
+ /// Add result to single image.
+ ///
+ /// bbox.
+ /// score.
+ public void Add(TextBox bbox, float score)
+ {
+ Init();
+ Results.Add(new TextDetect(bbox, score));
+ }
+
+ internal unsafe void Add(TextDetect* result)
+ {
+ Init();
+ Results.Add(new TextDetect(result));
+ }
+
+ ///
+ /// Gets number of output.
+ ///
+ public int Count
+ {
+ get { return (Results == null) ? 0 : Results.Count; }
+ }
+ }
+
+ ///
+ /// TextDetector.
+ ///
+ public class TextDetector : DisposableObject
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// model path.
+ /// device name.
+ /// device id.
+ public TextDetector(string modelPath, string deviceName, int deviceId)
+ {
+ ThrowException(NativeMethods.mmdeploy_text_detector_create_by_path(modelPath, deviceName, deviceId, out _handle));
+ }
+
+ ///
+ /// Get information of each image in a batch.
+ ///
+ /// input mats.
+ /// Results of each input mat.
+ public List Apply(Mat[] mats)
+ {
+ List output = new List();
+ unsafe
+ {
+ TextDetect* results = null;
+ int* resultCount = null;
+ fixed (Mat* _mats = mats)
+ {
+ ThrowException(NativeMethods.mmdeploy_text_detector_apply(_handle, _mats, mats.Length, &results, &resultCount));
+ }
+
+ FormatResult(mats.Length, resultCount, results, ref output, out var total);
+ ReleaseResult(results, resultCount, total);
+ }
+
+ return output;
+ }
+
+ private unsafe void FormatResult(int matCount, int* resultCount, TextDetect* results, ref List output, out int total)
+ {
+ total = 0;
+ for (int i = 0; i < matCount; i++)
+ {
+ TextDetectorOutput outi = default;
+ for (int j = 0; j < resultCount[i]; j++)
+ {
+ outi.Add(results);
+ results++;
+ total++;
+ }
+
+ output.Add(outi);
+ }
+ }
+
+ private unsafe void ReleaseResult(TextDetect* results, int* resultCount, int count)
+ {
+ NativeMethods.mmdeploy_text_detector_release_result(results, resultCount, count);
+ }
+
+ ///
+ protected override void ReleaseHandle()
+ {
+ NativeMethods.mmdeploy_text_detector_destroy(_handle);
+ }
+ }
+}
diff --git a/csrc/apis/csharp/MMDeploy/APIs/TextRecognizer.cs b/csrc/apis/csharp/MMDeploy/APIs/TextRecognizer.cs
new file mode 100644
index 000000000..716d859ed
--- /dev/null
+++ b/csrc/apis/csharp/MMDeploy/APIs/TextRecognizer.cs
@@ -0,0 +1,189 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace MMDeploy
+{
+#pragma warning disable 0649
+ internal unsafe struct CTextRecognize
+ {
+ public char* Text;
+ public float* Score;
+ public int Length;
+ }
+#pragma warning restore 0649
+
+ ///
+ /// Single result of a picture.
+ /// A picture may contains multiple reuslts.
+ ///
+ public struct TextRecognize
+ {
+ ///
+ /// Texts.
+ ///
+ public byte[] Text;
+
+ ///
+ /// Scores.
+ ///
+ public float[] Score;
+
+ internal unsafe TextRecognize(CTextRecognize* result)
+ {
+ Text = new byte[result->Length];
+ Score = new float[result->Length];
+ fixed (byte* _text = Text)
+ {
+ int nbytes = result->Length;
+ Buffer.MemoryCopy(result->Text, _text, nbytes, nbytes);
+ }
+
+ fixed (float* _score = Score)
+ {
+ int nbytes = result->Length * sizeof(float);
+ Buffer.MemoryCopy(result->Score, _score, nbytes, nbytes);
+ }
+ }
+ }
+
+ ///
+ /// Output of TextRecognizer.
+ ///
+ public struct TextRecognizerOutput
+ {
+ ///
+ /// Text recognization results for single image.
+ ///
+ public List Results;
+
+ private void Init()
+ {
+ if (Results == null)
+ {
+ Results = new List();
+ }
+ }
+
+ internal unsafe void Add(CTextRecognize* result)
+ {
+ Init();
+ Results.Add(new TextRecognize(result));
+ }
+ }
+
+ ///
+ /// TextRecognizer.
+ ///
+ public class TextRecognizer : DisposableObject
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// model path.
+ /// device name.
+ /// device id.
+ public TextRecognizer(string modelPath, string deviceName, int deviceId)
+ {
+ ThrowException(NativeMethods.mmdeploy_text_recognizer_create_by_path(modelPath, deviceName, deviceId, out _handle));
+ }
+
+ ///
+ /// Get information of each image in a batch.
+ ///
+ /// input mats.
+ /// Results of each input mat.
+ public List Apply(Mat[] mats)
+ {
+ List output = new List();
+ unsafe
+ {
+ CTextRecognize* results = null;
+ fixed (Mat* _mats = mats)
+ {
+ ThrowException(NativeMethods.mmdeploy_text_recognizer_apply(_handle, _mats, mats.Length, &results));
+ }
+
+ int[] _bbox_count = Enumerable.Repeat(1, mats.Length).ToArray();
+ fixed (int* bbox_count = _bbox_count)
+ {
+ FormatResult(mats.Length, bbox_count, results, ref output, out var total);
+ ReleaseResult(results, total);
+ }
+ }
+
+ return output;
+ }
+
+ ///
+ /// Get information of each image in a batch.
+ ///
+ /// input mats.
+ /// detection for each image.
+ /// Results of each input mat.
+ public List Apply(Mat[] mats, List vdetects)
+ {
+ List output = new List();
+ unsafe
+ {
+ int[] bbox_count = new int[vdetects.Count];
+ int sz = 0;
+ for (int i = 0; i < vdetects.Count; i++)
+ {
+ bbox_count[i] = vdetects[i].Count;
+ sz += bbox_count[i];
+ }
+
+ TextDetect[] bboxes = new TextDetect[sz];
+ int pos = 0;
+ for (int i = 0; i < vdetects.Count; i++)
+ {
+ for (int j = 0; j < vdetects[i].Count; j++)
+ {
+ bboxes[pos++] = vdetects[i].Results[j];
+ }
+ }
+
+ CTextRecognize* results = null;
+ fixed (Mat* _mats = mats)
+ fixed (TextDetect* _bboxes = bboxes)
+ fixed (int* _bbox_count = bbox_count)
+ {
+ ThrowException(NativeMethods.mmdeploy_text_recognizer_apply_bbox(_handle, _mats, mats.Length, _bboxes, _bbox_count, &results));
+ FormatResult(mats.Length, _bbox_count, results, ref output, out var total);
+ ReleaseResult(results, total);
+ }
+ }
+
+ return output;
+ }
+
+ private unsafe void FormatResult(int matCount, int* resultCount, CTextRecognize* results, ref List output, out int total)
+ {
+ total = 0;
+ for (int i = 0; i < matCount; i++)
+ {
+ TextRecognizerOutput outi = default;
+ for (int j = 0; j < resultCount[i]; j++)
+ {
+ outi.Add(results);
+ results++;
+ total++;
+ }
+
+ output.Add(outi);
+ }
+ }
+
+ private unsafe void ReleaseResult(CTextRecognize* results, int count)
+ {
+ NativeMethods.mmdeploy_text_recognizer_release_result(results, count);
+ }
+
+ ///
+ protected override void ReleaseHandle()
+ {
+ NativeMethods.mmdeploy_text_recognizer_destroy(_handle);
+ }
+ }
+}
diff --git a/csrc/apis/csharp/MMDeploy/APIs/common.cs b/csrc/apis/csharp/MMDeploy/APIs/common.cs
new file mode 100644
index 000000000..0bf302bcd
--- /dev/null
+++ b/csrc/apis/csharp/MMDeploy/APIs/common.cs
@@ -0,0 +1,91 @@
+#pragma warning disable 1591
+namespace MMDeploy
+{
+ ///
+ /// Pixel format.
+ ///
+ public enum PixelFormat
+ {
+ BGR,
+ RGB,
+ Grayscale,
+ NV12,
+ NV21,
+ BGRA,
+ UnknownPixelFormat
+ }
+
+ ///
+ /// Mat data type.
+ ///
+ public enum DataType
+ {
+ Float,
+ Half,
+ Int8,
+ Int32,
+ UnknownDataType
+ }
+
+ ///
+ /// Function return value.
+ ///
+ public enum Status
+ {
+ Success = 0,
+ InvalidArg = 1,
+ NotSupported = 2,
+ OutOfRange = 3,
+ OutOfMemory = 4,
+ FileNotExist = 5,
+ Fail = 6,
+ Unknown = -1,
+ }
+
+ ///
+ /// c struct of mm_mat_t.
+ ///
+ public unsafe struct Mat
+ {
+ public byte* Data;
+ public int Height;
+ public int Width;
+ public int Channel;
+ public PixelFormat Format;
+ public DataType Type;
+ }
+
+ ///
+ /// Rect of float value.
+ ///
+ public struct Rect
+ {
+ public float Left;
+ public float Top;
+ public float Right;
+ public float Bottom;
+ }
+
+ ///
+ /// Point of int.
+ ///
+ public struct Pointi
+ {
+ public int X;
+ public int Y;
+ }
+
+ ///
+ /// Point of float.
+ ///
+ public struct Pointf
+ {
+ public float X;
+ public float Y;
+ public Pointf(float x, float y)
+ {
+ X = x;
+ Y = y;
+ }
+ }
+}
diff --git a/csrc/apis/csharp/MMDeploy/MMDeploy.csproj b/csrc/apis/csharp/MMDeploy/MMDeploy.csproj
new file mode 100644
index 000000000..9d1ac81ee
--- /dev/null
+++ b/csrc/apis/csharp/MMDeploy/MMDeploy.csproj
@@ -0,0 +1,49 @@
+
+
+
+ netcoreapp3.1;net48;
+ 9.0
+ enable
+ MMDeploy
+ MMDeploy
+ true
+ true
+ false
+ AnyCPU;x64
+ true
+
+
+
+ $(MSBuildThisFileDirectory)\..\..\..\..
+
+
+
+
+
+
+ DEBUG;TRACE
+ true
+
+
+ TRACE
+ true
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/csrc/apis/csharp/MMDeploy/NativeAPIs/NativeMethods.cs b/csrc/apis/csharp/MMDeploy/NativeAPIs/NativeMethods.cs
new file mode 100644
index 000000000..a5b62dede
--- /dev/null
+++ b/csrc/apis/csharp/MMDeploy/NativeAPIs/NativeMethods.cs
@@ -0,0 +1,10 @@
+namespace MMDeploy
+{
+ ///
+ /// Nativate C methods.
+ ///
+ internal static partial class NativeMethods
+ {
+ public const string DllExtern = "MMDeployExtern";
+ }
+}
diff --git a/csrc/apis/csharp/MMDeploy/NativeAPIs/NativeMethods_c_api.cs b/csrc/apis/csharp/MMDeploy/NativeAPIs/NativeMethods_c_api.cs
new file mode 100644
index 000000000..6eb7f9ce5
--- /dev/null
+++ b/csrc/apis/csharp/MMDeploy/NativeAPIs/NativeMethods_c_api.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+
+namespace MMDeploy
+{
+ ///
+ /// Nativate C methods.
+ ///
+ internal static partial class NativeMethods
+ {
+ #region model.h
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern int mmdeploy_model_create_by_path(string path, out IntPtr handle);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern int mmdeploy_model_create(IntPtr buffer, int size, out IntPtr handle);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern void mmdeploy_model_destroy(IntPtr model);
+ #endregion
+
+ #region pose_detector.h
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern int mmdeploy_pose_detector_create(IntPtr model, string deviceName,
+ int deviceId, out IntPtr handle);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern int mmdeploy_pose_detector_create_by_path(string modelPath,
+ string deviceName, int deviceId, out IntPtr handle);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern unsafe int mmdeploy_pose_detector_apply(IntPtr handle, Mat* mats,
+ int matCount, CPoseDetect** results);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern unsafe int mmdeploy_pose_detector_apply_bbox(IntPtr handle, Mat* mats,
+ int matCount, Rect* bboxes, int* bbox_count, CPoseDetect** results);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern unsafe int mmdeploy_pose_detector_release_result(CPoseDetect* results,
+ int count);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern void mmdeploy_pose_detector_destroy(IntPtr handle);
+ #endregion
+
+ #region classifier.h
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern int mmdeploy_classifier_create(IntPtr model, string deviceName,
+ int deviceId, out IntPtr handle);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern int mmdeploy_classifier_create_by_path(string modelPath,
+ string deviceName, int deviceId, out IntPtr handle);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern unsafe int mmdeploy_classifier_apply(IntPtr handle, Mat* mats,
+ int matCount, Label** results, int** resultCount);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern unsafe void mmdeploy_classifier_release_result(Label* results,
+ int* resultCount, int count);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern void mmdeploy_classifier_destroy(IntPtr handle);
+ #endregion
+
+ #region detector.h
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern int mmdeploy_detector_create(IntPtr model, string deviceName,
+ int deviceId, out IntPtr handle);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern int mmdeploy_detector_create_by_path(string modelPath,
+ string deviceName, int deviceId, out IntPtr handle);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern unsafe int mmdeploy_detector_apply(IntPtr handle, Mat* mats,
+ int matCount, CDetect** results, int** resultCount);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern unsafe void mmdeploy_detector_release_result(CDetect* results,
+ int* resultCount, int count);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern void mmdeploy_detector_destroy(IntPtr handle);
+ #endregion
+
+ #region restorer.h
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern int mmdeploy_restorer_create(IntPtr model, string deviceName,
+ int deviceId, out IntPtr handle);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern int mmdeploy_restorer_create_by_path(string modelPath,
+ string deviceName, int deviceId, out IntPtr handle);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern unsafe int mmdeploy_restorer_apply(IntPtr handle, Mat* images,
+ int count, Mat** results);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern unsafe void mmdeploy_restorer_release_result(Mat* results,
+ int count);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern void mmdeploy_restorer_destroy(IntPtr handle);
+ #endregion
+
+ #region segmentor.h
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern int mmdeploy_segmentor_create(IntPtr model, string deviceName,
+ int deviceId, out IntPtr handle);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern int mmdeploy_segmentor_create_by_path(string modelPath,
+ string deviceName, int deviceId, out IntPtr handle);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern unsafe int mmdeploy_segmentor_apply(IntPtr handle, Mat* mats,
+ int matCount, CSegment** results);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern unsafe void mmdeploy_segmentor_release_result(CSegment* results,
+ int count);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern void mmdeploy_segmentor_destroy(IntPtr handle);
+ #endregion
+
+ #region text_detector.h
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern int mmdeploy_text_detector_create(IntPtr model, string deviceName,
+ int deviceId, out IntPtr handle);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern int mmdeploy_text_detector_create_by_path(string modelPath,
+ string deviceName, int deviceId, out IntPtr handle);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern unsafe int mmdeploy_text_detector_apply(IntPtr handle, Mat* mats,
+ int matCount, TextDetect** results, int** resultCount);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern unsafe void mmdeploy_text_detector_release_result(TextDetect* results,
+ int* resultCount, int count);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern void mmdeploy_text_detector_destroy(IntPtr handle);
+ #endregion
+
+ #region text_recognizer.h
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern int mmdeploy_text_recognizer_create(IntPtr model, string deviceName,
+ int deviceId, out IntPtr handle);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern int mmdeploy_text_recognizer_create_by_path(string modelPath,
+ string deviceName, int deviceId, out IntPtr handle);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern unsafe int mmdeploy_text_recognizer_apply(IntPtr handle, Mat* images,
+ int count, CTextRecognize** results);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern unsafe int mmdeploy_text_recognizer_apply_bbox(IntPtr handle,
+ Mat* images, int image_count, TextDetect* bboxes, int* bbox_count,
+ CTextRecognize** results);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern unsafe void mmdeploy_text_recognizer_release_result(
+ CTextRecognize* results, int count);
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
+ public static extern void mmdeploy_text_recognizer_destroy(IntPtr handle);
+ #endregion
+ }
+}
diff --git a/csrc/apis/csharp/MMDeploy/Properties/AssemblyInfo.cs b/csrc/apis/csharp/MMDeploy/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..90bacc368
--- /dev/null
+++ b/csrc/apis/csharp/MMDeploy/Properties/AssemblyInfo.cs
@@ -0,0 +1,22 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("MMDeploy")]
+[assembly: AssemblyDescription("C# Wrapper For MMDeploy")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("OpenMMLab")]
+[assembly: AssemblyProduct("MMDeploy")]
+[assembly: AssemblyCopyright("Copyright © 2022")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("3dc914eb-a8fb-4a89-a7cf-7df9cc5284a6")]
diff --git a/csrc/apis/csharp/README.md b/csrc/apis/csharp/README.md
new file mode 100644
index 000000000..49427121b
--- /dev/null
+++ b/csrc/apis/csharp/README.md
@@ -0,0 +1,45 @@
+# Installation
+
+## Binaries
+
+We provide nuget package on our [release page](https://github.com/open-mmlab/mmdeploy/releases). Currently the prebuilt package only support tensorrt and onnxruntiem backend.
+
+To use the nuget package, you also need to download the backend dependencies. For example, if you want to use the tensorrt backend, you should install cudatoolkit, cudnn and tensorrt, remember to add the dll directories to your system path. The version of backend dependencies that our prebuit nuget package used will be offered in release note.
+
+| backend | dependencies |
+| ------------- | ------------- |
+| tensorrt | cudatoolkit, cudnn, tensorrt |
+| onnxruntime | onnxruntime / onnxruntime-gpu |
+
+## From Source
+
+### Requirements
+
+* Environment required by building sdk
+* .NET Framework 4.8 / .NET core 3.1
+* Visual Studio 2019+
+
+### Installation
+
+**Step 0.** Build sdk.
+
+Before building the c# api, you need to build sdk first. Please follow this [tutorial](../../../docs/en/build/windows.md)/[教程](../../../docs/zh_cn/build/windows.md) to build sdk. Remember to set the MMDEPLOY_BUILD_CSHARP_EXTERN option to ON. We recommend setting `BUILD_SHARED_LIBS` to OFF and use the static third party libraries(spdlog, pplcv, opencv, etc.). If so, you only need add the backend dependencies to your system path, or you need to add all dependencies.
+
+If you follow the tutorial, the MMDeployExtern.dll will be built in `build\bin\release`. Make sure the expected dll is in that path or the next step will throw a file-not-exist error.
+
+**Step 1.** Build MMDeploy nuget package.
+
+There are two methods to build the nuget package.
+
+(*option 1*) Use the command.
+
+If your environment is well prepared, you can just go to the `csrc\apis\csharp` folder, open a terminal and type the following command, the nupkg will be built in `csrc\apis\csharp\MMDeploy\bin\Release\MMDeploy.1.0.0.nupkg`.
+```shell
+dotnet build --configuration Release -p:Version=1.0.0
+```
+
+(*option 2*) Open MMDeploy.sln && Build.
+
+You can set the package-version through `Properties -> Package Version`. The default version is 1.0.0 if you don't set it.
+
+If you meets some missing dependencies error, follow the vs instructions.
diff --git a/demo/csharp/Demo.sln b/demo/csharp/Demo.sln
new file mode 100644
index 000000000..bb24b7e9c
--- /dev/null
+++ b/demo/csharp/Demo.sln
@@ -0,0 +1,61 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31729.503
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "image_classification", "image_classification\image_classification.csproj", "{77D130AF-1B08-496F-8B6C-F38FCDFEB1BE}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "image_restorer", "image_restorer\image_restorer.csproj", "{2FB1A872-C361-4799-AE26-1F28454EA56D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "image_segmentation", "image_segmentation\image_segmentation.csproj", "{3568F017-112A-4BF3-AE90-BD047E2C389D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "object_detection", "object_detection\object_detection.csproj", "{140B7A2A-0492-4845-83DF-3E812E97CDC5}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ocr_detection", "ocr_detection\ocr_detection.csproj", "{3C4E4F6C-6E75-4110-BC68-DD36DD7B0546}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ocr_recognition", "ocr_recognition\ocr_recognition.csproj", "{9B68260C-0C7C-473C-8D6F-284283F91F84}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pose_detection", "pose_detection\pose_detection.csproj", "{10E3B87C-7544-4F4D-90A3-65D5654CBF94}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {77D130AF-1B08-496F-8B6C-F38FCDFEB1BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77D130AF-1B08-496F-8B6C-F38FCDFEB1BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77D130AF-1B08-496F-8B6C-F38FCDFEB1BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77D130AF-1B08-496F-8B6C-F38FCDFEB1BE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2FB1A872-C361-4799-AE26-1F28454EA56D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2FB1A872-C361-4799-AE26-1F28454EA56D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2FB1A872-C361-4799-AE26-1F28454EA56D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2FB1A872-C361-4799-AE26-1F28454EA56D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3568F017-112A-4BF3-AE90-BD047E2C389D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3568F017-112A-4BF3-AE90-BD047E2C389D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3568F017-112A-4BF3-AE90-BD047E2C389D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3568F017-112A-4BF3-AE90-BD047E2C389D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {140B7A2A-0492-4845-83DF-3E812E97CDC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {140B7A2A-0492-4845-83DF-3E812E97CDC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {140B7A2A-0492-4845-83DF-3E812E97CDC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {140B7A2A-0492-4845-83DF-3E812E97CDC5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3C4E4F6C-6E75-4110-BC68-DD36DD7B0546}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3C4E4F6C-6E75-4110-BC68-DD36DD7B0546}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3C4E4F6C-6E75-4110-BC68-DD36DD7B0546}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3C4E4F6C-6E75-4110-BC68-DD36DD7B0546}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9B68260C-0C7C-473C-8D6F-284283F91F84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9B68260C-0C7C-473C-8D6F-284283F91F84}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9B68260C-0C7C-473C-8D6F-284283F91F84}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9B68260C-0C7C-473C-8D6F-284283F91F84}.Release|Any CPU.Build.0 = Release|Any CPU
+ {10E3B87C-7544-4F4D-90A3-65D5654CBF94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {10E3B87C-7544-4F4D-90A3-65D5654CBF94}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {10E3B87C-7544-4F4D-90A3-65D5654CBF94}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {10E3B87C-7544-4F4D-90A3-65D5654CBF94}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {85E68B94-6CED-4912-BDB6-BAB2367C4212}
+ EndGlobalSection
+EndGlobal
diff --git a/demo/csharp/README.md b/demo/csharp/README.md
new file mode 100644
index 000000000..824ef95db
--- /dev/null
+++ b/demo/csharp/README.md
@@ -0,0 +1,29 @@
+# Usage
+
+**step 0.** install the local nuget package
+
+You should build csharp api first, it will generate a nuget package, or you can download our prebuit package. You may refer to [this](https://stackoverflow.com/a/55167481) on how to install local nuget package.
+
+**step 1.** Add runtime dll to the system path
+
+If you built csharp api from source and didn't build static lib, you should add the built dll to your system path. The same is to opencv, spdlog, etc.
+
+And don't forget to install backend dependencies. Take tensorrt backend as example, you have to install cudatoolkit, cudnn and tensorrt. The version of backend dependencies that our prebuit nuget package used will be offered in release note.
+
+| backend | dependencies |
+| ------------- | ------------- |
+| tensorrt | cudatoolkit, cudnn, tensorrt |
+| onnxruntime | onnxruntime / onnxruntime-gpu |
+
+
+**step 2.** Open Demo.sln and build solution.
+
+**step 3.** Prepare the model.
+
+You can either convert your model according to this [tutorial](../../docs/en/tutorials/how_to_convert_model.md) or download the test models from [OneDrive](https://1drv.ms/u/s!Aqis6w3rjKXSh2dXZ5OqbZIZSu9P?e=nefSdY) or [BaiduYun](https://pan.baidu.com/s/1VJkLo2oqHos6ZWDT7xamFg?pwd=STAR). The web drive contains onnx and tensorrt models and the test models are converted under environment of cuda11.1 + cudnn8.2.1 + tensorrt 8.2.3.0 + GTX2070s.
+
+*Note*:
++ a) If you want to use the tensorrt model from the link, make sure your environment and your gpu architecture is same with above.
++ b) When you use the downloaded onnx model, you have to edit `deploy.json`, edit `end2end.engine` to `end2end.onnx` and `tensorrt` to `onnxruntime`.
+
+**step 4.** Set one project as startup project and run it.
diff --git a/demo/csharp/image_classification/FormDemo.Designer.cs b/demo/csharp/image_classification/FormDemo.Designer.cs
new file mode 100644
index 000000000..03e38b5e6
--- /dev/null
+++ b/demo/csharp/image_classification/FormDemo.Designer.cs
@@ -0,0 +1,315 @@
+
+namespace image_classification
+{
+ partial class FormDemo
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.buttonSelectModelPath = new System.Windows.Forms.Button();
+ this.buttonInitModel = new System.Windows.Forms.Button();
+ this.buttonLoadImage = new System.Windows.Forms.Button();
+ this.pictureBoxPicture = new System.Windows.Forms.PictureBox();
+ this.radioButtonDeviceCpu = new System.Windows.Forms.RadioButton();
+ this.radioButtonDeviceCuda = new System.Windows.Forms.RadioButton();
+ this.buttonInference = new System.Windows.Forms.Button();
+ this.textBoxModelPath = new System.Windows.Forms.TextBox();
+ this.labelModelPath = new System.Windows.Forms.Label();
+ this.labelDevice = new System.Windows.Forms.Label();
+ this.panelModelOptions = new System.Windows.Forms.Panel();
+ this.textBoxStatus = new System.Windows.Forms.TextBox();
+ this.labelStatus = new System.Windows.Forms.Label();
+ this.labelModelOptions = new System.Windows.Forms.Label();
+ this.panelPicture = new System.Windows.Forms.Panel();
+ this.labelPicture = new System.Windows.Forms.Label();
+ this.textBoxResult = new System.Windows.Forms.TextBox();
+ this.labelResult = new System.Windows.Forms.Label();
+ this.labelUsage = new System.Windows.Forms.Label();
+ this.textBoxUsage = new System.Windows.Forms.TextBox();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBoxPicture)).BeginInit();
+ this.panelModelOptions.SuspendLayout();
+ this.panelPicture.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // buttonSelectModelPath
+ //
+ this.buttonSelectModelPath.Location = new System.Drawing.Point(959, 76);
+ this.buttonSelectModelPath.Name = "buttonSelectModelPath";
+ this.buttonSelectModelPath.Size = new System.Drawing.Size(143, 41);
+ this.buttonSelectModelPath.TabIndex = 1;
+ this.buttonSelectModelPath.Text = "select";
+ this.buttonSelectModelPath.UseVisualStyleBackColor = true;
+ this.buttonSelectModelPath.Click += new System.EventHandler(this.buttonSelectModelPath_Click);
+ //
+ // buttonInitModel
+ //
+ this.buttonInitModel.ForeColor = System.Drawing.SystemColors.ControlText;
+ this.buttonInitModel.Location = new System.Drawing.Point(920, 76);
+ this.buttonInitModel.Name = "buttonInitModel";
+ this.buttonInitModel.Size = new System.Drawing.Size(143, 38);
+ this.buttonInitModel.TabIndex = 1;
+ this.buttonInitModel.Text = "init model";
+ this.buttonInitModel.UseVisualStyleBackColor = true;
+ this.buttonInitModel.Click += new System.EventHandler(this.buttonInitModel_Click);
+ //
+ // buttonLoadImage
+ //
+ this.buttonLoadImage.Location = new System.Drawing.Point(461, 752);
+ this.buttonLoadImage.Name = "buttonLoadImage";
+ this.buttonLoadImage.Size = new System.Drawing.Size(185, 50);
+ this.buttonLoadImage.TabIndex = 2;
+ this.buttonLoadImage.Text = "load image";
+ this.buttonLoadImage.UseVisualStyleBackColor = true;
+ this.buttonLoadImage.Click += new System.EventHandler(this.buttonLoadImage_Click);
+ //
+ // pictureBoxPicture
+ //
+ this.pictureBoxPicture.Location = new System.Drawing.Point(4, 3);
+ this.pictureBoxPicture.Name = "pictureBoxPicture";
+ this.pictureBoxPicture.Size = new System.Drawing.Size(392, 456);
+ this.pictureBoxPicture.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
+ this.pictureBoxPicture.TabIndex = 3;
+ this.pictureBoxPicture.TabStop = false;
+ //
+ // radioButtonDeviceCpu
+ //
+ this.radioButtonDeviceCpu.AutoSize = true;
+ this.radioButtonDeviceCpu.Location = new System.Drawing.Point(244, 134);
+ this.radioButtonDeviceCpu.Name = "radioButtonDeviceCpu";
+ this.radioButtonDeviceCpu.Size = new System.Drawing.Size(87, 35);
+ this.radioButtonDeviceCpu.TabIndex = 4;
+ this.radioButtonDeviceCpu.Text = "cpu";
+ this.radioButtonDeviceCpu.UseVisualStyleBackColor = true;
+ this.radioButtonDeviceCpu.CheckedChanged += new System.EventHandler(this.radioButtonDeviceCpu_CheckedChanged);
+ //
+ // radioButtonDeviceCuda
+ //
+ this.radioButtonDeviceCuda.AutoSize = true;
+ this.radioButtonDeviceCuda.Checked = true;
+ this.radioButtonDeviceCuda.Location = new System.Drawing.Point(343, 134);
+ this.radioButtonDeviceCuda.Name = "radioButtonDeviceCuda";
+ this.radioButtonDeviceCuda.Size = new System.Drawing.Size(100, 35);
+ this.radioButtonDeviceCuda.TabIndex = 5;
+ this.radioButtonDeviceCuda.TabStop = true;
+ this.radioButtonDeviceCuda.Text = "cuda";
+ this.radioButtonDeviceCuda.UseVisualStyleBackColor = true;
+ this.radioButtonDeviceCuda.CheckedChanged += new System.EventHandler(this.radioButtonDeviceCuda_CheckedChanged);
+ //
+ // buttonInference
+ //
+ this.buttonInference.Location = new System.Drawing.Point(849, 752);
+ this.buttonInference.Name = "buttonInference";
+ this.buttonInference.Size = new System.Drawing.Size(185, 50);
+ this.buttonInference.TabIndex = 6;
+ this.buttonInference.Text = "inference";
+ this.buttonInference.UseVisualStyleBackColor = true;
+ this.buttonInference.Click += new System.EventHandler(this.buttonInference_Click);
+ //
+ // textBoxModelPath
+ //
+ this.textBoxModelPath.Location = new System.Drawing.Point(243, 76);
+ this.textBoxModelPath.Name = "textBoxModelPath";
+ this.textBoxModelPath.Size = new System.Drawing.Size(700, 38);
+ this.textBoxModelPath.TabIndex = 7;
+ //
+ // labelModelPath
+ //
+ this.labelModelPath.AutoSize = true;
+ this.labelModelPath.Location = new System.Drawing.Point(82, 76);
+ this.labelModelPath.Name = "labelModelPath";
+ this.labelModelPath.Size = new System.Drawing.Size(145, 31);
+ this.labelModelPath.TabIndex = 8;
+ this.labelModelPath.Text = "model path";
+ this.labelModelPath.TextAlign = System.Drawing.ContentAlignment.TopRight;
+ //
+ // labelDevice
+ //
+ this.labelDevice.AutoSize = true;
+ this.labelDevice.Location = new System.Drawing.Point(139, 134);
+ this.labelDevice.Name = "labelDevice";
+ this.labelDevice.Size = new System.Drawing.Size(88, 31);
+ this.labelDevice.TabIndex = 9;
+ this.labelDevice.Text = "device";
+ this.labelDevice.TextAlign = System.Drawing.ContentAlignment.TopRight;
+ //
+ // panelModelOptions
+ //
+ this.panelModelOptions.BackColor = System.Drawing.SystemColors.ButtonFace;
+ this.panelModelOptions.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.panelModelOptions.Controls.Add(this.textBoxStatus);
+ this.panelModelOptions.Controls.Add(this.labelStatus);
+ this.panelModelOptions.Controls.Add(this.buttonInitModel);
+ this.panelModelOptions.ForeColor = System.Drawing.SystemColors.ButtonShadow;
+ this.panelModelOptions.Location = new System.Drawing.Point(38, 57);
+ this.panelModelOptions.Name = "panelModelOptions";
+ this.panelModelOptions.Size = new System.Drawing.Size(1090, 139);
+ this.panelModelOptions.TabIndex = 10;
+ //
+ // textBoxStatus
+ //
+ this.textBoxStatus.BackColor = System.Drawing.SystemColors.Control;
+ this.textBoxStatus.BorderStyle = System.Windows.Forms.BorderStyle.None;
+ this.textBoxStatus.ForeColor = System.Drawing.SystemColors.WindowText;
+ this.textBoxStatus.Location = new System.Drawing.Point(657, 80);
+ this.textBoxStatus.Name = "textBoxStatus";
+ this.textBoxStatus.ReadOnly = true;
+ this.textBoxStatus.Size = new System.Drawing.Size(247, 31);
+ this.textBoxStatus.TabIndex = 3;
+ //
+ // labelStatus
+ //
+ this.labelStatus.AutoSize = true;
+ this.labelStatus.ForeColor = System.Drawing.SystemColors.ActiveCaptionText;
+ this.labelStatus.Location = new System.Drawing.Point(556, 76);
+ this.labelStatus.Name = "labelStatus";
+ this.labelStatus.Size = new System.Drawing.Size(95, 31);
+ this.labelStatus.TabIndex = 2;
+ this.labelStatus.Text = "status: ";
+ //
+ // labelModelOptions
+ //
+ this.labelModelOptions.AutoSize = true;
+ this.labelModelOptions.ForeColor = System.Drawing.SystemColors.ControlText;
+ this.labelModelOptions.Location = new System.Drawing.Point(21, 35);
+ this.labelModelOptions.Name = "labelModelOptions";
+ this.labelModelOptions.Size = new System.Drawing.Size(185, 31);
+ this.labelModelOptions.TabIndex = 11;
+ this.labelModelOptions.Text = "Model Options";
+ //
+ // panelPicture
+ //
+ this.panelPicture.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.panelPicture.Controls.Add(this.pictureBoxPicture);
+ this.panelPicture.Location = new System.Drawing.Point(354, 259);
+ this.panelPicture.Name = "panelPicture";
+ this.panelPicture.Size = new System.Drawing.Size(397, 464);
+ this.panelPicture.TabIndex = 12;
+ //
+ // labelPicture
+ //
+ this.labelPicture.AutoSize = true;
+ this.labelPicture.Location = new System.Drawing.Point(343, 239);
+ this.labelPicture.Name = "labelPicture";
+ this.labelPicture.Size = new System.Drawing.Size(94, 31);
+ this.labelPicture.TabIndex = 13;
+ this.labelPicture.Text = "Picture";
+ //
+ // textBoxResult
+ //
+ this.textBoxResult.BackColor = System.Drawing.SystemColors.Control;
+ this.textBoxResult.Location = new System.Drawing.Point(770, 267);
+ this.textBoxResult.Multiline = true;
+ this.textBoxResult.Name = "textBoxResult";
+ this.textBoxResult.ReadOnly = true;
+ this.textBoxResult.Size = new System.Drawing.Size(358, 456);
+ this.textBoxResult.TabIndex = 14;
+ //
+ // labelResult
+ //
+ this.labelResult.AutoSize = true;
+ this.labelResult.Location = new System.Drawing.Point(757, 233);
+ this.labelResult.Name = "labelResult";
+ this.labelResult.Size = new System.Drawing.Size(85, 31);
+ this.labelResult.TabIndex = 15;
+ this.labelResult.Text = "Result";
+ //
+ // labelUsage
+ //
+ this.labelUsage.AutoSize = true;
+ this.labelUsage.Location = new System.Drawing.Point(21, 233);
+ this.labelUsage.Name = "labelUsage";
+ this.labelUsage.Size = new System.Drawing.Size(85, 31);
+ this.labelUsage.TabIndex = 16;
+ this.labelUsage.Text = "Usage";
+ //
+ // textBoxUsage
+ //
+ this.textBoxUsage.Location = new System.Drawing.Point(37, 267);
+ this.textBoxUsage.Multiline = true;
+ this.textBoxUsage.Name = "textBoxUsage";
+ this.textBoxUsage.ReadOnly = true;
+ this.textBoxUsage.Size = new System.Drawing.Size(294, 454);
+ this.textBoxUsage.TabIndex = 17;
+ //
+ // FormDemo
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(14F, 31F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(1157, 829);
+ this.Controls.Add(this.textBoxUsage);
+ this.Controls.Add(this.labelUsage);
+ this.Controls.Add(this.labelResult);
+ this.Controls.Add(this.textBoxResult);
+ this.Controls.Add(this.labelPicture);
+ this.Controls.Add(this.panelPicture);
+ this.Controls.Add(this.labelModelOptions);
+ this.Controls.Add(this.labelDevice);
+ this.Controls.Add(this.labelModelPath);
+ this.Controls.Add(this.textBoxModelPath);
+ this.Controls.Add(this.buttonInference);
+ this.Controls.Add(this.radioButtonDeviceCuda);
+ this.Controls.Add(this.radioButtonDeviceCpu);
+ this.Controls.Add(this.buttonLoadImage);
+ this.Controls.Add(this.buttonSelectModelPath);
+ this.Controls.Add(this.panelModelOptions);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
+ this.Name = "FormDemo";
+ this.Text = "Image_classification";
+ this.Load += new System.EventHandler(this.FormDemo_Load);
+ this.Resize += new System.EventHandler(this.FormDemo_Resize);
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBoxPicture)).EndInit();
+ this.panelModelOptions.ResumeLayout(false);
+ this.panelModelOptions.PerformLayout();
+ this.panelPicture.ResumeLayout(false);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button buttonSelectModelPath;
+ private System.Windows.Forms.Button buttonInitModel;
+ private System.Windows.Forms.Button buttonLoadImage;
+ private System.Windows.Forms.Button buttonInference;
+ private System.Windows.Forms.PictureBox pictureBoxPicture;
+ private System.Windows.Forms.RadioButton radioButtonDeviceCpu;
+ private System.Windows.Forms.RadioButton radioButtonDeviceCuda;
+ private System.Windows.Forms.TextBox textBoxModelPath;
+ private System.Windows.Forms.Label labelModelPath;
+ private System.Windows.Forms.Label labelDevice;
+ private System.Windows.Forms.Panel panelModelOptions;
+ private System.Windows.Forms.Label labelModelOptions;
+ private System.Windows.Forms.Panel panelPicture;
+ private System.Windows.Forms.Label labelPicture;
+ private System.Windows.Forms.Label labelStatus;
+ private System.Windows.Forms.TextBox textBoxResult;
+ private System.Windows.Forms.Label labelResult;
+ private System.Windows.Forms.Label labelUsage;
+ private System.Windows.Forms.TextBox textBoxUsage;
+ private System.Windows.Forms.TextBox textBoxStatus;
+ }
+}
diff --git a/demo/csharp/image_classification/FormDemo.cs b/demo/csharp/image_classification/FormDemo.cs
new file mode 100644
index 000000000..9cccc5592
--- /dev/null
+++ b/demo/csharp/image_classification/FormDemo.cs
@@ -0,0 +1,204 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using MMDeploy;
+using OpenCvSharp.Extensions;
+using ImreadModes = OpenCvSharp.ImreadModes;
+using Cv2 = OpenCvSharp.Cv2;
+using CvMat = OpenCvSharp.Mat;
+
+#pragma warning disable IDE1006
+#pragma warning disable IDE0044
+
+namespace image_classification
+{
+ public partial class FormDemo : Form
+ {
+ Classifier classifier;
+ string modelPath = "";
+ string device = "cuda";
+ int deviceId = 0;
+ string imgPath = "";
+
+ #region auto resize
+ private float x;
+ private float y;
+ private void setTag(Control cons)
+ {
+ foreach (Control con in cons.Controls)
+ {
+ con.Tag = con.Width + ";" + con.Height + ";" + con.Left + ";" + con.Top + ";" + con.Font.Size;
+ if (con.Controls.Count > 0)
+ {
+ setTag(con);
+ }
+ }
+ }
+ private void setControls(float newx, float newy, Control cons)
+ {
+ foreach (Control con in cons.Controls)
+ {
+ if (con.Tag != null)
+ {
+ string[] mytag = con.Tag.ToString().Split(new char[] { ';' });
+ con.Width = Convert.ToInt32(System.Convert.ToSingle(mytag[0]) * newx);
+ con.Height = Convert.ToInt32(System.Convert.ToSingle(mytag[1]) * newy);
+ con.Left = Convert.ToInt32(System.Convert.ToSingle(mytag[2]) * newx);
+ con.Top = Convert.ToInt32(System.Convert.ToSingle(mytag[3]) * newy);
+ Single currentSize = System.Convert.ToSingle(mytag[4]) * newy;
+ con.Font = new Font(con.Font.Name, currentSize, con.Font.Style, con.Font.Unit);
+ if (con.Controls.Count > 0)
+ {
+ setControls(newx, newy, con);
+ }
+ }
+ }
+ }
+ private void FormDemo_Resize(object sender, EventArgs e)
+ {
+ float newx = (this.Width) / x;
+ float newy = (this.Height) / y;
+ setControls(newx, newy, this);
+ }
+
+ #endregion
+
+ static void CvMatToMat(CvMat[] cvMats, out Mat[] mats)
+ {
+ mats = new Mat[cvMats.Length];
+ unsafe
+ {
+ for (int i = 0; i < cvMats.Length; i++)
+ {
+ mats[i].Data = cvMats[i].DataPointer;
+ mats[i].Height = cvMats[i].Height;
+ mats[i].Width = cvMats[i].Width;
+ mats[i].Channel = cvMats[i].Dims;
+ mats[i].Format = PixelFormat.BGR;
+ mats[i].Type = DataType.Int8;
+ }
+ }
+ }
+
+ public FormDemo()
+ {
+ InitializeComponent();
+ x = this.Width;
+ y = this.Height;
+ setTag(this);
+ }
+
+ private void radioButtonDeviceCpu_CheckedChanged(object sender, EventArgs e)
+ {
+ device = "cpu";
+ }
+
+ private void radioButtonDeviceCuda_CheckedChanged(object sender, EventArgs e)
+ {
+ device = "cuda";
+ }
+
+ private void buttonSelectModelPath_Click(object sender, EventArgs e)
+ {
+ FolderBrowserDialog dilog = new FolderBrowserDialog();
+ if (dilog.ShowDialog() == DialogResult.OK)
+ {
+ textBoxModelPath.Text = dilog.SelectedPath;
+ }
+ }
+
+ private void buttonInitModel_Click(object sender, EventArgs e)
+ {
+ if (classifier != null)
+ {
+ classifier.Close();
+
+ }
+ classifier = null;
+ textBoxStatus.Text = "init model ...";
+ try
+ {
+ modelPath = textBoxModelPath.Text;
+ classifier = new Classifier(modelPath, device, deviceId);
+ textBoxStatus.ForeColor = Color.Green;
+ textBoxStatus.Text = "init model success.";
+ } catch
+ {
+ textBoxStatus.ForeColor = Color.Red;
+ textBoxStatus.Text = "init model failed.";
+ }
+ }
+
+ private void buttonLoadImage_Click(object sender, EventArgs e)
+ {
+ OpenFileDialog dilog = new OpenFileDialog
+ {
+ Filter = "(*.jpg;*.bmp;*.png;*.JPEG)|*.jpg;*.bmp;*.png;*.JPEG"
+ };
+ if (dilog.ShowDialog() == DialogResult.OK)
+ {
+ imgPath = dilog.FileName;
+ CvMat img = Cv2.ImRead(dilog.FileName);
+ Bitmap bitmap = BitmapConverter.ToBitmap(img);
+ pictureBoxPicture.Image = bitmap;
+ }
+ }
+
+ private void buttonInference_Click(object sender, EventArgs e)
+ {
+ textBoxResult.Clear();
+ if (classifier == null)
+ {
+ MessageBox.Show("init model first");
+ return;
+ }
+
+ CvMat[] imgs = new CvMat[1] { Cv2.ImRead(imgPath, ImreadModes.Color) };
+ CvMatToMat(imgs, out var mats);
+
+ try
+ {
+ List output = classifier.Apply(mats);
+ int idx = 1;
+ foreach (var obj in output[0].Results)
+ {
+ if (obj.Score < 1e-7)
+ {
+ break;
+ }
+ string res = string.Format("Top-{0}-label: {1}, score: {2:f3}", idx, obj.Id, obj.Score);
+ if (idx == 1)
+ {
+ textBoxResult.Text = res;
+ }
+ else
+ {
+ textBoxResult.AppendText("\r\n" + res);
+ }
+ idx++;
+ }
+ } catch
+ {
+ MessageBox.Show("inference error");
+ }
+ }
+
+ private void FormDemo_Load(object sender, EventArgs e)
+ {
+ textBoxUsage.Text = "1) select model dir" +
+ "\r\n" + "2) choose device" +
+ "\r\n" + "3) init model" +
+ "\r\n" + "4) select image" +
+ "\r\n" + "5) do inference";
+
+ textBoxStatus.ForeColor = Color.Gray;
+ textBoxStatus.Text = "model not init";
+ }
+ }
+}
diff --git a/demo/csharp/image_classification/FormDemo.resx b/demo/csharp/image_classification/FormDemo.resx
new file mode 100644
index 000000000..da834e202
--- /dev/null
+++ b/demo/csharp/image_classification/FormDemo.resx
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
diff --git a/demo/csharp/image_classification/Program.cs b/demo/csharp/image_classification/Program.cs
new file mode 100644
index 000000000..599af9ed5
--- /dev/null
+++ b/demo/csharp/image_classification/Program.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace image_classification
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.SetHighDpiMode(HighDpiMode.SystemAware);
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new FormDemo());
+ }
+ }
+}
diff --git a/demo/csharp/image_classification/image_classification.csproj b/demo/csharp/image_classification/image_classification.csproj
new file mode 100644
index 000000000..6d3046244
--- /dev/null
+++ b/demo/csharp/image_classification/image_classification.csproj
@@ -0,0 +1,23 @@
+
+
+
+ Exe
+ netcoreapp3.1
+ true
+ true
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
diff --git a/demo/csharp/image_classification/image_classification.csproj.user b/demo/csharp/image_classification/image_classification.csproj.user
new file mode 100644
index 000000000..6901cae71
--- /dev/null
+++ b/demo/csharp/image_classification/image_classification.csproj.user
@@ -0,0 +1,9 @@
+
+
+
+
+
+ Form
+
+
+
diff --git a/demo/csharp/image_restorer/Program.cs b/demo/csharp/image_restorer/Program.cs
new file mode 100644
index 000000000..d70809bd1
--- /dev/null
+++ b/demo/csharp/image_restorer/Program.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using MMDeploy;
+using ImreadModes = OpenCvSharp.ImreadModes;
+using Cv2 = OpenCvSharp.Cv2;
+using CvMat = OpenCvSharp.Mat;
+using MatType = OpenCvSharp.MatType;
+using ColorConversionCodes = OpenCvSharp.ColorConversionCodes;
+using WindowFlags = OpenCvSharp.WindowFlags;
+
+namespace image_restorer
+{
+ class Program
+ {
+ ///
+ /// transform input
+ ///
+ static void CvMatToMat(CvMat[] cvMats, out Mat[] mats)
+ {
+ mats = new Mat[cvMats.Length];
+ unsafe
+ {
+ for (int i = 0; i < cvMats.Length; i++)
+ {
+ mats[i].Data = cvMats[i].DataPointer;
+ mats[i].Height = cvMats[i].Height;
+ mats[i].Width = cvMats[i].Width;
+ mats[i].Channel = cvMats[i].Dims;
+ mats[i].Format = PixelFormat.BGR;
+ mats[i].Type = DataType.Int8;
+ }
+ }
+ }
+
+ static void CvWaitKey()
+ {
+ Cv2.WaitKey();
+ }
+
+ static void Main(string[] args)
+ {
+ if (args.Length != 3)
+ {
+ Console.WriteLine("usage:\n image_restorer deviceName modelPath imagePath\n");
+ Environment.Exit(1);
+ }
+
+ string deviceName = args[0];
+ string modelPath = args[1];
+ string imagePath = args[2];
+
+ // 1. create handle
+ Restorer handle = new Restorer(modelPath, deviceName, 0);
+
+ // 2. prepare input
+ CvMat[] imgs = new CvMat[1] { Cv2.ImRead(imagePath, ImreadModes.Color) };
+ CvMatToMat(imgs, out var mats);
+
+ // 3. process
+ List output = handle.Apply(mats);
+
+ // 4. show result
+ CvMat sr_img = new CvMat(output[0].Height, output[0].Width, MatType.CV_8UC3, output[0].Data);
+ Cv2.CvtColor(sr_img, sr_img, ColorConversionCodes.RGB2BGR);
+ Cv2.NamedWindow("sr", WindowFlags.GuiExpanded);
+ Cv2.ImShow("sr", sr_img);
+ CvWaitKey();
+
+ handle.Close();
+ }
+ }
+}
diff --git a/demo/csharp/image_restorer/image_restorer.csproj b/demo/csharp/image_restorer/image_restorer.csproj
new file mode 100644
index 000000000..693587bcd
--- /dev/null
+++ b/demo/csharp/image_restorer/image_restorer.csproj
@@ -0,0 +1,22 @@
+
+
+
+ Exe
+ netcoreapp3.1
+
+
+
+ true
+
+
+
+ true
+
+
+
+
+
+
+
+
+
diff --git a/demo/csharp/image_segmentation/Program.cs b/demo/csharp/image_segmentation/Program.cs
new file mode 100644
index 000000000..9395fca67
--- /dev/null
+++ b/demo/csharp/image_segmentation/Program.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Collections.Generic;
+using OpenCvSharp;
+using MMDeploy;
+
+namespace image_segmentation
+{
+ class Program
+ {
+ ///
+ /// transform input
+ ///
+ static void CvMatToMat(OpenCvSharp.Mat[] cvMats, out MMDeploy.Mat[] mats)
+ {
+ mats = new MMDeploy.Mat[cvMats.Length];
+ unsafe
+ {
+ for (int i = 0; i < cvMats.Length; i++)
+ {
+ mats[i].Data = cvMats[i].DataPointer;
+ mats[i].Height = cvMats[i].Height;
+ mats[i].Width = cvMats[i].Width;
+ mats[i].Channel = cvMats[i].Dims;
+ mats[i].Format = PixelFormat.BGR;
+ mats[i].Type = DataType.Int8;
+ }
+ }
+ }
+
+ static void CvWaitKey()
+ {
+ Cv2.WaitKey();
+ }
+
+ static Vec3b[] GenPalette(int classes)
+ {
+ Random rnd = new Random(0);
+ Vec3b[] palette = new Vec3b[classes];
+ for (int i = 0; i < classes; i++)
+ {
+ byte v1 = (byte)rnd.Next(0, 255);
+ byte v2 = (byte)rnd.Next(0, 255);
+ byte v3 = (byte)rnd.Next(0, 255);
+ palette[i] = new Vec3b(v1, v2, v3);
+ }
+ return palette;
+ }
+
+ static void Main(string[] args)
+ {
+ if (args.Length != 3)
+ {
+ Console.WriteLine("usage:\n image_segmentation deviceName modelPath imagePath\n");
+ Environment.Exit(1);
+ }
+
+ string deviceName = args[0];
+ string modelPath = args[1];
+ string imagePath = args[2];
+
+ // 1. create handle
+ Segmentor handle = new Segmentor(modelPath, deviceName, 0);
+
+ // 2. prepare input
+ OpenCvSharp.Mat[] imgs = new OpenCvSharp.Mat[1] { Cv2.ImRead(imagePath, ImreadModes.Color) };
+ CvMatToMat(imgs, out var mats);
+
+ // 3. process
+ List output = handle.Apply(mats);
+
+ // 4. show result
+ OpenCvSharp.Mat colorMask = new OpenCvSharp.Mat(output[0].Height, output[0].Width, MatType.CV_8UC3, new Scalar());
+ Vec3b[] palette = GenPalette(output[0].Classes);
+ unsafe
+ {
+ byte* data = colorMask.DataPointer;
+ fixed (int* _label = output[0].Mask)
+ {
+ int* label = _label;
+ for (int i = 0; i < output[0].Height; i++)
+ {
+ for (int j = 0; j < output[0].Width; j++)
+ {
+ data[0] = palette[*label][0];
+ data[1] = palette[*label][1];
+ data[2] = palette[*label][2];
+ data += 3;
+ label++;
+ }
+ }
+ }
+ }
+ colorMask = imgs[0] * 0.5 + colorMask * 0.5;
+
+ Cv2.NamedWindow("mmseg", WindowFlags.GuiExpanded);
+ Cv2.ImShow("mmseg", colorMask);
+ CvWaitKey();
+
+ handle.Close();
+ }
+ }
+}
diff --git a/demo/csharp/image_segmentation/image_segmentation.csproj b/demo/csharp/image_segmentation/image_segmentation.csproj
new file mode 100644
index 000000000..693587bcd
--- /dev/null
+++ b/demo/csharp/image_segmentation/image_segmentation.csproj
@@ -0,0 +1,22 @@
+
+
+
+ Exe
+ netcoreapp3.1
+
+
+
+ true
+
+
+
+ true
+
+
+
+
+
+
+
+
+
diff --git a/demo/csharp/object_detection/Program.cs b/demo/csharp/object_detection/Program.cs
new file mode 100644
index 000000000..de146d549
--- /dev/null
+++ b/demo/csharp/object_detection/Program.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using OpenCvSharp;
+using MMDeploy;
+
+namespace object_detection
+{
+ class Program
+ {
+ static void CvMatToMat(OpenCvSharp.Mat[] cvMats, out MMDeploy.Mat[] mats)
+ {
+ mats = new MMDeploy.Mat[cvMats.Length];
+ unsafe
+ {
+ for (int i = 0; i < cvMats.Length; i++)
+ {
+ mats[i].Data = cvMats[i].DataPointer;
+ mats[i].Height = cvMats[i].Height;
+ mats[i].Width = cvMats[i].Width;
+ mats[i].Channel = cvMats[i].Dims;
+ mats[i].Format = PixelFormat.BGR;
+ mats[i].Type = DataType.Int8;
+ }
+ }
+ }
+
+ static void CvWaitKey()
+ {
+ Cv2.WaitKey();
+ }
+
+ static void Main(string[] args)
+ {
+ if (args.Length != 3)
+ {
+ Console.WriteLine("usage:\n object_detection deviceName modelPath imagePath\n");
+ Environment.Exit(1);
+ }
+
+ string deviceName = args[0];
+ string modelPath = args[1];
+ string imagePath = args[2];
+
+ // 1. create handle
+ Detector handle = new Detector(modelPath, deviceName, 0);
+
+ // 2. prepare input
+ OpenCvSharp.Mat[] imgs = new OpenCvSharp.Mat[1] { Cv2.ImRead(imagePath, ImreadModes.Color) };
+ CvMatToMat(imgs, out var mats);
+
+ // 3. process
+ List output = handle.Apply(mats);
+
+ // 4. show result
+ foreach (var obj in output[0].Results)
+ {
+ if (obj.Score > 0.3)
+ {
+ if (obj.HasMask)
+ {
+ OpenCvSharp.Mat imgMask = new OpenCvSharp.Mat(obj.Mask.Height, obj.Mask.Width, MatType.CV_8UC1, obj.Mask.Data);
+ float x0 = Math.Max((float)Math.Floor(obj.BBox.Left) - 1, 0f);
+ float y0 = Math.Max((float)Math.Floor(obj.BBox.Top) - 1, 0f);
+ OpenCvSharp.Rect roi = new OpenCvSharp.Rect((int)x0, (int)y0, obj.Mask.Width, obj.Mask.Height);
+ Cv2.Split(imgs[0], out OpenCvSharp.Mat[] ch);
+ int col = 0;
+ Cv2.BitwiseOr(imgMask, ch[col][roi], ch[col][roi]);
+ Cv2.Merge(ch, imgs[0]);
+ }
+
+ Cv2.Rectangle(imgs[0], new Point((int)obj.BBox.Left, (int)obj.BBox.Top),
+ new Point((int)obj.BBox.Right, obj.BBox.Bottom), new Scalar(0, 255, 0));
+ }
+ }
+ Cv2.NamedWindow("mmdet", WindowFlags.GuiExpanded);
+ Cv2.ImShow("mmdet", imgs[0]);
+ CvWaitKey();
+
+ handle.Close();
+ }
+ }
+}
diff --git a/demo/csharp/object_detection/object_detection.csproj b/demo/csharp/object_detection/object_detection.csproj
new file mode 100644
index 000000000..693587bcd
--- /dev/null
+++ b/demo/csharp/object_detection/object_detection.csproj
@@ -0,0 +1,22 @@
+
+
+
+ Exe
+ netcoreapp3.1
+
+
+
+ true
+
+
+
+ true
+
+
+
+
+
+
+
+
+
diff --git a/demo/csharp/ocr_detection/Program.cs b/demo/csharp/ocr_detection/Program.cs
new file mode 100644
index 000000000..0c96fcedc
--- /dev/null
+++ b/demo/csharp/ocr_detection/Program.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using OpenCvSharp;
+using MMDeploy;
+
+namespace ocr_detection
+{
+ class Program
+ {
+ static void CvMatToMat(OpenCvSharp.Mat[] cvMats, out MMDeploy.Mat[] mats)
+ {
+ mats = new MMDeploy.Mat[cvMats.Length];
+ unsafe
+ {
+ for (int i = 0; i < cvMats.Length; i++)
+ {
+ mats[i].Data = cvMats[i].DataPointer;
+ mats[i].Height = cvMats[i].Height;
+ mats[i].Width = cvMats[i].Width;
+ mats[i].Channel = cvMats[i].Dims;
+ mats[i].Format = PixelFormat.BGR;
+ mats[i].Type = DataType.Int8;
+ }
+ }
+ }
+
+ static void CvWaitKey()
+ {
+ Cv2.WaitKey();
+ }
+
+ static void Main(string[] args)
+ {
+ if (args.Length != 3)
+ {
+ Console.WriteLine("usage:\n ocr_detection deviceName modelPath imagePath\n");
+ Environment.Exit(1);
+ }
+
+ string deviceName = args[0];
+ string modelPath = args[1];
+ string imagePath = args[2];
+
+ // 1. create handle
+ MMDeploy.TextDetector handle = new MMDeploy.TextDetector(modelPath, deviceName, 0);
+
+ // 2. prepare input
+ OpenCvSharp.Mat[] imgs = new OpenCvSharp.Mat[1] { Cv2.ImRead(imagePath, ImreadModes.Color) };
+ CvMatToMat(imgs, out var mats);
+
+ // 3. process
+ List output = handle.Apply(mats);
+
+ // 4. show result
+ foreach (var detect in output[0].Results)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ int sp = i;
+ int ep = (i + 1) % 4;
+ Cv2.Line(imgs[0], new Point((int)detect.BBox[sp].X, (int)detect.BBox[sp].Y),
+ new Point((int)detect.BBox[ep].X, (int)detect.BBox[ep].Y), new Scalar(0, 255, 0));
+ }
+ }
+
+ Cv2.NamedWindow("ocr-det", WindowFlags.GuiExpanded);
+ Cv2.ImShow("ocr-det", imgs[0]);
+ CvWaitKey();
+
+ handle.Close();
+ }
+ }
+}
diff --git a/demo/csharp/ocr_detection/ocr_detection.csproj b/demo/csharp/ocr_detection/ocr_detection.csproj
new file mode 100644
index 000000000..693587bcd
--- /dev/null
+++ b/demo/csharp/ocr_detection/ocr_detection.csproj
@@ -0,0 +1,22 @@
+
+
+
+ Exe
+ netcoreapp3.1
+
+
+
+ true
+
+
+
+ true
+
+
+
+
+
+
+
+
+
diff --git a/demo/csharp/ocr_recognition/Program.cs b/demo/csharp/ocr_recognition/Program.cs
new file mode 100644
index 000000000..04ed3bfc2
--- /dev/null
+++ b/demo/csharp/ocr_recognition/Program.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using OpenCvSharp;
+using MMDeploy;
+
+namespace ocr_recognition
+{
+ class Program
+ {
+ static void CvMatToMat(OpenCvSharp.Mat[] cvMats, out MMDeploy.Mat[] mats)
+ {
+ mats = new MMDeploy.Mat[cvMats.Length];
+ unsafe
+ {
+ for (int i = 0; i < cvMats.Length; i++)
+ {
+ mats[i].Data = cvMats[i].DataPointer;
+ mats[i].Height = cvMats[i].Height;
+ mats[i].Width = cvMats[i].Width;
+ mats[i].Channel = cvMats[i].Dims;
+ mats[i].Format = PixelFormat.BGR;
+ mats[i].Type = DataType.Int8;
+ }
+ }
+ }
+
+ static void CvWaitKey()
+ {
+ Cv2.WaitKey();
+ }
+
+ static void Main(string[] args)
+ {
+ if (args.Length != 3)
+ {
+ Console.WriteLine("usage:\n ocr_recognition deviceName modelPath imagePath\n");
+ Environment.Exit(1);
+ }
+
+ string deviceName = args[0];
+ string modelPath = args[1];
+ string imagePath = args[2];
+
+ // 1. create handle
+ TextRecognizer handle = new TextRecognizer(modelPath, deviceName, 0);
+
+ // 2. prepare input
+ OpenCvSharp.Mat[] imgs = new OpenCvSharp.Mat[1] { Cv2.ImRead(imagePath, ImreadModes.Color) };
+ CvMatToMat(imgs, out var mats);
+
+ // 3. process
+ List output = handle.Apply(mats);
+
+ //// 4. show result
+ foreach (var box in output[0].Results)
+ {
+ string text = System.Text.Encoding.UTF8.GetString(box.Text);
+ Cv2.PutText(imgs[0], text, new Point(20, 20), HersheyFonts.HersheySimplex, 0.7, new Scalar(0, 255, 0), 1);
+ }
+
+ Cv2.NamedWindow("ocr-reg", WindowFlags.GuiExpanded);
+ Cv2.ImShow("ocr-reg", imgs[0]);
+ CvWaitKey();
+
+ handle.Close();
+ }
+ }
+}
diff --git a/demo/csharp/ocr_recognition/ocr_recognition.csproj b/demo/csharp/ocr_recognition/ocr_recognition.csproj
new file mode 100644
index 000000000..693587bcd
--- /dev/null
+++ b/demo/csharp/ocr_recognition/ocr_recognition.csproj
@@ -0,0 +1,22 @@
+
+
+
+ Exe
+ netcoreapp3.1
+
+
+
+ true
+
+
+
+ true
+
+
+
+
+
+
+
+
+
diff --git a/demo/csharp/pose_detection/Program.cs b/demo/csharp/pose_detection/Program.cs
new file mode 100644
index 000000000..67367f400
--- /dev/null
+++ b/demo/csharp/pose_detection/Program.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+using OpenCvSharp;
+using MMDeploy;
+
+namespace pose_detection
+{
+ class Program
+ {
+ static void CvMatToMat(OpenCvSharp.Mat[] cvMats, out MMDeploy.Mat[] mats)
+ {
+ mats = new MMDeploy.Mat[cvMats.Length];
+ unsafe
+ {
+ for (int i = 0; i < cvMats.Length; i++)
+ {
+ mats[i].Data = cvMats[i].DataPointer;
+ mats[i].Height = cvMats[i].Height;
+ mats[i].Width = cvMats[i].Width;
+ mats[i].Channel = cvMats[i].Dims;
+ mats[i].Format = PixelFormat.BGR;
+ mats[i].Type = DataType.Int8;
+ }
+ }
+ }
+
+ static void CvWaitKey()
+ {
+ Cv2.WaitKey();
+ }
+
+ static Vec3b[] GenPalette(int n)
+ {
+ Random rnd = new Random(2);
+ Vec3b[] palette = new Vec3b[n];
+ for (int i = 0; i < n; i++)
+ {
+ byte v1 = (byte)rnd.Next(0, 255);
+ byte v2 = (byte)rnd.Next(0, 255);
+ byte v3 = (byte)rnd.Next(0, 255);
+ palette[i] = new Vec3b(v1, v2, v3);
+ }
+ return palette;
+ }
+
+ static void Main(string[] args)
+ {
+ if (args.Length != 3)
+ {
+ Console.WriteLine("usage:\n pose_detection deviceName modelPath imagePath\n");
+ Environment.Exit(1);
+ }
+
+ string deviceName = args[0];
+ string modelPath = args[1];
+ string imagePath = args[2];
+
+ // 1. create handle
+ PoseDetector handle = new PoseDetector(modelPath, deviceName, 0);
+
+ // 2. prepare input
+ OpenCvSharp.Mat[] imgs = new OpenCvSharp.Mat[1] { Cv2.ImRead(imagePath, ImreadModes.Color) };
+ CvMatToMat(imgs, out var mats);
+
+ // 3. process
+ List output = handle.Apply(mats);
+
+ // 4. show result
+ Vec3b[] palette = GenPalette(output[0].Count);
+ int index = 0;
+ foreach (var box in output[0].Results)
+ {
+ for (int i = 0; i < box.Points.Count; i++)
+ {
+ Cv2.Circle(imgs[0], (int)box.Points[i].X, (int)box.Points[i].Y, 1,
+ new Scalar(palette[index][0], palette[index][1], palette[index][2]), 2);
+ }
+ index++;
+ }
+ Cv2.NamedWindow("pose", WindowFlags.GuiExpanded);
+ Cv2.ImShow("pose", imgs[0]);
+ CvWaitKey();
+
+ handle.Close();
+ }
+ }
+}
diff --git a/demo/csharp/pose_detection/pose_detection.csproj b/demo/csharp/pose_detection/pose_detection.csproj
new file mode 100644
index 000000000..693587bcd
--- /dev/null
+++ b/demo/csharp/pose_detection/pose_detection.csproj
@@ -0,0 +1,22 @@
+
+
+
+ Exe
+ netcoreapp3.1
+
+
+
+ true
+
+
+
+ true
+
+
+
+
+
+
+
+
+