DHDHSoftware/DH.Devices.Vision/SimboDetection.cs
2025-03-18 14:20:11 +08:00

256 lines
9.0 KiB
C#
Raw 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 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.Security.Cryptography.Xml;
using System.Runtime.InteropServices;
using Newtonsoft.Json;
using DH.Commons.Enums;
namespace DH.Devices.Vision
{
/// <summary>
/// 目标检测 GPU
/// </summary>
public class SimboDetection : SimboVisionMLBase
{
public override bool Load(MLInit mLInit)
{
bool res = false;
try
{
Model = MLGPUEngine.InitModel(mLInit.ModelFile, 1, mLInit.Score_thre, mLInit.GPUId, 3, 8);
//Model = MLEngine.InitModel(mLInit.ModelFile, 1, 0.45f, 0, 3);
res = true;
#if USE_MULTI_THREAD
IsCreated = true;
if (IsCreated)
{
_runHandleBefore ??= new AutoResetEvent(false);
_runHandleAfter ??= new ManualResetEvent(false);
_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);
#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型
HYoloResult detResult = JsonConvert.DeserializeObject<HYoloResult>(json);
#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型
if (detResult == null)
{
return;
}
int iNum = detResult.HYolo.Count;
#pragma warning disable CS0219 // 变量已被赋值,但从未使用过它的值
int IokNum = 0;
#pragma warning restore CS0219 // 变量已被赋值,但从未使用过它的值
for (int ix = 0; ix < iNum; ix++)
{
var det = detResult.HYolo[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 = rect[2] * rect[3];
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();
#pragma warning disable CS0168 // 声明了变量,但从未使用过
try
{
if (req.mImage == null)
{
mlResult.IsSuccess = false;
mlResult.ResultMessage = "异常mat为null无法执行推理";
return mlResult;
}
// resize
detectMat = req.mImage;//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);
}
//输入数据转化为字节
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();
//mlResult.IsSuccess = true;
unsafe
{
//mlResult.IsSuccess = MLGPUEngine.Inference(Model, inputByte, iWidth, iHeight, 3, req.in_lable_path, ref outputByte[0], ref labellist[0]);
mlResult.IsSuccess = MLGPUEngine.Inference2(Model, inputByte, iWidth, iHeight, 3, req.in_lable_path, ref labellist[0]);
}
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);
if (strGet == null)
{
mlResult.ResultMessage = $"异常:深度学习执行推理失败!";
return mlResult;
}
ConvertJsonResult(strGet, ref mlResult);
return mlResult;
}
else
{
mlResult.ResultMessage = $"异常:深度学习执行推理失败!";
return mlResult;
}
}
catch (Exception ex)
{
mlResult.ResultMessage = $"深度学习执行推理异常";
return mlResult;
}
finally
{
originMat?.Dispose();
#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型
originMat = null;
#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型
//maskMat?.Dispose();
// maskMat = null;
detectMat?.Dispose();
#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型
detectMat = null;
#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型
// maskWeighted?.Dispose();
// maskWeighted = null;
// GC.Collect();
}
#pragma warning restore CS0168 // 声明了变量,但从未使用过
}
}
}