using System; using System.Collections.Generic; namespace MMDeploy { #pragma warning disable 0649 /// /// mm_instance_mask_t of c code. /// internal unsafe struct CInstanceMask { public char* Data; public int Height; public int Width; } /// /// mm_detect_t of c code. /// internal unsafe struct CDetect { public int LabelId; public float Score; public Rect BBox; public CInstanceMask* Mask; } #pragma warning restore 0649 /// /// Instance mask. /// public struct InstanceMask { /// /// Height. /// public int Height; /// /// Width. /// public int Width; /// /// Raw data. /// public byte[] Data; internal unsafe InstanceMask(CInstanceMask* mask) { Height = mask->Height; Width = mask->Width; Data = new byte[Height * Width]; fixed (byte* data = this.Data) { Buffer.MemoryCopy(mask->Data, data, Height * Width, Height * Width); } } } /// /// Single detection result of a picture. /// A picture may contains multiple reuslts. /// public struct Detect { /// /// Label id. /// public int LabelId; /// /// Score. /// public float Score; /// /// Bounding box. /// public Rect BBox; /// /// Whether has mask. /// public bool HasMask; /// /// Mask. /// public InstanceMask Mask; /// /// Initializes a new instance of the struct. /// /// label id. /// score. /// bounding box. public Detect(int labelId, float score, Rect bbox) { LabelId = labelId; Score = score; BBox = bbox; HasMask = false; Mask = default; } internal unsafe Detect(CDetect* result) : this(result->LabelId, result->Score, result->BBox) { if (result->Mask != null) { HasMask = true; CInstanceMask* mask = result->Mask; Mask = new InstanceMask(mask); } } } /// /// Output of Detector. /// public struct DetectorOutput { /// /// Detection results for single image. /// public List Results; /// /// Init Reuslts. /// public void Init() { if (Results == null) { Results = new List(); } } /// /// Add result to single image. /// /// label id. /// score. /// bounding box. public void Add(int labelId, float score, Rect bbox) { Init(); Results.Add(new Detect(labelId, score, bbox)); } internal unsafe void Add(CDetect* result) { Init(); Results.Add(new Detect(result)); } /// /// Gets number of output. /// public int Count { get { return (Results == null) ? 0 : Results.Count; } } } /// /// Detector. /// public class Detector : DisposableObject { /// /// Initializes a new instance of the class. /// /// model path. /// device name. /// device id. public Detector(string modelPath, string deviceName, int deviceId) { ThrowException(NativeMethods.mmdeploy_detector_create_by_path(modelPath, deviceName, deviceId, out _handle)); } /// /// Get information of each image in a batch. /// /// input mats. /// Results of each input mat. public List Apply(Mat[] mats) { List output = new List(); unsafe { CDetect* results = null; int* resultCount = null; fixed (Mat* _mats = mats) { ThrowException(NativeMethods.mmdeploy_detector_apply(_handle, _mats, mats.Length, &results, &resultCount)); } FormatResult(mats.Length, resultCount, results, ref output, out var total); ReleaseResult(results, resultCount, total); } return output; } private unsafe void FormatResult(int matCount, int* resultCount, CDetect* results, ref List output, out int total) { total = 0; for (int i = 0; i < matCount; i++) { DetectorOutput outi = default; for (int j = 0; j < resultCount[i]; j++) { outi.Add(results); results++; total++; } output.Add(outi); } } private unsafe void ReleaseResult(CDetect* results, int* resultCount, int count) { NativeMethods.mmdeploy_detector_release_result(results, resultCount, count); } /// protected override void ReleaseHandle() { NativeMethods.mmdeploy_detector_destroy(_handle); } } }