add csharp support (#388)
* 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>pull/534/head
parent
b7bdd2172b
commit
9e6a3c8ec5
|
@ -129,6 +129,11 @@ work_dirs/
|
|||
/cmake-build-debug*
|
||||
/cmake-build-release*
|
||||
|
||||
# c#
|
||||
.vs/
|
||||
obj/
|
||||
bin/
|
||||
|
||||
# install directory
|
||||
/install
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,234 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MMDeploy
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
/// <summary>
|
||||
/// mm_instance_mask_t of c code.
|
||||
/// </summary>
|
||||
internal unsafe struct CInstanceMask
|
||||
{
|
||||
public char* Data;
|
||||
public int Height;
|
||||
public int Width;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// mm_detect_t of c code.
|
||||
/// </summary>
|
||||
internal unsafe struct CDetect
|
||||
{
|
||||
public int LabelId;
|
||||
public float Score;
|
||||
public Rect BBox;
|
||||
public CInstanceMask* Mask;
|
||||
}
|
||||
#pragma warning restore 0649
|
||||
|
||||
/// <summary>
|
||||
/// Instance mask.
|
||||
/// </summary>
|
||||
public struct InstanceMask
|
||||
{
|
||||
/// <summary>
|
||||
/// Height.
|
||||
/// </summary>
|
||||
public int Height;
|
||||
|
||||
/// <summary>
|
||||
/// Width.
|
||||
/// </summary>
|
||||
public int Width;
|
||||
|
||||
/// <summary>
|
||||
/// Raw data.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Single detection result of a picture.
|
||||
/// A picture may contains multiple reuslts.
|
||||
/// </summary>
|
||||
public struct Detect
|
||||
{
|
||||
/// <summary>
|
||||
/// Label id.
|
||||
/// </summary>
|
||||
public int LabelId;
|
||||
|
||||
/// <summary>
|
||||
/// Score.
|
||||
/// </summary>
|
||||
public float Score;
|
||||
|
||||
/// <summary>
|
||||
/// Bounding box.
|
||||
/// </summary>
|
||||
public Rect BBox;
|
||||
|
||||
/// <summary>
|
||||
/// Whether has mask.
|
||||
/// </summary>
|
||||
public bool HasMask;
|
||||
|
||||
/// <summary>
|
||||
/// Mask.
|
||||
/// </summary>
|
||||
public InstanceMask Mask;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Detect"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="labelId">label id.</param>
|
||||
/// <param name="score"> score.</param>
|
||||
/// <param name="bbox">bounding box.</param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output of Detector.
|
||||
/// </summary>
|
||||
public struct DetectorOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// Detection results for single image.
|
||||
/// </summary>
|
||||
public List<Detect> Results;
|
||||
|
||||
/// <summary>
|
||||
/// Init Reuslts.
|
||||
/// </summary>
|
||||
public void Init()
|
||||
{
|
||||
if (Results == null)
|
||||
{
|
||||
Results = new List<Detect>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add result to single image.
|
||||
/// </summary>
|
||||
/// <param name="labelId">label id.</param>
|
||||
/// <param name="score">score.</param>
|
||||
/// <param name="bbox">bounding box.</param>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets number of output.
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get { return (Results == null) ? 0 : Results.Count; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detector.
|
||||
/// </summary>
|
||||
public class Detector : DisposableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Detector"/> class.
|
||||
/// </summary>
|
||||
/// <param name="modelPath">model path.</param>
|
||||
/// <param name="deviceName">device name.</param>
|
||||
/// <param name="deviceId">device id.</param>
|
||||
public Detector(string modelPath, string deviceName, int deviceId)
|
||||
{
|
||||
ThrowException(NativeMethods.mmdeploy_detector_create_by_path(modelPath, deviceName, deviceId, out _handle));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get information of each image in a batch.
|
||||
/// </summary>
|
||||
/// <param name="mats">input mats.</param>
|
||||
/// <returns>Results of each input mat.</returns>
|
||||
public List<DetectorOutput> Apply(Mat[] mats)
|
||||
{
|
||||
List<DetectorOutput> output = new List<DetectorOutput>();
|
||||
|
||||
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<DetectorOutput> 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);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void ReleaseHandle()
|
||||
{
|
||||
NativeMethods.mmdeploy_detector_destroy(_handle);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MMDeploy
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class which manages its own memory.
|
||||
/// </summary>
|
||||
public class DisposableObject : IDisposable
|
||||
{
|
||||
#pragma warning disable SA1401 // Fields should be private
|
||||
/// <summary>
|
||||
/// Handle pointer.
|
||||
/// </summary>
|
||||
protected IntPtr _handle;
|
||||
#pragma warning restore SA1401 // Fields should be private
|
||||
|
||||
private bool _disposed = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance has been disposed.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close handle.
|
||||
/// </summary>
|
||||
public void Close()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases the resources.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases managed resources.
|
||||
/// </summary>
|
||||
protected virtual void ReleaseManaged()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases unmanaged resources.
|
||||
/// </summary>
|
||||
protected virtual void ReleaseHandle()
|
||||
{
|
||||
Marshal.FreeHGlobal(_handle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="DisposableObject"/> class.
|
||||
/// </summary>
|
||||
~DisposableObject()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Throw exception is result is not zero.
|
||||
/// </summary>
|
||||
/// <param name="result">function return value.</param>
|
||||
protected static void ThrowException(int result)
|
||||
{
|
||||
if (result != 0)
|
||||
{
|
||||
throw new Exception(result.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
/// <summary>
|
||||
/// Single detection result of a bbox.
|
||||
/// A picture may contains multiple reuslts.
|
||||
/// </summary>
|
||||
public struct PoseDetect
|
||||
{
|
||||
/// <summary>
|
||||
/// Keypoins.
|
||||
/// </summary>
|
||||
public List<Pointf> Points;
|
||||
|
||||
/// <summary>
|
||||
/// Scores.
|
||||
/// </summary>
|
||||
public List<float> Scores;
|
||||
|
||||
/// <summary>
|
||||
/// Init points and scores if empty.
|
||||
/// </summary>
|
||||
private void Init()
|
||||
{
|
||||
if (Points == null || Scores == null)
|
||||
{
|
||||
Points = new List<Pointf>();
|
||||
Scores = new List<float>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add single keypoint to list.
|
||||
/// </summary>
|
||||
/// <param name="point">Keypoint.</param>
|
||||
/// <param name="score">Score.</param>
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output of PoseDetector.
|
||||
/// </summary>
|
||||
public struct PoseDetectorOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// Pose detection results for single image.
|
||||
/// </summary>
|
||||
public List<PoseDetect> Results;
|
||||
|
||||
/// <summary>
|
||||
/// Gets number of output.
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get { return (Results == null) ? 0 : Results.Count; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Result for box level.
|
||||
/// </summary>
|
||||
/// <param name="boxRes">Box res.</param>
|
||||
public void Add(PoseDetect boxRes)
|
||||
{
|
||||
if (Results == null)
|
||||
{
|
||||
Results = new List<PoseDetect>();
|
||||
}
|
||||
|
||||
Results.Add(boxRes);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PoseDetector.
|
||||
/// </summary>
|
||||
public class PoseDetector : DisposableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PoseDetector"/> class.
|
||||
/// </summary>
|
||||
/// <param name="modelPath">model path.</param>
|
||||
/// <param name="deviceName">device name.</param>
|
||||
/// <param name="deviceId">device id.</param>
|
||||
public PoseDetector(string modelPath, string deviceName, int deviceId)
|
||||
{
|
||||
ThrowException(NativeMethods.mmdeploy_pose_detector_create_by_path(modelPath, deviceName, deviceId, out _handle));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get information of each image in a batch.
|
||||
/// </summary>
|
||||
/// <param name="mats">input mats.</param>
|
||||
/// <param name="bboxes">bounding boxes..</param>
|
||||
/// <param name="bboxCount">bounding boxes count for each image.</param>
|
||||
/// <returns>Results of each input mat.</returns>
|
||||
public List<PoseDetectorOutput> Apply(Mat[] mats, Rect[] bboxes, int[] bboxCount)
|
||||
{
|
||||
List<PoseDetectorOutput> output = new List<PoseDetectorOutput>();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get information of each image in a batch.
|
||||
/// </summary>
|
||||
/// <param name="mats">Input mats.</param>
|
||||
/// <returns>Results of each input mat.</returns>
|
||||
public List<PoseDetectorOutput> Apply(Mat[] mats)
|
||||
{
|
||||
List<PoseDetectorOutput> output = new List<PoseDetectorOutput>();
|
||||
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<PoseDetectorOutput> 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);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void ReleaseHandle()
|
||||
{
|
||||
NativeMethods.mmdeploy_pose_detector_destroy(_handle);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MMDeploy
|
||||
{
|
||||
/// <summary>
|
||||
/// Output of Restorer.
|
||||
/// </summary>
|
||||
public struct RestorerOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// Height.
|
||||
/// </summary>
|
||||
public int Height;
|
||||
|
||||
/// <summary>
|
||||
/// Width.
|
||||
/// </summary>
|
||||
public int Width;
|
||||
|
||||
/// <summary>
|
||||
/// Raw data.
|
||||
/// </summary>
|
||||
public byte[] Data;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RestorerOutput"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="height">height.</param>
|
||||
/// <param name="width">width.</param>
|
||||
/// <param name="data">data.</param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restorer.
|
||||
/// </summary>
|
||||
public class Restorer : DisposableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Restorer"/> class.
|
||||
/// </summary>
|
||||
/// <param name="modelPath">model path.</param>
|
||||
/// <param name="deviceName">device name.</param>
|
||||
/// <param name="deviceId">device id.</param>
|
||||
public Restorer(string modelPath, string deviceName, int deviceId)
|
||||
{
|
||||
ThrowException(NativeMethods.mmdeploy_restorer_create_by_path(modelPath, deviceName, deviceId, out _handle));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get information of each image in a batch.
|
||||
/// </summary>
|
||||
/// <param name="mats">input mats.</param>
|
||||
/// <returns>Results of each input mat.</returns>
|
||||
public List<RestorerOutput> Apply(Mat[] mats)
|
||||
{
|
||||
List<RestorerOutput> output = new List<RestorerOutput>();
|
||||
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<RestorerOutput> 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);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void ReleaseHandle()
|
||||
{
|
||||
NativeMethods.mmdeploy_restorer_destroy(_handle);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
/// <summary>
|
||||
/// Output of Segmentor.
|
||||
/// </summary>
|
||||
public struct SegmentorOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// Height of image.
|
||||
/// </summary>
|
||||
public int Height;
|
||||
|
||||
/// <summary>
|
||||
/// Width if image.
|
||||
/// </summary>
|
||||
public int Width;
|
||||
|
||||
/// <summary>
|
||||
/// Number of classes.
|
||||
/// </summary>
|
||||
public int Classes;
|
||||
|
||||
/// <summary>
|
||||
/// Mask data.
|
||||
/// </summary>
|
||||
public int[] Mask;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SegmentorOutput"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="height">height.</param>
|
||||
/// <param name="width">width.</param>
|
||||
/// <param name="classes">classes.</param>
|
||||
/// <param name="mask">mask.</param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Segmentor.
|
||||
/// </summary>
|
||||
public class Segmentor : DisposableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Segmentor"/> class.
|
||||
/// </summary>
|
||||
/// <param name="modelPath">model path.</param>
|
||||
/// <param name="deviceName">device name.</param>
|
||||
/// <param name="deviceId">device id.</param>
|
||||
public Segmentor(string modelPath, string deviceName, int deviceId)
|
||||
{
|
||||
ThrowException(NativeMethods.mmdeploy_segmentor_create_by_path(modelPath, deviceName, deviceId, out _handle));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get information of each image in a batch.
|
||||
/// </summary>
|
||||
/// <param name="mats">input mats.</param>
|
||||
/// <returns>Results of each input mat.</returns>
|
||||
public List<SegmentorOutput> Apply(Mat[] mats)
|
||||
{
|
||||
List<SegmentorOutput> output = new List<SegmentorOutput>();
|
||||
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<SegmentorOutput> 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);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void ReleaseHandle()
|
||||
{
|
||||
NativeMethods.mmdeploy_segmentor_destroy(_handle);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,213 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MMDeploy
|
||||
{
|
||||
/// <summary>
|
||||
/// Box.
|
||||
/// </summary>
|
||||
public struct TextBox
|
||||
{
|
||||
/// <summary>
|
||||
/// P1.
|
||||
/// </summary>
|
||||
public Pointf P1;
|
||||
|
||||
/// <summary>
|
||||
/// P2.
|
||||
/// </summary>
|
||||
public Pointf P2;
|
||||
|
||||
/// <summary>
|
||||
/// P3.
|
||||
/// </summary>
|
||||
public Pointf P3;
|
||||
|
||||
/// <summary>
|
||||
/// P4.
|
||||
/// </summary>
|
||||
public Pointf P4;
|
||||
|
||||
/// <summary>
|
||||
/// Get reference Pi.
|
||||
/// </summary>
|
||||
/// <param name="i">ith point.</param>
|
||||
/// <returns>Pi reference.</returns>
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Single detection result of a picture.
|
||||
/// A picture may contains multiple reuslts.
|
||||
/// </summary>
|
||||
public struct TextDetect
|
||||
{
|
||||
/// <summary>
|
||||
/// Bounding box.
|
||||
/// </summary>
|
||||
public TextBox BBox;
|
||||
|
||||
/// <summary>
|
||||
/// Score.
|
||||
/// </summary>
|
||||
public float Score;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TextDetect"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="score">score.</param>
|
||||
/// <param name="bbox">bbox.</param>
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output of DetectorOutput.
|
||||
/// </summary>
|
||||
public struct TextDetectorOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// Detection results for single image.
|
||||
/// </summary>
|
||||
public List<TextDetect> Results;
|
||||
|
||||
private void Init()
|
||||
{
|
||||
if (Results == null)
|
||||
{
|
||||
Results = new List<TextDetect>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add result to single image.
|
||||
/// </summary>
|
||||
/// <param name="bbox">bbox.</param>
|
||||
/// <param name="score">score.</param>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets number of output.
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get { return (Results == null) ? 0 : Results.Count; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TextDetector.
|
||||
/// </summary>
|
||||
public class TextDetector : DisposableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TextDetector"/> class.
|
||||
/// </summary>
|
||||
/// <param name="modelPath">model path.</param>
|
||||
/// <param name="deviceName">device name.</param>
|
||||
/// <param name="deviceId">device id.</param>
|
||||
public TextDetector(string modelPath, string deviceName, int deviceId)
|
||||
{
|
||||
ThrowException(NativeMethods.mmdeploy_text_detector_create_by_path(modelPath, deviceName, deviceId, out _handle));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get information of each image in a batch.
|
||||
/// </summary>
|
||||
/// <param name="mats">input mats.</param>
|
||||
/// <returns>Results of each input mat.</returns>
|
||||
public List<TextDetectorOutput> Apply(Mat[] mats)
|
||||
{
|
||||
List<TextDetectorOutput> output = new List<TextDetectorOutput>();
|
||||
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<TextDetectorOutput> 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);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void ReleaseHandle()
|
||||
{
|
||||
NativeMethods.mmdeploy_text_detector_destroy(_handle);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
/// <summary>
|
||||
/// Single result of a picture.
|
||||
/// A picture may contains multiple reuslts.
|
||||
/// </summary>
|
||||
public struct TextRecognize
|
||||
{
|
||||
/// <summary>
|
||||
/// Texts.
|
||||
/// </summary>
|
||||
public byte[] Text;
|
||||
|
||||
/// <summary>
|
||||
/// Scores.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output of TextRecognizer.
|
||||
/// </summary>
|
||||
public struct TextRecognizerOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// Text recognization results for single image.
|
||||
/// </summary>
|
||||
public List<TextRecognize> Results;
|
||||
|
||||
private void Init()
|
||||
{
|
||||
if (Results == null)
|
||||
{
|
||||
Results = new List<TextRecognize>();
|
||||
}
|
||||
}
|
||||
|
||||
internal unsafe void Add(CTextRecognize* result)
|
||||
{
|
||||
Init();
|
||||
Results.Add(new TextRecognize(result));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TextRecognizer.
|
||||
/// </summary>
|
||||
public class TextRecognizer : DisposableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TextRecognizer"/> class.
|
||||
/// </summary>
|
||||
/// <param name="modelPath">model path.</param>
|
||||
/// <param name="deviceName">device name.</param>
|
||||
/// <param name="deviceId">device id.</param>
|
||||
public TextRecognizer(string modelPath, string deviceName, int deviceId)
|
||||
{
|
||||
ThrowException(NativeMethods.mmdeploy_text_recognizer_create_by_path(modelPath, deviceName, deviceId, out _handle));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get information of each image in a batch.
|
||||
/// </summary>
|
||||
/// <param name="mats">input mats.</param>
|
||||
/// <returns>Results of each input mat.</returns>
|
||||
public List<TextRecognizerOutput> Apply(Mat[] mats)
|
||||
{
|
||||
List<TextRecognizerOutput> output = new List<TextRecognizerOutput>();
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get information of each image in a batch.
|
||||
/// </summary>
|
||||
/// <param name="mats">input mats.</param>
|
||||
/// <param name="vdetects">detection for each image.</param>
|
||||
/// <returns>Results of each input mat.</returns>
|
||||
public List<TextRecognizerOutput> Apply(Mat[] mats, List<TextDetectorOutput> vdetects)
|
||||
{
|
||||
List<TextRecognizerOutput> output = new List<TextRecognizerOutput>();
|
||||
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<TextRecognizerOutput> 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);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void ReleaseHandle()
|
||||
{
|
||||
NativeMethods.mmdeploy_text_recognizer_destroy(_handle);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
#pragma warning disable 1591
|
||||
namespace MMDeploy
|
||||
{
|
||||
/// <summary>
|
||||
/// Pixel format.
|
||||
/// </summary>
|
||||
public enum PixelFormat
|
||||
{
|
||||
BGR,
|
||||
RGB,
|
||||
Grayscale,
|
||||
NV12,
|
||||
NV21,
|
||||
BGRA,
|
||||
UnknownPixelFormat
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mat data type.
|
||||
/// </summary>
|
||||
public enum DataType
|
||||
{
|
||||
Float,
|
||||
Half,
|
||||
Int8,
|
||||
Int32,
|
||||
UnknownDataType
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function return value.
|
||||
/// </summary>
|
||||
public enum Status
|
||||
{
|
||||
Success = 0,
|
||||
InvalidArg = 1,
|
||||
NotSupported = 2,
|
||||
OutOfRange = 3,
|
||||
OutOfMemory = 4,
|
||||
FileNotExist = 5,
|
||||
Fail = 6,
|
||||
Unknown = -1,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// c struct of mm_mat_t.
|
||||
/// </summary>
|
||||
public unsafe struct Mat
|
||||
{
|
||||
public byte* Data;
|
||||
public int Height;
|
||||
public int Width;
|
||||
public int Channel;
|
||||
public PixelFormat Format;
|
||||
public DataType Type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rect of float value.
|
||||
/// </summary>
|
||||
public struct Rect
|
||||
{
|
||||
public float Left;
|
||||
public float Top;
|
||||
public float Right;
|
||||
public float Bottom;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Point of int.
|
||||
/// </summary>
|
||||
public struct Pointi
|
||||
{
|
||||
public int X;
|
||||
public int Y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Point of float.
|
||||
/// </summary>
|
||||
public struct Pointf
|
||||
{
|
||||
public float X;
|
||||
public float Y;
|
||||
public Pointf(float x, float y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp3.1;net48;</TargetFrameworks>
|
||||
<LangVersion>9.0</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<AssemblyName>MMDeploy</AssemblyName>
|
||||
<RootNamespace>MMDeploy</RootNamespace>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<Deterministic>true</Deterministic>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<MMDeployExternalNativeDlls>$(MSBuildThisFileDirectory)\..\..\..\..</MMDeployExternalNativeDlls>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Content CopyToOutputDirectory="PreserveNewest" Include="$(MMDeployExternalNativeDlls)\build\bin\Release\MMDeployExtern.dll" Pack="true" PackagePath="runtimes\win-x64\native\MMDeployExtern.dll" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net48'">
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,10 @@
|
|||
namespace MMDeploy
|
||||
{
|
||||
/// <summary>
|
||||
/// Nativate C methods.
|
||||
/// </summary>
|
||||
internal static partial class NativeMethods
|
||||
{
|
||||
public const string DllExtern = "MMDeployExtern";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
using System;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MMDeploy
|
||||
{
|
||||
/// <summary>
|
||||
/// Nativate C methods.
|
||||
/// </summary>
|
||||
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
|
||||
}
|
||||
}
|
|
@ -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")]
|
|
@ -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.
|
|
@ -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
|
|
@ -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.
|
|
@ -0,0 +1,315 @@
|
|||
|
||||
namespace image_classification
|
||||
{
|
||||
partial class FormDemo
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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<ClassifierOutput> 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";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.SetHighDpiMode(HighDpiMode.SystemAware);
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new FormDemo());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<ApplicationIcon />
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MMDeploy" Version="1.0.0" />
|
||||
<PackageReference Include="OpenCvSharp4" Version="4.5.5.20211231" />
|
||||
<PackageReference Include="OpenCvSharp4.Extensions" Version="4.5.5.20211231" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.5.5.20211231" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
<ItemGroup>
|
||||
<Compile Update="FormDemo.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// transform input
|
||||
/// </summary>
|
||||
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<RestorerOutput> 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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MMDeploy" Version="1.0.0" />
|
||||
<PackageReference Include="OpenCvSharp4" Version="4.5.5.20211231" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.5.5.20211231" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,102 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenCvSharp;
|
||||
using MMDeploy;
|
||||
|
||||
namespace image_segmentation
|
||||
{
|
||||
class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// transform input
|
||||
/// </summary>
|
||||
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<SegmentorOutput> 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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MMDeploy" Version="1.0.0" />
|
||||
<PackageReference Include="OpenCvSharp4" Version="4.5.5.20211231" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.5.5.20211231" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -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<DetectorOutput> 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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MMDeploy" Version="1.0.0" />
|
||||
<PackageReference Include="OpenCvSharp4" Version="4.5.5.20211231" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.5.5.20211231" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -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<TextDetectorOutput> 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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MMDeploy" Version="1.0.0" />
|
||||
<PackageReference Include="OpenCvSharp4" Version="4.5.5.20211231" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.5.5.20211231" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -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<TextRecognizerOutput> 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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MMDeploy" Version="1.0.0" />
|
||||
<PackageReference Include="OpenCvSharp4" Version="4.5.5.20211231" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.5.5.20211231" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -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<PoseDetectorOutput> 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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MMDeploy" Version="1.0.0" />
|
||||
<PackageReference Include="OpenCvSharp4" Version="4.5.5.20211231" />
|
||||
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.5.5.20211231" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
Loading…
Reference in New Issue