Skip to content

Commit

Permalink
add csharp support (open-mmlab#388)
Browse files Browse the repository at this point in the history
* add csharp support, init commit

* export MMDeploySharpExtern.dll when build sdk

* refactor code

* multi frameworks

* move csharp demo to demo folder

* try to fix lint

* try to fix lint

* update csharp demo Readme

* rename MMDeploySharp -> MMDeploy

* add comment why build MMDeployExtern.dll

* squeeze MMDeploy project

* remove Mm

* print error code

* update c# api build README.md

* fix exception

* fix exception

* update demo

* update README.md

* fix typo

* fix ci

* fix ci

* fix formatresult

* add options whether build MMDeployExtern.dll

* update CMakeListst.txt

* change MMDEPLOY_BUILD_CSHARP_EXTERN -> MMDEPLOY_BUILD_SDK_CSHARP_API

* c# api -> C# API

Co-authored-by: chenxin2 <chenxin2@sensetime.com>
  • Loading branch information
irexyc and irexyc committed May 27, 2022
1 parent b7bdd21 commit 9e6a3c8
Show file tree
Hide file tree
Showing 39 changed files with 3,194 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ work_dirs/
/cmake-build-debug*
/cmake-build-release*

# c#
.vs/
obj/
bin/

# install directory
/install

Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
11 changes: 11 additions & 0 deletions csrc/apis/c/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
50 changes: 50 additions & 0 deletions csrc/apis/csharp/MMDeploy.sln
Original file line number Diff line number Diff line change
@@ -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
110 changes: 110 additions & 0 deletions csrc/apis/csharp/MMDeploy/.editorconfig
Original file line number Diff line number Diff line change
@@ -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
135 changes: 135 additions & 0 deletions csrc/apis/csharp/MMDeploy/APIs/Classifier.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
using System.Collections.Generic;

namespace MMDeploy
{
/// <summary>
/// Single classification result of a picture.
/// A picture may contains multiple reuslts.
/// </summary>
public struct Label
{
/// <summary>
/// Id.
/// </summary>
public int Id;

/// <summary>
/// Score.
/// </summary>
public float Score;

/// <summary>
/// Initializes a new instance of the <see cref="Label"/> struct.
/// </summary>
/// <param name="id">id.</param>
/// <param name="score">score.</param>
public Label(int id, float score)
{
Id = id;
Score = score;
}
}

/// <summary>
/// Output of Classifier.
/// </summary>
public struct ClassifierOutput
{
/// <summary>
/// Classification results for single image.
/// </summary>
public List<Label> Results;

/// <summary>
/// Add result to single image.
/// </summary>
/// <param name="id">id.</param>
/// <param name="score">score.</param>
public void Add(int id, float score)
{
if (Results == null)
{
Results = new List<Label>();
}

Results.Add(new Label(id, score));
}

/// <summary>
/// Gets number of output.
/// </summary>
public int Count
{
get { return (Results == null) ? 0 : Results.Count; }
}
}

/// <summary>
/// classifier.
/// </summary>
public class Classifier : DisposableObject
{
/// <summary>
/// Initializes a new instance of the <see cref="Classifier"/> class.
/// </summary>
/// <param name="modelPath">model path.</param>
/// <param name="deviceName">device name.</param>
/// <param name="deviceId">deviceId.</param>
public Classifier(string modelPath, string deviceName, int deviceId)
{
ThrowException(NativeMethods.mmdeploy_classifier_create_by_path(modelPath, deviceName, deviceId, out _handle));
}

/// <summary>
/// Get label information of each image in a batch.
/// </summary>
/// <param name="mats">input mats.</param>
/// <returns>Results of each input mat.</returns>
public List<ClassifierOutput> Apply(Mat[] mats)
{
List<ClassifierOutput> output = new List<ClassifierOutput>();
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<ClassifierOutput> 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);
}

/// <inheritdoc/>
protected override void ReleaseHandle()
{
NativeMethods.mmdeploy_classifier_destroy(_handle);
}
}
}
Loading

0 comments on commit 9e6a3c8

Please sign in to comment.