2024-05-31 10:14:57 +08:00
|
|
|
|
|
|
|
|
|
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 SegResultCountry
|
|
|
|
|
{
|
|
|
|
|
public List<ResultCountry> SegmentResult;
|
|
|
|
|
public class ResultCountry
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
public double fScore;
|
|
|
|
|
public int classId;
|
|
|
|
|
public string classname;
|
|
|
|
|
|
|
|
|
|
public double area;
|
|
|
|
|
public List<List<int>> rect;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class PaddleOcrModelCountry
|
|
|
|
|
{
|
|
|
|
|
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]
|
2024-06-11 11:40:47 +08:00
|
|
|
|
public MLResult RunInference(MLRequest req)
|
2024-05-31 10:14:57 +08:00
|
|
|
|
{
|
|
|
|
|
#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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2024-06-11 11:40:47 +08:00
|
|
|
|
private void ConvertJsonResult(string json, ref MLResult result)
|
2024-05-31 10:14:57 +08:00
|
|
|
|
{
|
|
|
|
|
// 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);
|
|
|
|
|
SegResultCountry detResult = JsonConvert.DeserializeObject<SegResultCountry>(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;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DetectionResultDetail detectionResultDetail = new DetectionResultDetail();
|
|
|
|
|
detectionResultDetail.LabelNo = det.classId;
|
|
|
|
|
//todo: 标签名相对应
|
|
|
|
|
detectionResultDetail.LabelDisplay = det.classname;
|
|
|
|
|
detectionResultDetail.Rect = new Rectangle(rectX.ToInt(), rectY.ToInt(), rectWidth.ToInt(), rectHeight.ToInt());
|
|
|
|
|
detectionResultDetail.Score = det.fScore;
|
|
|
|
|
detectionResultDetail.LabelName = det.classname;
|
|
|
|
|
detectionResultDetail.Area = det.area;
|
|
|
|
|
result.ResultDetails.Add(detectionResultDetail);
|
|
|
|
|
//if (det.classname.Contains("Model:") || det.classname.Contains("Batch:"))
|
|
|
|
|
//{
|
|
|
|
|
// string[] sArray = Regex.Split(det.classname, "Model:", RegexOptions.IgnoreCase);
|
|
|
|
|
// string splitBar = "";
|
|
|
|
|
// if (sArray.Count() > 1)
|
|
|
|
|
// {
|
|
|
|
|
// result.WashMachineBar = sArray[1];
|
|
|
|
|
// string[] aBatch = Regex.Split(sArray[0], "Batch:", RegexOptions.IgnoreCase);
|
|
|
|
|
// if (aBatch.Count() > 1)
|
|
|
|
|
// {
|
|
|
|
|
// result.WashMachineBatch = aBatch[1];
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
//}
|
|
|
|
|
//if (det.classname.Contains("SN:") )
|
|
|
|
|
//{
|
|
|
|
|
// string[] sArray = Regex.Split(det.classname, "SN:", RegexOptions.IgnoreCase);
|
|
|
|
|
// string splitBar = "";
|
|
|
|
|
// if (sArray.Count() > 1)
|
|
|
|
|
// {
|
|
|
|
|
// result.WashMachineSN = sArray[1];
|
|
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
//}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[HandleProcessCorruptedStateExceptions]
|
2024-06-11 11:40:47 +08:00
|
|
|
|
public MLResult RunInferenceFixed(MLRequest req)
|
2024-05-31 10:14:57 +08:00
|
|
|
|
{
|
2024-06-11 11:40:47 +08:00
|
|
|
|
MLResult mlResult = new MLResult();
|
2024-05-31 10:14:57 +08:00
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void FreeModel()
|
|
|
|
|
{
|
|
|
|
|
OcrEngine.FreePredictor(Model);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|