Commit 546b4279 authored by limm's avatar limm
Browse files

add csrc and mmdeploy module

parent 502f4fb9
Pipeline #2810 canceled with stages
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());
}
}
/// <summary>
/// Gets internal handle.
/// </summary>
/// <param name="obj">instance.</param>
public static implicit operator IntPtr(DisposableObject obj) => obj._handle;
}
}
namespace MMDeploy
{
/// <summary>
/// model.
/// </summary>
public class Model : DisposableObject
{
/// <summary>
/// Initializes a new instance of the <see cref="Model"/> class.
/// </summary>
/// <param name="modelPath">model path.</param>
public Model(string modelPath)
{
ThrowException(NativeMethods.mmdeploy_model_create_by_path(modelPath, out _handle));
}
/// <inheritdoc/>
protected override void ReleaseHandle()
{
NativeMethods.mmdeploy_model_destroy(_handle);
}
}
}
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);
}
}
}
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace MMDeploy
{
#pragma warning disable 0649
internal unsafe struct CPoseTrack
{
public Pointf* Keypoints;
public int KeypointCount;
public float* Scores;
public Rect Bbox;
public int TargetId;
}
#pragma warning restore 0649
/// <summary>
/// Single tracking result of a bbox.
/// A picture may contains multiple reuslts.
/// </summary>
public struct PoseTrack
{
/// <summary>
/// Keypoints.
/// </summary>
public List<Pointf> Keypoints;
/// <summary>
/// Scores.
/// </summary>
public List<float> Scores;
/// <summary>
/// Bbox.
/// </summary>
public Rect Bbox;
/// <summary>
/// TargetId.
/// </summary>
public int TargetId;
/// <summary>
/// Init data.
/// </summary>
private void Init()
{
if (Keypoints == null || Scores == null)
{
Keypoints = new List<Pointf>();
Scores = new List<float>();
}
}
internal unsafe void Add(CPoseTrack* result)
{
Init();
for (int i = 0; i < result->KeypointCount; i++)
{
Keypoints.Add(new Pointf(result->Keypoints[i].X, result->Keypoints[i].Y));
Scores.Add(result->Scores[i]);
}
Bbox = result->Bbox;
TargetId = result->TargetId;
}
}
/// <summary>
/// Output of PoseTracker.
/// </summary>
public struct PoseTrackerOutput
{
/// <summary>
/// Tracking results for single image.
/// </summary>
public List<PoseTrack> 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(PoseTrack boxRes)
{
if (Results == null)
{
Results = new List<PoseTrack>();
}
Results.Add(boxRes);
}
}
/// <summary>
/// PoseTracker.
/// </summary>
public class PoseTracker : DisposableObject
{
/// <summary>
/// Params.
/// </summary>
public struct Params
{
/// <summary>
/// init with default value.
/// </summary>
public void Init()
{
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Params)));
NativeMethods.mmdeploy_pose_tracker_default_params(ptr);
this = Marshal.PtrToStructure<Params>(ptr);
Marshal.DestroyStructure<Params>(ptr);
Marshal.FreeHGlobal(ptr);
}
/// <summary>
/// Sets keypoint sigmas.
/// </summary>
/// <param name="array">keypoint sigmas.</param>
public void SetKeypointSigmas(float[] array)
{
this.KeypointSigmasSize = array.Length;
this.KeypointSigmas = Marshal.AllocHGlobal(sizeof(float) * array.Length);
Marshal.Copy(array, 0, this.KeypointSigmas, array.Length);
}
/// <summary>
/// Release ptr.
/// </summary>
public void DeleteKeypointSigmas()
{
if (this.KeypointSigmas != null)
{
Marshal.FreeHGlobal(this.KeypointSigmas);
this.KeypointSigmasSize = 0;
}
}
/// <summary>
/// detection interval, default = 1.
/// </summary>
public int DetInterval;
/// <summary>
/// detection label use for pose estimation, default = 0.
/// </summary>
public int DetLabel;
/// <summary>
/// detection score threshold, default = 0.5.
/// </summary>
public float DetThr;
/// <summary>
/// detection minimum bbox size (compute as sqrt(area)), default = -1.
/// </summary>
public float DetMinBboxSize;
/// <summary>
/// nms iou threshold for merging detected bboxes and bboxes from tracked targets, default = 0.7.
/// </summary>
public float DetNmsThr;
/// <summary>
/// max number of bboxes used for pose estimation per frame, default = -1.
/// </summary>
public int PoseMaxNumBboxes;
/// <summary>
/// threshold for visible key-points, default = 0.5.
/// </summary>
public float PoseKptThr;
/// <summary>
/// min number of key-points for valid poses, default = -1.
/// </summary>
public int PoseMinKeypoints;
/// <summary>
/// scale for expanding key-points to bbox, default = 1.25.
/// </summary>
public float PoseBboxScale;
/// <summary>
/// min pose bbox size, tracks with bbox size smaller than the threshold will be dropped,default = -1.
/// </summary>
public float PoseMinBboxSize;
/// <summary>
/// nms oks/iou threshold for suppressing overlapped poses, useful when multiple pose estimations
/// collapse to the same target, default = 0.5.
/// </summary>
public float PoseNmsThr;
/// <summary>
/// keypoint sigmas for computing OKS, will use IOU if not set, default = nullptr.
/// </summary>
public IntPtr KeypointSigmas;
/// <summary>
/// size of keypoint sigma array, must be consistent with the number of key-points, default = 0.
/// </summary>
public int KeypointSigmasSize;
/// <summary>
/// iou threshold for associating missing tracks, default = 0.4.
/// </summary>
public float TrackIouThr;
/// <summary>
/// max number of missing frames before a missing tracks is removed, default = 10.
/// </summary>
public int TrackMaxMissing;
/// <summary>
/// track history size, default = 1.
/// </summary>
public int TrackHistorySize;
/// <summary>
/// weight of position for setting covariance matrices of kalman filters, default = 0.05.
/// </summary>
public float StdWeightPosition;
/// <summary>
/// weight of velocity for setting covariance matrices of kalman filters, default = 0.00625.
/// </summary>
public float StdWeightVelocity;
/// <summary>
/// params for the one-euro filter for smoothing the outputs - (beta, fc_min, fc_derivative)
/// default = (0.007, 1, 1).
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public float[] SmoothParams;
}
/// <summary>
/// tracking state.
/// </summary>
public class State : DisposableObject
{
/// <summary>
/// Initializes a new instance of the <see cref="State"/> class.
/// </summary>
/// <param name="pipeline">pipeline.</param>
/// <param name="param">param.</param>
public State(IntPtr pipeline, Params param)
{
ThrowException(NativeMethods.mmdeploy_pose_tracker_create_state(pipeline, param, out _handle));
}
/// <inheritdoc/>
protected override void ReleaseHandle()
{
NativeMethods.mmdeploy_pose_tracker_destroy_state(_handle);
}
}
/// <summary>
/// Initializes a new instance of the <see cref="PoseTracker"/> class.
/// </summary>
/// <param name="detect">detect model.</param>
/// <param name="pose">pose model.</param>
/// <param name="context">context.</param>
public PoseTracker(Model detect, Model pose, Context context)
{
ThrowException(NativeMethods.mmdeploy_pose_tracker_create(detect, pose, context, out _handle));
}
/// <summary>
/// Get track information of image.
/// </summary>
/// <param name="state">state for video.</param>
/// <param name="mat">input mat.</param>
/// <param name="detect">control the use of detector.
/// -1: use params.DetInterval, 0: don't use detector, 1: force use detector.</param>
/// <returns>results of this frame.</returns>
public PoseTrackerOutput Apply(State state, Mat mat, int detect = -1)
{
PoseTrackerOutput output = default;
IntPtr[] states = new IntPtr[1] { state };
Mat[] mats = new Mat[1] { mat };
int[] detects = new int[1] { -1 };
unsafe
{
CPoseTrack* results = null;
int* resultCount = null;
fixed (Mat* _mats = mats)
fixed (IntPtr* _states = states)
fixed (int* _detects = detects)
{
ThrowException(NativeMethods.mmdeploy_pose_tracker_apply(_handle, _states, _mats, _detects,
mats.Length, &results, &resultCount));
FormatResult(resultCount, results, ref output, out var total);
ReleaseResult(results, resultCount, mats.Length);
}
}
return output;
}
private unsafe void FormatResult(int* resultCount, CPoseTrack* results, ref PoseTrackerOutput output, out int total)
{
total = resultCount[0];
for (int i = 0; i < total; i++)
{
PoseTrack outi = default;
outi.Add(results);
output.Add(outi);
results++;
}
}
private unsafe void ReleaseResult(CPoseTrack* results, int* resultCount, int count)
{
NativeMethods.mmdeploy_pose_tracker_release_result(results, resultCount, count);
}
/// <summary>
/// Create internal state.
/// </summary>
/// <param name="param">instance of Params.</param>
/// <returns>instance of State.</returns>
public State CreateState(Params param)
{
State state = new State(_handle, param);
return state;
}
/// <inheritdoc/>
protected override void ReleaseHandle()
{
// _state.Dispose();
NativeMethods.mmdeploy_pose_tracker_destroy(_handle);
}
}
}
namespace MMDeploy
{
/// <summary>
/// Profiler.
/// </summary>
public class Profiler : DisposableObject
{
/// <summary>
/// Initializes a new instance of the <see cref="Profiler"/> class.
/// </summary>
/// <param name="path">path.</param>
public Profiler(string path)
{
ThrowException(NativeMethods.mmdeploy_profiler_create(path, out _handle));
}
/// <inheritdoc/>
protected override void ReleaseHandle()
{
NativeMethods.mmdeploy_profiler_destroy(_handle);
}
}
}
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);
}
}
}
using System;
using System.Collections.Generic;
namespace MMDeploy
{
/// <summary>
/// Single detection result of a picture.
/// A picture may contains multiple reuslts.
/// </summary>
public struct RDetect
{
/// <summary>
/// Label id.
/// </summary>
public int LabelId;
/// <summary>
/// Score.
/// </summary>
public float Score;
/// <summary>
/// Center x.
/// </summary>
public float Cx;
/// <summary>
/// Center y.
/// </summary>
public float Cy;
/// <summary>
/// Width.
/// </summary>
public float Width;
/// <summary>
/// Height.
/// </summary>
public float Height;
/// <summary>
/// Angle.
/// </summary>
public float Angle;
internal unsafe RDetect(RDetect* result) : this()
{
this = *result;
}
}
/// <summary>
/// Output of RotatedDetector.
/// </summary>
public struct RotatedDetectorOutput
{
/// <summary>
/// Rotated detection results for single image.
/// </summary>
public List<RDetect> Results;
private void Init()
{
if (Results == null)
{
Results = new List<RDetect>();
}
}
internal unsafe void Add(RDetect* result)
{
Init();
Results.Add(new RDetect(result));
}
/// <summary>
/// Gets number of output.
/// </summary>
public int Count
{
get { return (Results == null) ? 0 : Results.Count; }
}
}
/// <summary>
/// RotatedDetector.
/// </summary>
public class RotatedDetector : DisposableObject
{
/// <summary>
/// Initializes a new instance of the <see cref="RotatedDetector"/> class.
/// </summary>
/// <param name="modelPath">model path.</param>
/// <param name="deviceName">device name.</param>
/// <param name="deviceId">device id.</param>
public RotatedDetector(string modelPath, string deviceName, int deviceId)
{
ThrowException(NativeMethods.mmdeploy_rotated_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<RotatedDetectorOutput> Apply(Mat[] mats)
{
List<RotatedDetectorOutput> output = new List<RotatedDetectorOutput>();
unsafe
{
RDetect* results = null;
int* resultCount = null;
fixed (Mat* _mats = mats)
{
ThrowException(NativeMethods.mmdeploy_rotated_detector_apply(_handle,
_mats, mats.Length, &results, &resultCount));
}
FormatResult(mats.Length, resultCount, results, ref output, out var total);
ReleaseResult(results, resultCount);
}
return output;
}
private unsafe void FormatResult(int matCount, int* resultCount, RDetect* results,
ref List<RotatedDetectorOutput> output, out int total)
{
total = matCount;
for (int i = 0; i < matCount; i++)
{
RotatedDetectorOutput outi = default;
for (int j = 0; j < resultCount[i]; j++)
{
outi.Add(results);
results++;
}
output.Add(outi);
}
}
private unsafe void ReleaseResult(RDetect* results, int* resultCount)
{
NativeMethods.mmdeploy_rotated_detector_release_result(results, resultCount);
}
/// <inheritdoc/>
protected override void ReleaseHandle()
{
NativeMethods.mmdeploy_rotated_detector_destroy(_handle);
}
}
}
using System;
namespace MMDeploy
{
/// <summary>
/// Scheduler.
/// </summary>
public class Scheduler : DisposableObject
{
private Scheduler()
{
}
/// <summary>
/// Create thread pool scheduler.
/// </summary>
/// <param name="num_threads">thread number.</param>
/// <returns>scheduler.</returns>
public static Scheduler ThreadPool(int num_threads)
{
Scheduler result = new Scheduler();
unsafe
{
result._handle = (IntPtr)NativeMethods.mmdeploy_executor_create_thread_pool(num_threads);
}
return result;
}
/// <summary>
/// Create single thread scheduler.
/// </summary>
/// <returns>scheduler.</returns>
public static Scheduler Thread()
{
Scheduler result = new Scheduler();
unsafe
{
result._handle = (IntPtr)NativeMethods.mmdeploy_executor_create_thread();
}
return result;
}
/// <inheritdoc/>
protected override void ReleaseHandle()
{
NativeMethods.mmdeploy_scheduler_destroy(_handle);
}
}
}
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;
public float* Score;
}
#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, mask[i * width + j] indicates the label id of pixel at (i, j).
/// </summary>
public int[] Mask;
/// <summary>
/// Score data, score[height * width * k + i * width + j] indicates the score
/// of class k at pixel (i, j).
/// </summary>
public float[] Score;
/// <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>
/// <param name="score">score.</param>
public SegmentorOutput(int height, int width, int classes, int[] mask, float[] score)
{
Height = height;
Width = width;
Classes = classes;
if (mask.Length > 0)
{
Mask = new int[Height * Width];
Array.Copy(mask, this.Mask, mask.Length);
}
else
{
Mask = new int[] { };
}
if (score.Length > 0)
{
Score = new float[Height * Width * Classes];
Array.Copy(score, this.Score, score.Length);
}
else
{
Score = new float[] { };
}
}
internal unsafe SegmentorOutput(CSegment* result)
{
Height = result->Height;
Width = result->Width;
Classes = result->Classes;
if (result->Mask != null)
{
Mask = new int[Height * Width];
int nbytes = Height * Width * sizeof(int);
fixed (int* data = this.Mask)
{
Buffer.MemoryCopy(result->Mask, data, nbytes, nbytes);
}
}
else
{
Mask = new int[] { };
}
if (result->Score != null)
{
Score = new float[Height * Width * Classes];
int nbytes = Height * Width * Classes * sizeof(float);
fixed (float* data = this.Score)
{
Buffer.MemoryCopy(result->Score, data, nbytes, nbytes);
}
}
else
{
Score = new float[] { };
}
}
}
/// <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);
}
}
}
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 TextDetector.
/// </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 = matCount;
for (int i = 0; i < matCount; i++)
{
TextDetectorOutput outi = default;
for (int j = 0; j < resultCount[i]; j++)
{
outi.Add(results);
results++;
}
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);
}
}
}
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);
}
}
}
#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;
public void* Device;
}
/// <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;
}
}
/// <summary>
/// Context type.
/// </summary>
public enum ContextType
{
DEVICE = 0,
STREAM = 1,
MODEL = 2,
SCHEDULER = 3,
MAT = 4,
PROFILER = 5,
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp3.1;net48;</TargetFrameworks>
<LangVersion>9.0</LangVersion>
<Nullable>enable</Nullable>
<AssemblyName>MMDeployCSharp</AssemblyName>
<RootNamespace>MMDeploy</RootNamespace>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Deterministic>true</Deterministic>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Platforms>AnyCPU;x64</Platforms>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup>
<MMDeployNativeDlls>$(MSBuildThisFileDirectory)\..\..\..\..\..</MMDeployNativeDlls>
</PropertyGroup>
<ItemGroup>
<Content Include="$(MMDeployNativeDlls)\build\bin\Release\mmdeploy.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Pack>true</Pack>
<PackagePath>runtimes\win-x64\native\mmdeploy.dll</PackagePath>
</Content>
<Content Include="MMDeployCSharp.props">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Pack>true</Pack>
<PackagePath>build\net48\MMDeployCSharp.props</PackagePath>
</Content>
</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>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MMDeployNativeDlls>$(MSBuildThisFileDirectory)..\..\runtimes</MMDeployNativeDlls>
</PropertyGroup>
<ItemGroup Condition="$(TargetFrameworkVersion.StartsWith('v4')) Or $(TargetFramework.StartsWith('net4'))">
<Content Include="$(MMDeployNativeDlls)\win-x64\native\mmdeploy.dll">
<Link>mmdeploy.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
namespace MMDeploy
{
/// <summary>
/// Nativate C methods.
/// </summary>
internal static partial class NativeMethods
{
public const string DllExtern = "mmdeploy";
}
}
using System;
using System.Diagnostics.Contracts;
using System.Runtime.InteropServices;
namespace MMDeploy
{
/// <summary>
/// Nativate C methods.
/// </summary>
internal static partial class NativeMethods
{
#region common.h
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern int mmdeploy_context_create(out IntPtr handle);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern int mmdeploy_context_create_by_device(string deviceName, int deviceId,
out IntPtr handle);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void mmdeploy_context_destroy(IntPtr handle);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern int mmdeploy_context_add(IntPtr handle, int type, string name,
IntPtr obj);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern int mmdeploy_device_create(string device_name, int device_id,
out IntPtr device);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void mmdeploy_device_destroy(IntPtr device);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern int mmdeploy_profiler_create(string path, out IntPtr handle);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe void mmdeploy_profiler_destroy(IntPtr handle);
#endregion
#region scheduler.h
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe void* mmdeploy_executor_create_thread();
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe void* mmdeploy_executor_create_thread_pool(int num_threads);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void mmdeploy_scheduler_destroy(IntPtr handle);
#endregion
#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 pose_tracker.h
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern int mmdeploy_pose_tracker_create(IntPtr det_model, IntPtr pose_model,
IntPtr context, out IntPtr handle);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern int mmdeploy_pose_tracker_destroy(IntPtr handle);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern int mmdeploy_pose_tracker_default_params(IntPtr handle);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern int mmdeploy_pose_tracker_create_state(IntPtr pipeline,
PoseTracker.Params param, out IntPtr state);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void mmdeploy_pose_tracker_destroy_state(IntPtr state);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe int mmdeploy_pose_tracker_apply(IntPtr handle, IntPtr* state,
Mat* mats, int* useDet, int count, CPoseTrack** results, int** resultCount);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe void mmdeploy_pose_tracker_release_result(CPoseTrack* results,
int* resultCount, int count);
#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 rotated_detector.h
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern int mmdeploy_rotated_detector_create(IntPtr model,
string deviceName, int deviceId, out IntPtr handle);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern int mmdeploy_rotated_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_rotated_detector_apply(IntPtr handle, Mat* mats,
int matCount, RDetect** results, int** resultCount);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe void mmdeploy_rotated_detector_release_result(RDetect* results,
int* resultCount);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void mmdeploy_rotated_detector_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
}
}
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")]
# 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_SDK_CSHARP_API option to ON. We recommend setting `MMDEPLOY_SHARED_LIBS` to OFF and use the static third party libraries(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 mmdeploy.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\MMDeployCSharp.1.3.1.nupkg`.
```shell
dotnet build --configuration Release -p:Version=1.3.1
```
(*option 2*) Open MMDeploy.sln && Build.
You can set the package-version through `Properties -> Package Version`. The default version is 1.3.1 if you don't set it.
If you encounter missing dependencies, follow the instructions for MSVC.
# Copyright (c) OpenMMLab. All rights reserved.
cmake_minimum_required(VERSION 3.14)
project(mmdeploy_cxx_api)
add_library(${PROJECT_NAME} INTERFACE)
target_include_directories(${PROJECT_NAME} INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>)
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_17)
set(_tasks ${MMDEPLOY_TASKS} pipeline)
foreach (task ${_tasks})
target_link_libraries(mmdeploy_${task} INTERFACE ${PROJECT_NAME})
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/mmdeploy/${task}.hpp
DESTINATION include/mmdeploy)
endforeach ()
if (TARGET mmdeploy)
target_include_directories(${PROJECT_NAME} INTERFACE
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/csrc>
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/third_party/outcome>
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/third_party/json>
)
target_include_directories(${PROJECT_NAME} INTERFACE
$<INSTALL_INTERFACE:include>
$<INSTALL_INTERFACE:include/mmdeploy/third_party/outcome>
$<INSTALL_INTERFACE:include/mmdeploy/third_party/json>
)
if (NOT MMDEPLOY_SPDLOG_EXTERNAL)
target_include_directories(${PROJECT_NAME} INTERFACE
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/third_party/spdlog/include>
$<INSTALL_INTERFACE:include/mmdeploy/third_party>)
endif ()
target_link_libraries(mmdeploy INTERFACE ${PROJECT_NAME})
else ()
target_link_libraries(${PROJECT_NAME} INTERFACE mmdeploy::core)
endif ()
mmdeploy_export_impl(${PROJECT_NAME})
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/mmdeploy/common.hpp
DESTINATION include/mmdeploy)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/demo/csrc/ DESTINATION example/cpp
FILES_MATCHING
PATTERN "*.cxx"
PATTERN "*.h"
)
// Copyright (c) OpenMMLab. All rights reserved.
#ifndef MMDEPLOY_CSRC_MMDEPLOY_APIS_CXX_CLASSIFIER_HPP_
#define MMDEPLOY_CSRC_MMDEPLOY_APIS_CXX_CLASSIFIER_HPP_
#include "mmdeploy/classifier.h"
#include "mmdeploy/common.hpp"
namespace mmdeploy {
namespace cxx {
using Classification = mmdeploy_classification_t;
class Classifier : public NonMovable {
public:
Classifier(const Model& model, const Context& context) {
auto ec = mmdeploy_classifier_create_v2(model, context, &classifier_);
if (ec != MMDEPLOY_SUCCESS) {
throw_exception(static_cast<ErrorCode>(ec));
}
}
~Classifier() {
if (classifier_) {
mmdeploy_classifier_destroy(classifier_);
classifier_ = {};
}
}
using Result = Result_<Classification>;
std::vector<Result> Apply(Span<const Mat> images) {
if (images.empty()) {
return {};
}
Classification* results{};
int* result_count{};
auto ec = mmdeploy_classifier_apply(classifier_, reinterpret(images.data()),
static_cast<int>(images.size()), &results, &result_count);
if (ec != MMDEPLOY_SUCCESS) {
throw_exception(static_cast<ErrorCode>(ec));
}
std::vector<Result> rets;
rets.reserve(images.size());
std::shared_ptr<Classification> data(results, [result_count, count = images.size()](auto p) {
mmdeploy_classifier_release_result(p, result_count, count);
});
size_t offset = 0;
for (size_t i = 0; i < images.size(); ++i) {
offset += rets.emplace_back(offset, result_count[i], data).size();
}
return rets;
}
Result Apply(const Mat& img) { return Apply(Span{img})[0]; }
private:
mmdeploy_classifier_t classifier_{};
};
} // namespace cxx
using cxx::Classification;
using cxx::Classifier;
} // namespace mmdeploy
#endif // MMDEPLOY_CSRC_MMDEPLOY_APIS_CXX_CLASSIFIER_HPP_
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment