first commit

This commit is contained in:
2025-03-07 09:06:46 +08:00
parent 4a54a0b9f5
commit f6f5517d40
121 changed files with 5388 additions and 0 deletions

View File

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<BaseOutputPath>..\</BaseOutputPath>
<AppendTargetFrameworkToOutputPath>output</AppendTargetFrameworkToOutputPath>
<UseWindowsForms>true</UseWindowsForms>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="OpenCvSharp4" Version="4.5.3.20210817" />
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.5.3.20210817" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,295 @@
//#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;
namespace DH.Devices.Vision
{
//public class SegResult
//{
// public List<Result> SegmentResult;
// public class Result
// {
// public double fScore;
// public int classId;
// public string classname;
// public double area;
// public List<int> rect;
// }
//}
/// <summary>
/// 实例分割 maskrcnn
/// </summary>
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<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;
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 tempMat;
try
{
if (req.mImage == null)
{
mlResult.IsSuccess = false;
mlResult.ResultMessage = "异常mat为null无法执行推理";
return mlResult;
}
// resize
tempMat = req.mImage;//1ms
int iWidth = tempMat.Cols;
int iHeight = tempMat.Rows;
// 如果是单通道图像,转换为三通道 RGB 格式
if (tempMat.Channels() == 1)
{
// 将灰度图像转换为RGB格式三通道
Cv2.CvtColor( tempMat,originMat, ColorConversionCodes.GRAY2BGR);
}
else if (tempMat.Channels() == 3)
{
// 如果已经是三通道BGR则直接转换为RGB
Cv2.CvtColor( tempMat,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();
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";
//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 = $"深度学习执行推理异常";
return mlResult;
}
finally
{
req.mImage?.Dispose();
req.mImage = null;
originMat = null;
// GC.Collect();
}
}
}
}

View File

@ -0,0 +1,191 @@

