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