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);
}
}
}