using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
namespace DH.Devices.Vision
{
public abstract class SimboVisionMLBase
{
public Mat ColorLut { get; set; }
public byte[] ColorMap { get; set; }
public MLModelType ModelType { get; set; }
public IntPtr Model { get; set; }
public abstract bool Load(MLInit mLInit);
public abstract MLResult RunInference(MLRequest req);
public void Dispose()
{
try
{
MLGPUEngine.FreePredictor(Model);
}
catch (Exception e) { }
// MLEngine.FreePredictor(Model);
}
public void Dispose2()
{
try
{
MLEngine.FreePredictor(Model);
}
catch (Exception e) { }
// MLEngine.FreePredictor(Model);
}
public SimboVisionMLBase()
{
// ColorMap = OpenCVHelper.GetColorMap(256);//使用3个通道
// ColorLut = new Mat(1, 256, MatType.CV_8UC3, ColorMap);
}
}
public class SegResult
{
public List<Result> SegmentResult;
public class Result
{
public double fScore;
public int classId;
public string classname;
public double area;
public List<int> rect;
}
}
public static class MLGPUEngine
{
// private const string sPath = @"D:\XHM\XHM\M018_NET7.0speed - 副本 - 副本\src\x64\Debug\HYolo.dll";
[DllImport("HYolo.dll", EntryPoint = "InitModel")]
//public static extern IntPtr InitModel(string model_path, int batch_size, float score_thre, int device_id, int number_of_warmup_runs);
public static extern IntPtr InitModel(string model_path, int batch_size, float score_thre, int device_id, int number_of_warmup_runs,int request_infer);
[DllImport("HYolo.dll", EntryPoint = "PreHot")]
public static extern bool PreHot(IntPtr model, byte[] img, int W, int H, int C);
[DllImport("HYolo.dll", EntryPoint = "Inference")]
public static extern bool Inference(IntPtr model, byte[] img, int W, int H, int C,
string labelText, ref byte Mask_output, ref byte label);
[DllImport("HYolo.dll", EntryPoint = "Inference2")]
public static extern bool Inference2(IntPtr model, byte[] img, int W, int H, int C,
string labelText, ref byte label);
[DllImport("HYolo.dll", EntryPoint = "FreePredictor")]
public static extern void FreePredictor(IntPtr model);
}
public static class MLEngine
{
//private const string sPath = @"D:\\C#\磁环项目\\OpenVinoYolo\\openvino_Yolov5_v7_v2.0\\openvino_Yolov5_v7\\Program\ConsoleProject\\x64\\Release\\QuickSegmentDynamic.dll";
[DllImport("QuickSegmentDynamic.dll", EntryPoint = "InitModel")]
public static extern IntPtr InitModel(string model_filename, string inferenceDevice, string input_node_name, int bacth, int inferenceChannels, int InferenceWidth, int InferenceHeight,int request_infer);
/// <summary>
/// 分割
/// </summary>
/// <param name="model"></param>
/// <param name="img"></param>
/// <param name="W"></param>
/// <param name="H"></param>
/// <param name="C"></param>
/// <param name="labelText"></param>
/// <param name="conf_threshold"></param>
/// <param name="IOU_THRESHOLD"></param>
/// <param name="fScoreThre"></param>
/// <param name="segmentWidth"></param>
/// <param name="Mask_output"></param>
/// <param name="label"></param>
/// <returns></returns>
[DllImport("QuickSegmentDynamic.dll", EntryPoint = "seg_ModelPredict")]
public static extern bool seg_ModelPredict(IntPtr model, byte[] img, int W, int H, int C,
string labelText, float conf_threshold, float IOU_THRESHOLD, float fScoreThre, int segmentWidth,
ref byte Mask_output, ref byte label);
/// <summary>
/// 目标检测
/// </summary>
/// <param name="model"></param>
/// <param name="img"></param>
/// <param name="W"></param>
/// <param name="H"></param>
/// <param name="C"></param>
/// <param name="nodes"></param>
/// <param name="labelText"></param>
/// <param name="conf_threshold"></param>
/// <param name="IOU_THRESHOLD"></param>
/// <param name="Mask_output"></param>
/// <param name="label"></param>
[DllImport("QuickSegmentDynamic.dll", EntryPoint = "det_ModelPredict")]
public static extern bool det_ModelPredict(IntPtr model, byte[] img, int W, int H, int C,
string nodes,// ++++++++++++++++++++++++++++++++++++
string labelText, float conf_threshold, float IOU_THRESHOLD,
ref byte Mask_output, ref byte label);
[DllImport("QuickSegmentDynamic.dll", EntryPoint = "FreePredictor")]
public static extern void FreePredictor(IntPtr model);
}
public static class MLEngine1
{
/**********************************************************************/
/***************** 1.推理DLL导入实现 ****************/
/**********************************************************************/
//private const string sPath = @"D:\M018_NET7.0\src\Debug\model_infer.dll";
// 加载推理相关方法
[DllImport("model_infer.dll", EntryPoint = "InitModel")] // 模型统一初始化方法: 需要yml、pdmodel、pdiparams
//[DllImport(sPath, EntryPoint = "InitModel")] // 模型统一初始化方法: 需要yml、pdmodel、pdiparams
public static extern IntPtr InitModel(string model_type, string model_filename, string params_filename, string cfg_file, bool use_gpu, int gpu_id, ref byte paddlex_model_type);
[DllImport("model_infer.dll", EntryPoint = "Det_ModelPredict")] // PaddleDetection模型推理方法
public static extern bool Det_ModelPredict(IntPtr model, byte[] img, int W, int H, int C, IntPtr output, int[] BoxesNum, ref byte label);
[DllImport("model_infer.dll", EntryPoint = "Seg_ModelPredict")] // PaddleSeg模型推理方法
public static extern bool Seg_ModelPredict(IntPtr model, byte[] img, int W, int H, int C, ref byte output);
[DllImport("model_infer.dll", EntryPoint = "Cls_ModelPredict")] // PaddleClas模型推理方法
public static extern bool Cls_ModelPredict(IntPtr model, byte[] img, int W, int H, int C, ref float score, ref byte category, ref int category_id);
[DllImport("model_infer.dll", EntryPoint = "Mask_ModelPredict")] // Paddlex的MaskRCNN模型推理方法
public static extern bool Mask_ModelPredict(IntPtr model, byte[] img, int W, int H, int C, IntPtr output, ref byte Mask_output, int[] BoxesNum, ref byte label);
//public static extern bool Mask_ModelPredict(IntPtr model, IntPtr img, int W, int H, int C, IntPtr output, ref byte Mask_output, int[] BoxesNum, ref byte label);
[DllImport("model_infer.dll", EntryPoint = "DestructModel")] // 分割、检测、识别模型销毁方法
public static extern void DestructModel(IntPtr model);
}
}

