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 /// /// Single result of a picture. /// A picture may contains multiple reuslts. /// public struct TextRecognize { /// /// Texts. /// public byte[] Text; /// /// Scores. /// 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); } } } /// /// Output of TextRecognizer. /// public struct TextRecognizerOutput { /// /// Text recognization results for single image. /// public List Results; private void Init() { if (Results == null) { Results = new List(); } } internal unsafe void Add(CTextRecognize* result) { Init(); Results.Add(new TextRecognize(result)); } } /// /// TextRecognizer. /// public class TextRecognizer : DisposableObject { /// /// Initializes a new instance of the class. /// /// model path. /// device name. /// device id. public TextRecognizer(string modelPath, string deviceName, int deviceId) { ThrowException(NativeMethods.mmdeploy_text_recognizer_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 { 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; } /// /// Get information of each image in a batch. /// /// input mats. /// detection for each image. /// Results of each input mat. public List Apply(Mat[] mats, List vdetects) { List output = new List(); 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 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); } /// protected override void ReleaseHandle() { NativeMethods.mmdeploy_text_recognizer_destroy(_handle); } } }