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 SegmentResult; public class Result { public double fScore; public int classId; public string classname; public double area; public List> 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(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 points = new List(); List maxYs = new List(); //把字体打印在矩形框的下面,考虑矩形框最靠下的角点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(rectX.ToInt(), rectY.ToInt(), rectWidth.ToInt(), rectHeight.ToInt()); 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); } } }