View File

@ -0,0 +1,299 @@
using OpenCvSharp;
using System.ComponentModel;
using System.Drawing;
using static OpenCvSharp.AgastFeatureDetector;
using System.Text.RegularExpressions;
using System.Text;
namespace DH.Devices.Vision
{
public enum MLModelType
{
[Description("图像分类")]
ImageClassification = 1,
[Description("目标检测")]
ObjectDetection = 2,
//[Description("图像分割")]
//ImageSegmentation = 3
[Description("语义分割")]
SemanticSegmentation = 3,
[Description("实例分割")]
InstanceSegmentation = 4,
[Description("目标检测GPU")]
ObjectGPUDetection = 5
}
public class MLRequest
{
public int ImageChannels = 3;
public Mat mImage;
public int ResizeWidth;
public int ResizeHeight;
public float confThreshold;
public float iouThreshold;
//public int ImageResizeCount;
public bool IsCLDetection;
public int ProCount;
public string in_node_name;
public string out_node_name;
public string in_lable_path;
public int ResizeImageSize;
public int segmentWidth;
public int ImageWidth;
// public List<labelStringBase> OkClassTxtList;
// public List<ModelLabel> LabelNames;
public float Score;
}
public enum ResultState
{
[Description("检测NG")]
DetectNG = -3,
//[Description("检测不足TBD")]
// ShortageTBD = -2,
[Description("检测结果TBD")]
ResultTBD = -1,
[Description("OK")]
OK = 1,
// [Description("NG")]
// NG = 2,
//统计结果
[Description("A类NG")]
A_NG = 25,
[Description("B类NG")]
B_NG = 26,
[Description("C类NG")]
C_NG = 27,
}
/// <summary>
/// 深度学习 识别结果明细 面向业务detect 面向深度学习Recongnition、Inference
/// </summary>
public class DetectionResultDetail
{
public string LabelBGR { get; set; }//识别到对象的标签BGR
public int LabelNo { get; set; } // 识别到对象的标签索引
public string LabelName { get; set; }//识别到对象的标签名称
public double Score { get; set; }//识别目标结果的可能性、得分
public string LabelDisplay { get; set; }//识别到对象的 显示信息
public double Area { get; set; }//识别目标的区域面积
public Rectangle Rect { get; set; }//识别目标的外接矩形
public RotatedRect MinRect { get; set; }//识别目标的最小外接矩形(带角度)
public ResultState InferenceResult { get; set; }//只是模型推理 label的结果
public double DistanceToImageCenter { get; set; } //计算矩形框到图像中心的距离
public ResultState FinalResult { get; set; }//模型推理+其他视觉、逻辑判断后 label结果
}
public class MLResult
{
public bool IsSuccess = false;
public string ResultMessage;
public Bitmap ResultMap;
public List<DetectionResultDetail> ResultDetails = new List<DetectionResultDetail>();
}
public class MLInit
{
public string ModelFile;
public string InferenceDevice;
public int InferenceWidth;
public int InferenceHeight;
public string InputNodeName;
public int SizeModel;
public bool bReverse;//尺寸测量正反面
//目标检测Gpu
public bool IsGPU;
public int GPUId;
public float Score_thre;
public MLInit(string modelFile, bool isGPU, int gpuId, float score_thre)
{
ModelFile = modelFile;
IsGPU = isGPU;
GPUId = gpuId;
Score_thre = score_thre;
}
public MLInit(string modelFile, string inputNodeName, string inferenceDevice, int inferenceWidth, int inferenceHeight)
{
ModelFile = modelFile;
InferenceDevice = inferenceDevice;
InferenceWidth = inferenceWidth;
InferenceHeight = inferenceHeight;
InputNodeName = inputNodeName;
}
}
public class DetectStationResult
{
public string Pid { get; set; }
public string TempPid { get; set; }
/// <summary>
/// 检测工位名称
/// </summary>
public string DetectName { get; set; }
/// <summary>
/// 深度学习 检测结果
/// </summary>
public List<DetectionResultDetail> DetectDetails = new List<DetectionResultDetail>();
/// <summary>
/// 工位检测结果
/// </summary>
public ResultState ResultState { get; set; } = ResultState.ResultTBD;
public double FinalResultfScore { get; set; } = 0.0;
public string ResultLabel { get; set; } = "";// 多个ng时根据label优先级设定当前检测项的label
public string ResultLabelCategoryId { get; set; } = "";// 多个ng时根据label优先级设定当前检测项的label
public int PreTreatState { get; set; }
public bool IsPreTreatDone { get; set; } = true;
public bool IsAfterTreatDone { get; set; } = true;
public bool IsMLDetectDone { get; set; } = true;
/// <summary>
/// 预处理阶段已经NG
/// </summary>
public bool IsPreTreatNG { get; set; } = false;
/// <summary>
/// 目标检测NG
/// </summary>
public bool IsObjectDetectNG { get; set; } = false;
public DateTime EndTime { get; set; }
public int StationDetectElapsed { get; set; }
public static string NormalizeAndClean(string input)
{
if (input == null) return null;
// Step 1: 标准化字符编码为 Form C (规范组合)
string normalizedString = input.Normalize(NormalizationForm.FormC);
// Step 2: 移除所有空白字符,包括制表符和换行符
string withoutWhitespace = Regex.Replace(normalizedString, @"\s+", "");
// Step 3: 移除控制字符 (Unicode 控制字符,范围 \u0000 - \u001F 和 \u007F)
string withoutControlChars = Regex.Replace(withoutWhitespace, @"[\u0000-\u001F\u007F]+", "");
// Step 4: 移除特殊的不可见字符(如零宽度空格等)
string cleanedString = Regex.Replace(withoutControlChars, @"[\u200B\u200C\u200D\uFEFF]+", "");
return cleanedString;
}
}
public class RelatedCamera
{
[Category("关联相机")]
[DisplayName("关联相机")]
[Description("关联相机描述")]
//[TypeConverter(typeof(CollectionCountConvert))]
public string CameraSourceId { get; set; } = "";
}
public class VisionEngine
{
[ReadOnly(true)]
public string Id { get; set; } = Guid.NewGuid().ToString();
[Category("检测配置")]
[DisplayName("检测配置名称")]
[Description("检测配置名称")]
public string Name { get; set; }
[Category("关联相机")]
[DisplayName("关联相机")]
[Description("关联相机描述")]
public string CameraSourceId { get; set; } = "";
[Category("关联相机集合")]
[DisplayName("关联相机集合")]
[Description("关联相机描述")]
//[TypeConverter(typeof(DeviceIdSelectorConverter<CameraBase>))]
public List<RelatedCamera> CameraCollects { get; set; } = new List<RelatedCamera>();
[Category("启用配置")]
[DisplayName("是否启用GPU检测")]
[Description("是否启用GPU检测")]
public bool IsEnableGPU { get; set; } = false;
[Category("2.中检测(深度学习)")]
[DisplayName("中检测-模型类型")]
[Description("模型类型ImageClassification-图片分类ObjectDetection目标检测Segmentation-图像分割")]
//[TypeConverter(typeof(EnumDescriptionConverter<MLModelType>))]
public MLModelType ModelType { get; set; } = MLModelType.ObjectDetection;
//[Category("2.中检测(深度学习)")]
//[DisplayName("中检测-GPU索引")]
//[Description("GPU索引")]
//public int GPUIndex { get; set; } = 0;
[Category("2.中检测(深度学习)")]
[DisplayName("中检测-模型文件路径")]
[Description("中处理 深度学习模型文件路径,路径中不可含有中文字符,一般情况可以只配置中检测模型,当需要先用预检测过滤一次时,请先配置好与预检测相关配置")]
public string ModelPath { get; set; }
public VisionEngine(string name, MLModelType modelType, string modelPath, bool isEnableGPU,string sCameraSourceId)
{
ModelPath = modelPath ?? string.Empty;
Name = name;
ModelType = modelType;
IsEnableGPU = isEnableGPU;
Id = Guid.NewGuid().ToString();
CameraSourceId = sCameraSourceId;
}
}
}