//#define USE_MULTI_THREAD
using OpenCvSharp;
using OpenCvSharp.Extensions;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using Newtonsoft.Json;
using System.Xml;
using DH.Commons.Base;
namespace DH.Devices.Vision
{
///
/// 实例分割 maskrcnn
///
public class SimboObjectDetection : SimboVisionMLBase
{
public override bool Load(MLInit mLInit)
{
bool res = false;
try
{
Model = MLEngine.InitModel(mLInit.ModelFile,
mLInit.InferenceDevice,
mLInit.InputNodeName,
1, 3,
mLInit.InferenceWidth,
mLInit.InferenceHeight,5);
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 override 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;
for (int ix = 0; ix < iNum; ix++)
{
var det = detResult.SegmentResult[ix];
var rect = det.rect;
DetectionResultDetail detectionResultDetail = new DetectionResultDetail();
detectionResultDetail.LabelNo = det.classId;
//todo: 标签名相对应
detectionResultDetail.LabelDisplay = det.classname;
detectionResultDetail.Rect = new Rectangle(rect[0], rect[1], rect[2], rect[3]);
detectionResultDetail.Score = det.fScore;
detectionResultDetail.LabelName = det.classname;
detectionResultDetail.Area = det.area;
detectionResultDetail.InferenceResult = ResultState.DetectNG;
result.ResultDetails.Add(detectionResultDetail);
}
}
[HandleProcessCorruptedStateExceptions]
public MLResult RunInferenceFixed(MLRequest req)
{
MLResult mlResult = new MLResult();
Mat originMat=new Mat() ;
Mat detectMat= new Mat();
try
{
if (req.mImage == null)
{
mlResult.IsSuccess = false;
mlResult.ResultMessage = "异常:mat为null,无法执行推理!";
return mlResult;
}
// resize
detectMat = req.mImage.Clone();//1ms
int iWidth = detectMat.Cols;
int iHeight = detectMat.Rows;
// 如果是单通道图像,转换为三通道 RGB 格式
if (detectMat.Channels() == 1)
{
// 将灰度图像转换为RGB格式(三通道)
Cv2.CvtColor( detectMat,originMat, ColorConversionCodes.GRAY2BGR);
}
else if (detectMat.Channels() == 3)
{
// 如果已经是三通道(BGR),则直接转换为RGB
// Cv2.CvtColor( detectMat,originMat, ColorConversionCodes.BGR2RGB);
// 直接使用原始图像
originMat = detectMat.Clone();
}
//输入数据转化为字节
var inputByte = new byte[originMat.Total() * 3];//这里必须乘以通道数,不然数组越界,也可以用w*h*c,差不多
Marshal.Copy(originMat.Data, inputByte, 0, inputByte.Length);
byte[] labellist = new byte[40960]; //新建字节数组:label1_str label2_str
byte[] outputByte = new byte[originMat.Total() * 3];
Stopwatch sw = new Stopwatch();
sw.Start();
unsafe
{
mlResult.IsSuccess = MLEngine.det_ModelPredict(Model,
inputByte,
iWidth, iHeight, 3,
req.out_node_name,
req.in_lable_path,
req.confThreshold, req.iouThreshold,
ref outputByte[0],
ref labellist[0]);
// mlResult.IsSuccess = true;
}
sw.Stop();
if (mlResult.IsSuccess)
{
mlResult.ResultMessage = $"深度学习推理成功,耗时:{sw.ElapsedMilliseconds} ms";
//将字节数组转换为字符串
mlResult.ResultMap = originMat.ToBitmap();//4ms
string strGet = System.Text.Encoding.Default.GetString(labellist, 0, labellist.Length);
Console.WriteLine("strGet:", strGet);
ConvertJsonResult(strGet, ref mlResult);
// 解析json字符串
return mlResult;
}
else
{
mlResult.ResultMessage = $"异常:深度学习执行推理失败!";
return mlResult;
}
}
catch (Exception ex)
{
mlResult.ResultMessage = $"深度学习执行推理异常";
return mlResult;
}
finally
{
// 释放 Mat 资源
if (detectMat != null)
{
detectMat = null;
}
if (originMat != null)
{
originMat.Dispose();
originMat = null;
}
// GC.Collect();
}
#pragma warning restore CS0168 // 声明了变量,但从未使用过
}
}
}