hisence-yolo-detection/HisenceYoloDetection/PaddleOcrModel.cs
2024-06-27 09:22:31 +08:00

286 lines
8.7 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//#define USE_MULTI_THREAD
using Newtonsoft.Json;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using PaddleOCRSharp;
using STTech.BytesIO.Core;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static System.Net.Mime.MediaTypeNames;
using Point = OpenCvSharp.Point;
namespace XKRS.Device.SimboVision.SimboHelper
{
public class SegResult
{
public List<Result> SegmentResult;
public class Result
{
public double fScore;
public int classId;
public string classname;
public double area;
public List<List<int>> rect;
}
}
public class PaddleOcrModel
{
IntPtr Model;
public bool Load(string ModelFile,string Device)
{
bool res = false;
try
{
Model = OcrEngine.InitModel(ModelFile, Device);
res = true;
#if USE_MULTI_THREAD
IsCreated = true;
if (IsCreated)
{
if (_runHandleBefore == null)
{
_runHandleBefore = new AutoResetEvent(false);
}
if (_runHandleAfter == null)
{
_runHandleAfter = new ManualResetEvent(false);
}
if (_runTask == null)
{
_runTask = Task.Factory.StartNew(() =>
{
while (IsCreated)
{
_runHandleBefore.WaitOne();
if (IsCreated)
{
_result = RunInferenceFixed(_req);
_runHandleAfter.Set();
}
}
}, TaskCreationOptions.LongRunning);
}
}
#endif
}
catch (Exception ex)
{
throw ex;
}
return res;
}
#if USE_MULTI_THREAD
MLRequest _req = null;
MLResult _result = null;
public bool IsCreated { get; set; } = false;
Task _runTask = null;
AutoResetEvent _runHandleBefore = new AutoResetEvent(false);
ManualResetEvent _runHandleAfter = new ManualResetEvent(false);
object _runLock = new object();
#endif
[HandleProcessCorruptedStateExceptions]
public MLResult RunInference(MLRequest req)
{
#if USE_MULTI_THREAD
MLResult mlResult = null;
lock (_runLock)
{
_result = new MLResult();
_req = req;
_runHandleAfter.Reset();
_runHandleBefore.Set();
_runHandleAfter.WaitOne();
mlResult = _result;
}
return mlResult;
#else
return RunInferenceFixed(req);
#endif
}
private void ConvertJsonResult(string json, ref MLResult result)
{
// json = "{\"FastDetResult\":[{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654843,\"rect\":[175,99,110,594]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654589,\"rect\":[2608,19,104,661]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654285,\"rect\":[1275,19,104,662]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.620762,\"rect\":[1510,95,107,600]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.617812,\"rect\":[2844,93,106,602]}]}";
//
Console.WriteLine("检测结果JSON" + json);
SegResult detResult = JsonConvert.DeserializeObject<SegResult>(json);
if (detResult == null)
{
return;
}
int iNum = detResult.SegmentResult.Count;
int IokNum = 0;
for (int ix = 0; ix < iNum; ix++)
{
var det = detResult.SegmentResult[ix];
var rect = det.rect;
List<Point> points = new List<Point>();
List<float> maxYs = new List<float>();
//把字体打印在矩形框的下面考虑矩形框最靠下的角点Y值不能超过边框值 否则就往上写
for (int n = 0; n < det.rect.Count(); n++)
{
points.Add(new Point(det.rect[n][0], det.rect[n][1]));
maxYs.Add(det.rect[n][1]);
}
// 定义矩形左上角和右下角的坐标
Point topLeft = points[0];
Point bottomRight = points[2];
// 计算矩形的长和宽
int width = bottomRight.X - topLeft.X;//矩形宽度
int height = bottomRight.Y - topLeft.Y;//矩形高度
//下面定义一个矩形区域,以后在这个矩形里画上白底黑字
float rectX = points[0].X;
float rectY = points[0].Y;
float rectWidth = width;
float rectHeight = height;
if(det.classname!="")
{
DetectionResultDetail detectionResultDetail = new DetectionResultDetail();
detectionResultDetail.LabelNo = det.classId;
//todo: 标签名相对应
detectionResultDetail.LabelDisplay = det.classname;
detectionResultDetail.Rect = new Rectangle((int)rectX, (int)rectY, (int)rectWidth, (int)rectHeight); detectionResultDetail.Score = det.fScore;
detectionResultDetail.LabelName = det.classname;
detectionResultDetail.Area = det.area;
result.ResultDetails.Add(detectionResultDetail);
}
}
}
[HandleProcessCorruptedStateExceptions]
public MLResult RunInferenceFixed(MLRequest req)
{
MLResult mlResult = new MLResult();
Mat originMat = new Mat();
try
{
originMat = req.currentMat;//1ms
int iWidth = originMat.Cols;
int iHeight = originMat.Rows;
//输入数据转化为字节
var inputByte = new byte[originMat.Total() * 3];//这里必须乘以通道数不然数组越界也可以用w*h*c差不多
Marshal.Copy(originMat.Data, inputByte, 0, inputByte.Length);
byte[] labellist = new byte[20480]; //新建字节数组label1_str label2_str
byte[] outputByte = new byte[originMat.Total() * 3];
Stopwatch sw = new Stopwatch();
sw.Start();
unsafe
{
mlResult.IsSuccess = OcrEngine.Inference(Model, inputByte, iWidth, iHeight, 3, ref outputByte[0], ref labellist[0]);
}
sw.Stop();
if (mlResult.IsSuccess)
{
mlResult.ResultMessage = $"深度学习推理成功,耗时:{sw.ElapsedMilliseconds} ms";
Mat maskWeighted = new Mat(iHeight, iWidth, MatType.CV_8UC3, outputByte);
mlResult.ResultMap = BitmapConverter.ToBitmap(maskWeighted);//4ms
//将字节数组转换为字符串
//mlResult.ResultMap = originMat.ToBitmap();//4ms
string strGet = System.Text.Encoding.Default.GetString(labellist, 0, labellist.Length);
Console.WriteLine("strGet:", strGet);
ConvertJsonResult(strGet, ref mlResult);
maskWeighted?.Dispose();
maskWeighted = null;
//解析json字符串
return mlResult;
}
else
{
mlResult.ResultMessage = $"异常:深度学习执行推理失败!";
return mlResult;
}
}
catch (Exception ex)
{
mlResult.ResultMessage = $"深度学习执行推理异常:{ex.Message}";
return mlResult;
}
finally
{
// originMat?.Dispose();
// originMat = null;
// GC.Collect();
}
}
[HandleProcessCorruptedStateExceptions]
public void FreeModel()
{
OcrEngine.FreePredictor(Model);
}
}
}