286 lines
8.7 KiB
C#
286 lines
8.7 KiB
C#
//#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);
|
||
}
|
||
|
||
|
||
}
|
||
}
|