using System.Collections.Generic; using System.Linq; namespace MMDeploy { #pragma warning disable 0649 internal unsafe struct CPoseDetect { public Pointf* Point; public float* Score; public int Length; } #pragma warning restore 0649 /// /// Single detection result of a bbox. /// A picture may contains multiple reuslts. /// public struct PoseDetect { /// /// Keypoins. /// public List Points; /// /// Scores. /// public List Scores; /// /// Init points and scores if empty. /// private void Init() { if (Points == null || Scores == null) { Points = new List(); Scores = new List(); } } /// /// Add single keypoint to list. /// /// Keypoint. /// Score. public void Add(Pointf point, float score) { Init(); Points.Add(point); Scores.Add(score); } internal unsafe void Add(Pointf* point, float score) { Init(); Points.Add(new Pointf(point->X, point->Y)); } } /// /// Output of PoseDetector. /// public struct PoseDetectorOutput { /// /// Pose detection results for single image. /// public List Results; /// /// Gets number of output. /// public int Count { get { return (Results == null) ? 0 : Results.Count; } } /// /// Result for box level. /// /// Box res. public void Add(PoseDetect boxRes) { if (Results == null) { Results = new List(); } Results.Add(boxRes); } } /// /// PoseDetector. /// public class PoseDetector : DisposableObject { /// /// Initializes a new instance of the class. /// /// model path. /// device name. /// device id. public PoseDetector(string modelPath, string deviceName, int deviceId) { ThrowException(NativeMethods.mmdeploy_pose_detector_create_by_path(modelPath, deviceName, deviceId, out _handle)); } /// /// Get information of each image in a batch. /// /// input mats. /// bounding boxes.. /// bounding boxes count for each image. /// Results of each input mat. public List Apply(Mat[] mats, Rect[] bboxes, int[] bboxCount) { List output = new List(); unsafe { CPoseDetect* results = null; fixed (Mat* _mats = mats) fixed (Rect* _bboxes = bboxes) fixed (int* _bboxCount = bboxCount) { ThrowException(NativeMethods.mmdeploy_pose_detector_apply_bbox(_handle, _mats, mats.Length, _bboxes, _bboxCount, &results)); FormatResult(mats.Length, _bboxCount, results, ref output, out var total); ReleaseResult(results, total); } } return output; } /// /// Get information of each image in a batch. /// /// Input mats. /// Results of each input mat. public List Apply(Mat[] mats) { List output = new List(); unsafe { CPoseDetect* results = null; fixed (Mat* _mats = mats) { ThrowException(NativeMethods.mmdeploy_pose_detector_apply(_handle, _mats, mats.Length, &results)); } int[] _bbox_count = Enumerable.Repeat(1, mats.Length).ToArray(); fixed (int* bbox_count = _bbox_count) { FormatResult(mats.Length, bbox_count, results, ref output, out var total); ReleaseResult(results, total); } } return output; } private unsafe void FormatResult(int matCount, int* bboxCount, CPoseDetect* results, ref List output, out int total) { total = 0; for (int i = 0; i < matCount; i++) { PoseDetectorOutput outi = default; for (int j = 0; j < bboxCount[i]; j++) { PoseDetect boxRes = default; for (int k = 0; k < results->Length; k++) { boxRes.Add(results->Point[k], results->Score[k]); } outi.Add(boxRes); results++; total++; } output.Add(outi); } } private unsafe void ReleaseResult(CPoseDetect* results, int count) { NativeMethods.mmdeploy_pose_detector_release_result(results, count); } /// protected override void ReleaseHandle() { NativeMethods.mmdeploy_pose_detector_destroy(_handle); } } }