DHDHSoftware/DH.Devices.Vision/SimboVisionDriver.cs

1355 lines
56 KiB
C#
Raw Normal View History

2025-03-21 08:51:20 +08:00
using DH.Commons.Base;
using DH.Commons.Enums;
2025-04-01 18:15:30 +08:00
using DH.Commons.Helper;
2025-03-16 13:11:08 +08:00
using DH.UI.Model.Winform;
using HalconDotNet;
using OpenCvSharp;
using OpenCvSharp.Extensions;
2025-03-07 16:29:38 +08:00
using System;
using System.Collections.Generic;
using System.Diagnostics;
2025-04-02 18:26:34 +08:00
using System.Diagnostics.Eventing.Reader;
using System.Drawing.Imaging;
2025-03-07 16:29:38 +08:00
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Threading.Tasks;
2025-03-16 13:11:08 +08:00
using System.Windows.Forms;
2025-03-07 16:29:38 +08:00
using System.Xml.Linq;
2025-03-16 13:11:08 +08:00
using XKRS.UI.Model.Winform;
using static DH.Commons.Enums.EnumHelper;
2025-04-01 18:15:30 +08:00
using LogLevel = DH.Commons.Enums.EnumHelper.LogLevel;
2025-03-21 08:51:20 +08:00
using ResultState = DH.Commons.Base.ResultState;
2025-03-16 13:11:08 +08:00
2025-03-07 16:29:38 +08:00
namespace DH.Devices.Vision
{
2025-03-16 13:11:08 +08:00
public class SimboVisionDriver : VisionEngineBase
2025-03-07 16:29:38 +08:00
{
2025-03-16 13:11:08 +08:00
public Dictionary<string, HDevEngineTool> HalconToolDict = new Dictionary<string, HDevEngineTool>();
public List<SimboStationMLEngineSet> SimboStationMLEngineList = new List<SimboStationMLEngineSet>();
public void Init()
{
//InitialQueue();
InitialHalconTools();
InitialSimboMLEnginesAsync();
// ImageSaveHelper.OnImageSaveExceptionRaised -= ImageSaveHelper_OnImageSaveExceptionRaised;
// ImageSaveHelper.OnImageSaveExceptionRaised += ImageSaveHelper_OnImageSaveExceptionRaised;
// base.Init();
}
2025-03-27 18:03:07 +08:00
public void Stop()
{
SimboStationMLEngineList.ToList().ForEach(sm =>
{
if (sm.IsUseGPU)
{
sm.StationMLEngine.Dispose();
}
else
{
sm.StationMLEngine.Dispose2();
}
});
}
2025-03-16 13:11:08 +08:00
//private void ImageSaveHelper_OnImageSaveExceptionRaised(DateTime dt, string msg)
//{
// LogAsync(new LogMsg(dt, LogLevel.Error, msg));
//}
public override DetectStationResult RunInference(Mat originImgSet, string detectionId = null)
{
DetectStationResult detectResult = new DetectStationResult();
DetectionConfig detectConfig = null;
//找到对应的配置
if (!string.IsNullOrWhiteSpace(detectionId))
{
detectConfig = DetectionConfigs.FirstOrDefault(u => u.Id == detectionId);
}
else
{
//detectConfig = DetectionConfigs.FirstOrDefault(u => u.CameraSourceId == camera.CameraName);
}
if (detectConfig == null)
{
2025-04-01 18:15:30 +08:00
LogAsync(DateTime.Now, LogLevel.Exception, $"异常:未能获取检测配置");
2025-03-16 13:11:08 +08:00
//未能获得检测配置
return detectResult;
}
2025-04-02 18:26:34 +08:00
detectResult.DetectName = detectConfig.Name;
2025-04-02 14:41:26 +08:00
detectResult.ImageSaveDirectory=detectConfig.ImageSaveDirectory;
detectResult.SaveNGDetect=detectConfig.SaveNGDetect;
detectResult.SaveNGOriginal=detectConfig.SaveNGOriginal;
detectResult.SaveOKDetect=detectConfig.SaveOKDetect;
detectResult.SaveOKOriginal=detectConfig.SaveOKOriginal;
2025-04-02 18:26:34 +08:00
//detectResult.DetectionOriginImage = originImgSet.Clone().ToBitmap();
2025-04-01 18:15:30 +08:00
Stopwatch sw = new Stopwatch();
2025-03-16 13:11:08 +08:00
#region 1.
2025-04-01 18:15:30 +08:00
sw.Start();
2025-03-16 13:11:08 +08:00
using (Mat PreTMat = originImgSet.Clone())
{
PreTreated(detectConfig, detectResult, PreTMat);
2025-04-01 18:15:30 +08:00
PreTreated2(detectConfig, detectResult, PreTMat);
2025-03-16 13:11:08 +08:00
}
2025-04-01 18:15:30 +08:00
sw.Stop();
LogAsync(DateTime.Now, LogLevel.Information, $"产品:{detectResult.Pid} {detectConfig.Name}预处理耗时:{sw.ElapsedMilliseconds}ms。SpecsResults{string.Join("", detectResult.realSpecs.Select(u => $"{u.Code} {u.ActualValue}"))}");
// 工位2尺寸测量
2025-03-16 13:11:08 +08:00
#endregion
if (detectResult.IsPreTreatNG)
{
detectResult.ResultState = ResultState.DetectNG;
detectResult.IsPreTreatDone = true;
detectResult.IsMLDetectDone = false;
return detectResult;
}
if (!string.IsNullOrWhiteSpace(detectConfig.ModelPath) && detectConfig.IsEnabled)
{
SimboStationMLEngineSet mlSet = null;
mlSet = SimboStationMLEngineList.FirstOrDefault(t => t.DetectionId == detectConfig.Id);
if (mlSet == null)
{
// LogAsync(DateTime.Now, LogLevel.Exception, $"异常:{detectConfig.Name}未能获取对应配置的模型检测工具");
detectResult.IsMLDetectDone = false;
//HandleDetectDone(detectResult, detectConfig);
return detectResult;
}
#region 2.
2025-04-01 18:15:30 +08:00
LogAsync(DateTime.Now, LogLevel.Information, $"{detectConfig.Name} 产品{detectResult.TempPid} 模型检测执行");
2025-03-16 13:11:08 +08:00
if (!string.IsNullOrWhiteSpace(detectConfig.ModelPath))
{
Stopwatch mlWatch = new Stopwatch();
var req = new MLRequest();
//之前的检测图片都是相机存储成HImage
req.ResizeWidth = (int)detectConfig.ModelWidth;
req.ResizeHeight = (int)detectConfig.ModelHeight;
// req.LabelNames = detectConfig.GetLabelNames();
// req.Score = IIConfig.Score;
req.mImage = originImgSet.Clone();
2025-03-21 08:51:20 +08:00
req.in_lable_path = detectConfig.In_lable_path;
2025-03-16 13:11:08 +08:00
req.confThreshold = detectConfig.ModelconfThreshold;
req.iouThreshold = 0.3f;
req.segmentWidth = 320;
req.out_node_name = "output0";
switch (detectConfig.ModelType)
{
2025-03-21 08:51:20 +08:00
case ModelType.:
2025-03-16 13:11:08 +08:00
break;
2025-03-21 08:51:20 +08:00
case ModelType.:
2025-03-16 13:11:08 +08:00
break;
2025-03-21 08:51:20 +08:00
case ModelType.:
2025-03-16 13:11:08 +08:00
break;
2025-03-21 08:51:20 +08:00
case ModelType.:
2025-03-16 13:11:08 +08:00
break;
2025-03-21 08:51:20 +08:00
case ModelType.GPU:
2025-03-16 13:11:08 +08:00
break;
default:
break;
}
// LogAsync(DateTime.Now, LogLevel.Information, $"{detectConfig.Name} 产品{detectResult.TempPid} RunInference BEGIN");
mlWatch.Start();
//20230802改成多线程推理 RunInferenceFixed
2025-03-27 17:51:07 +08:00
// MLResult result = new MLResult();
var result = mlSet.StationMLEngine.RunInference(req);
2025-03-16 13:11:08 +08:00
// var result = mlSet.StationMLEngine.RunInferenceFixed(req);
mlWatch.Stop();
// LogAsync(DateTime.Now, LogLevel.Information, $"{detectConfig.Name} 产品{detectResult.TempPid} RunInference END");
// var req = new MLRequest();
//req.mImage = inferenceImage;
//req.ResizeWidth = detectConfig.ModelWidth;
//req.ResizeHeight = detectConfig.ModelHeight;
//req.confThreshold = detectConfig.ModelconfThreshold;
//req.iouThreshold = 0.3f;
//req.out_node_name = "output0";
//req.in_lable_path = detectConfig.in_lable_path;
//Stopwatch sw = Stopwatch.StartNew();
//var result = Dectection[detectionId].RunInference(req);
//sw.Stop();
//LogAsync(DateTime.Now, LogLevel.Information, $"{camera.Name} 推理进度1.1,产品{productNumber},耗时{sw.ElapsedMilliseconds}ms");
//this.BeginInvoke(new MethodInvoker(delegate ()
//{
// // pictureBox1.Image?.Dispose(); // 释放旧图像
// // pictureBox1.Image = result.ResultMap;
// richTextBox1.AppendText($"推理成功 {productNumber}, {result.IsSuccess}相机名字{camera.CameraName} 耗时 {mlWatch.ElapsedMilliseconds}ms\n");
//}));
//req.mImage?.Dispose();
if (result == null || (result != null && !result.IsSuccess))
{
2025-04-01 18:15:30 +08:00
LogAsync(DateTime.Now, LogLevel.Exception, $"CoreInx:{mlSet.GPUNo} 产品:{detectResult.Pid} {detectConfig.Name} 模型检测异常,{result?.ResultMessage}");
2025-03-16 13:11:08 +08:00
detectResult.IsMLDetectDone = false;
}
if (result != null && result.IsSuccess)
{
detectResult.DetectDetails = result.ResultDetails;
if (detectResult.DetectDetails != null)
{
2025-04-01 18:15:30 +08:00
LogAsync(DateTime.Now, LogLevel.Information, $"CoreInx:{mlSet.GPUNo} 产品:{detectResult.Pid} {detectResult.DetectName} 模型检测总耗时:{mlWatch.ElapsedMilliseconds} ms {result.ResultMessage},{string.Join("", detectResult.DetectDetails.Select(u => $"{u.LabelName} X:{u.Rect.X} Y:{u.Rect.Y} Area:{u.Area.ToString("f2")} W:{u.Rect.Width} H:{u.Rect.Height}"))}");
2025-03-16 13:11:08 +08:00
}
else
{
2025-04-01 18:15:30 +08:00
LogAsync(DateTime.Now, LogLevel.Exception, $"CoreInx:{mlSet.GPUNo} 产品:{detectResult.Pid} {detectConfig.Name} 模型检测异常返回 null");
2025-03-16 13:11:08 +08:00
detectResult.IsMLDetectDone = false;
}
}
}
#endregion
#region 3.
#endregion
//根据那些得分大于阈值的推理结果,判断产品是否成功
#region 4.
detectResult.DetectDetails?.ForEach(d =>
{
2025-03-24 15:21:16 +08:00
// 当前检测项的 过滤条件
var conditionList = detectConfig.DetectionLableList
.Where(u=>u.LabelName == d.LabelName)
.GroupBy(u => u.ResultState)
.OrderBy(u => u.Key)
.ToList();
if (conditionList.Count == 0)
{
2025-03-16 13:11:08 +08:00
2025-03-24 15:21:16 +08:00
d.FinalResult = d.LabelName.ToLower() == "ok"
? ResultState.OK
: ResultState.DetectNG;
}
else
{
d.FinalResult = detectConfig.IsMixModel
? ResultState.A_NG
: ResultState.OK;
2025-03-16 13:11:08 +08:00
2025-03-24 15:21:16 +08:00
}
2025-03-16 13:11:08 +08:00
2025-04-02 18:26:34 +08:00
//foreach (IGrouping<ResultState, DetectionFilter> group in conditionList)
//{
// bool b = group.ToList().Any(f =>
// {
// return f.FilterOperation(d);
// });
2025-03-24 15:21:16 +08:00
2025-04-02 18:26:34 +08:00
// if (b)
// {
// d.FinalResult = group.Key;
// break;
// }
2025-03-24 15:21:16 +08:00
2025-04-02 18:26:34 +08:00
//}
2025-03-16 13:11:08 +08:00
});
#endregion
#region 5.NG
//if (detectResult.DetectDetails?.Count > 0)
//{
// detectResult.ResultState = detectResult.DetectDetails.GroupBy(u => u.FinalResult).OrderBy(u => u.Key).First().First().FinalResult;
// detectResult.ResultLabel = detectResult.ResultLabel;
// detectResult.ResultLabelCategoryId = detectResult.ResultLabel;//TODO:设置优先级
//}
detectResult.ResultState = detectResult.DetectDetails?
.GroupBy(u => u.FinalResult)
.OrderBy(u => u.Key)
.FirstOrDefault()?.Key ?? ResultState.OK;
detectResult.ResultLabel = detectResult.ResultLabel;
detectResult.ResultLabelCategoryId = detectResult.ResultLabel;//TODO:设置优先级
#endregion
2025-04-01 18:15:30 +08:00
LogAsync(DateTime.Now, LogLevel.Information, $"{detectConfig.Name} 检测结果:{detectResult.ResultState.GetEnumDescription()}");
2025-03-16 13:11:08 +08:00
DisplayDetectionResult(detectResult, originImgSet.Clone(), detectionId);
}
return detectResult;
}
/// <summary>
/// 初始化深度学习工具
/// </summary>
private bool InitialSimboMLEnginesAsync()
{
//深度学习 模型加载
var resultOK = MLLoadModel();
return resultOK;
}
/// <summary>
/// 深度学习 模型加载
/// </summary>
/// <returns></returns>
private bool MLLoadModel()
{
bool resultOK = false;
try
{
// SimboStationMLEngineList = new List<SimboStationMLEngineSet>();
// _cameraRelatedDetectionDict = IConfig.DetectionConfigs.Select(t => t.ModelPath).Distinct().ToList();
DetectionConfigs.ForEach(dc =>
//_cameraRelatedDetectionDict.ForEach(dc =>
{
if (dc.IsEnabled && !string.IsNullOrWhiteSpace(dc.ModelPath))
{
if (dc.IsEnableGPU)
{
//if (IIConfig.IsLockGPU)
//{
//foreach (var validGPU in ValidGPUList2)
//{
// if (validGPU.DetectionIds.Contains(dc.Id))
// {
var engine = SingleMLLoadModel(dc, true, 0);
SimboStationMLEngineList.Add(engine);
// }
//}
//}
//else
//{
// foreach (var validGPU in ValidGPUList)
// {
// //var validGPU = ValidGPUList.FirstOrDefault(u => u.DetectionIds.Contains(dc.Id));
// if (validGPU.DetectionId == dc.Id)
// {
// var engine = SingleMLLoadModel(dc, true, validGPU.GPUNo);
// SimboStationMLEngineList.Add(engine);
// }
// }
//}
}
else
{
//for (int i = 0; i < IConfig.CPUNums; i++)
for (int i = 0; i < 1; i++)
{
//var engine = SingleMLLoadModel(dc, false, i);
var engine = SingleMLLoadModel(dc, false, i);
SimboStationMLEngineList.Add(engine);
}
}
}
});
resultOK = true;
}
catch (Exception ex)
{
// LogAsync(DateTime.Now, LogLevel.Exception, $"异常:模型并发加载异常:{ex.GetExceptionMessage()}");
resultOK = false;
}
return resultOK;
}
/// <summary>
/// 单个模型加载
/// </summary>
/// <param name="dc"></param>
/// <param name="gpuNum"></param>
/// <returns></returns>
private SimboStationMLEngineSet SingleMLLoadModel(DetectionConfig dc, bool isGPU, int coreInx)
{
SimboStationMLEngineSet mLEngineSet = new SimboStationMLEngineSet();
try
{
mLEngineSet.IsUseGPU = isGPU;
if (isGPU)
{
mLEngineSet.GPUNo = coreInx;
}
else
{
mLEngineSet.CPUNo = coreInx;
}
mLEngineSet.DetectionId = dc.Id;
mLEngineSet.DetectionName = dc.Name;
if (!string.IsNullOrWhiteSpace(dc.ModelPath))
{
// 根据算法类型创建不同的实例
switch (dc.ModelType)
{
2025-03-21 08:51:20 +08:00
case ModelType.:
2025-03-16 13:11:08 +08:00
break;
2025-03-21 08:51:20 +08:00
case ModelType.:
2025-03-16 13:11:08 +08:00
mLEngineSet.StationMLEngine = new SimboObjectDetection();
break;
2025-03-21 08:51:20 +08:00
case ModelType.:
2025-03-16 13:11:08 +08:00
break;
2025-03-21 08:51:20 +08:00
case ModelType.:
2025-03-16 13:11:08 +08:00
mLEngineSet.StationMLEngine = new SimboInstanceSegmentation();
break;
2025-03-21 08:51:20 +08:00
case ModelType.GPU:
2025-03-16 13:11:08 +08:00
mLEngineSet.StationMLEngine = new SimboDetection();
break;
default:
break;
}
MLInit mLInit;
string inferenceDevice = "CPU";
if (dc.IsEnableGPU)
{
inferenceDevice = "GPU";
mLInit = new MLInit(dc.ModelPath, isGPU, coreInx, dc.ModelconfThreshold);
}
else
{
mLInit = new MLInit(dc.ModelPath, "images", inferenceDevice, (int)dc.ModelWidth, (int)dc.ModelHeight);
}
bool isSuccess = mLEngineSet.StationMLEngine.Load(mLInit);
if (!isSuccess)
{
// throw new ProcessException("异常:模型加载异常", null);
}
2025-04-01 18:15:30 +08:00
LogAsync(DateTime.Now, LogLevel.Information, $"模型加载成功是否GPU:{isGPU} CoreInx:{coreInx} - {dc.Name}" + $" {dc.ModelType.GetEnumDescription()}:{dc.ModelPath}");
2025-03-16 13:11:08 +08:00
}
}
catch (Exception ex)
{
2025-04-02 18:26:34 +08:00
// LogAsync(DateTime.Now, LogLevel.Error, $"模型加载成功是否GPU:{isGPU} CoreInx:{coreInx} - {dc.Name}" + $" {dc.ModelType.GetEnumDescription()}:{dc.ModelPath}");
2025-04-01 18:15:30 +08:00
2025-04-02 18:26:34 +08:00
throw new ProcessException($"异常是否GPU:{isGPU} CoreInx:{coreInx} - {dc.Name}模型加载异常:{ex.GetExceptionMessage()}");
2025-03-16 13:11:08 +08:00
}
return mLEngineSet;
}
private void InitialHalconTools()
{
HOperatorSet.SetSystem("parallelize_operators", "true");
HOperatorSet.SetSystem("reentrant", "true");
HOperatorSet.SetSystem("global_mem_cache", "exclusive");
HalconToolDict = new Dictionary<string, HDevEngineTool>();
DetectionConfigs.ForEach(c =>
{
if (!c.IsEnabled)
return;
if (c.HalconAlgorithemPath_Pre != null)
LoadHalconTool(c.HalconAlgorithemPath_Pre);
});
}
private void LoadHalconTool(string path)
{
if (!HalconToolDict.ContainsKey(path))
{
string algorithemPath = path;
if (string.IsNullOrWhiteSpace(algorithemPath))
return;
string directoryPath = Path.GetDirectoryName(algorithemPath);
string fileName = Path.GetFileNameWithoutExtension(algorithemPath);
HDevEngineTool tool = new HDevEngineTool(directoryPath);
tool.LoadProcedure(fileName);
HalconToolDict[path] = tool;
}
}
/// <summary>
/// 预处理
/// </summary>
/// <param name="detectConfig"></param>
/// <param name="detectResult"></param>
public void PreTreated(DetectionConfig detectConfig, DetectStationResult detectResult, Mat MhImage)
{
try
{
// detectResult.VisionImageSet.DetectionOriginImage = detectResult.VisionImageSet.HImage.ConvertHImageToBitmap();
//detectResult.VisionImageSet.PreTreatedBitmap = detectResult.VisionImageSet.HImage.ConvertHImageToBitmap();
//detectResult.VisionImageSet.DetectionResultImage = detectResult.VisionImageSet.PreTreatedBitmap?.CopyBitmap();
if (!string.IsNullOrWhiteSpace(detectConfig.HalconAlgorithemPath_Pre))
{
HObject obj = OpenCVHelper.MatToHImage(MhImage);
HImage hImage = HalconHelper.ConvertHObjectToHImage(obj);
string toolKey = detectConfig.HalconAlgorithemPath_Pre;
if (!HalconToolDict.ContainsKey(toolKey))
{
// LogAsync(DateTime.Now, LogLevel.Exception, $"{detectConfig.Name}未获取预处理算法");
return;
}
//Mean_Thre Deviation_Thre Mean_standard Deviation_standard
var tool = HalconToolDict[toolKey];
////tool.InputTupleDic["Mean_Thre"] = 123;
for (int i = 0; i < detectConfig.PreTreatParams.Count; i++)
{
var param = detectConfig.PreTreatParams[i];
tool.InputTupleDic[param.Name] = double.Parse(param.Value);
}
// tool.InputTupleDic["fCricularity"] = 200;
tool.InputImageDic["INPUT_Image"] = hImage;
if (!tool.RunProcedure(out string errorMsg, out _))
{
// detectResult.PreTreatedFlag = false;
2025-04-01 18:15:30 +08:00
LogAsync(DateTime.Now, LogLevel.Exception, $"{detectConfig.Name}预处理异常,{errorMsg}");
2025-03-16 13:11:08 +08:00
detectResult.IsPreTreatDone = false;
return;
}
var preTreatRet = tool.GetResultTuple("OUTPUT_Flag").I;
//var fRCricularity = tool.GetResultTuple("fRCricularity");
// detectResult.IsPreTreatDone = detectResult.VisionImageSet.PreTreatedFlag = preTreatRet == 1;
//detectResult.IsPreTreatDone = detectResult.VisionImageSet.PreTreatedFlag = true;
// detectResult.VisionImageSet.PreTreatedTime = DateTime.Now;
2025-04-01 18:15:30 +08:00
switch (preTreatRet)
2025-03-16 13:11:08 +08:00
{
2025-04-01 18:15:30 +08:00
case 0: // 预处理算法无异常
{
for (int i = 0; i < detectConfig.OUTPreTreatParams.Count; i++)
{
var param = detectConfig.OUTPreTreatParams[i];
var Value = tool.GetResultTuple(param.Name);
// 显示结果
IndexedSpec specRCricularity = new()
{
Code = param.Name,
ActualValue = Value
};
detectResult.realSpecs.Add(specRCricularity);
}
detectResult.IsPreTreatNG = false;
detectResult.IsPreTreatDone = true;
}
break;
case -111: // 检测结果为NG
{
/// detectResult.VisionImageSet.DetectionResultImage =
// tool.GetResultObject("OUTPUT_PreTreatedImage").ConvertHImageToBitmap();
for (int i = 0; i < detectConfig.OUTPreTreatParams.Count; i++)
{
var param = detectConfig.OUTPreTreatParams[i];
var Value = tool.GetResultTuple(param.Name);
// 显示结果
IndexedSpec specRCricularity = new()
{
Code = param.Name,
ActualValue = Value
};
detectResult.realSpecs.Add(specRCricularity);
}
// 结果为NG
detectResult.ResultState = ResultState.DetectNG;
detectResult.IsPreTreatNG = true;
detectResult.IsPreTreatDone = true;
break;
}
default:
case -999: // 算法异常
{
// 算法异常时,结果图
// detectResult.VisionImageSet.DetectionResultImage =
// tool.GetResultObject("OUTPUT_PreTreatedImage").ConvertHImageToBitmap();
for (int i = 0; i < detectConfig.OUTPreTreatParams.Count; i++)
{
var param = detectConfig.OUTPreTreatParams[i];
// 显示结果
IndexedSpec specRCricularity = new()
{
Code = param.Name,
ActualValue = -1,
};
detectResult.realSpecs.Add(specRCricularity);
}
// 结果保持TBD
detectResult.IsPreTreatDone = true;
break;
}
2025-03-16 13:11:08 +08:00
}
2025-04-01 18:15:30 +08:00
2025-03-16 13:11:08 +08:00
// 2023/10/16 新增预处理结果反馈如果预处理结果为NG直接返回
if (preTreatRet != 0)
{
detectResult.ResultState = ResultState.DetectNG;
detectResult.IsPreTreatNG = true;
// if (detectResult.VisionImageSet.PreTreatedFlag)
{
//detectResult.VisionImageSet.MLImage = tool.GetResultObject("OUTPUT_PreTreatedImage");
//DetectionResultImage
// detectResult.VisionImageSet.DetectionResultImage = detectResult.VisionImageSet.MLImage.ConvertHImageToBitmap();
}
}
else
{
// detectResult.VisionImageSet.DetectionResultImage = detectResult.VisionImageSet.MLImage.ConvertHImageToBitmap();
}
}
}
catch (Exception ex)
{
2025-04-01 18:15:30 +08:00
LogAsync(DateTime.Now, LogLevel.Exception, $"{detectConfig.Name}预处理异常:{ex.GetExceptionMessage()}");
2025-03-16 13:11:08 +08:00
}
finally
{
//detectResult.VisionImageSet.HImage?.Dispose();
//detectResult.VisionImageSet.HImage = null;
// MhImage?.Dispose();
//MhImage = null;
}
}
2025-04-01 18:15:30 +08:00
public void PreTreated2(DetectionConfig detectConfig, DetectStationResult detectResult,Mat MhImage)
{
try
{
if (detectConfig.SizeTreatParamList != null && detectConfig.SizeTreatParamList.Count > 0)
{
foreach (var preTreat in detectConfig.SizeTreatParamList)
{
if (!string.IsNullOrWhiteSpace(preTreat.PrePath))
{
string toolKey = preTreat.PrePath;
if (!HalconToolDict.ContainsKey(toolKey))
{
LogAsync(DateTime.Now, LogLevel.Exception, $"{detectConfig.Name}未获取预处理{preTreat.PreName}算法");
return;
}
//Mean_Thre Deviation_Thre Mean_standard Deviation_standard
var tool = HalconToolDict[toolKey];
//tool.InputTupleDic["Mean_Thre"] = 123;
List<PreTreatParam> PreParams = new List<PreTreatParam>();
preoutparms(PreParams, preTreat.ResultShow);
for (int i = 0; i < PreParams.Count(); i++)
{
var param = PreParams[i];
if (param.Value.Contains(","))
{
string[] strings = param.Value.Split(",");
float[] array = strings.Select(s => float.Parse(s)).ToArray();
HTuple hTupleArray = new HTuple(array);
tool.InputTupleDic[param.Name] = hTupleArray;
}
else
{
tool.InputTupleDic[param.Name] = double.Parse(param.Value);// param.Value.ToInt();
}
IndexedSpec spec1 = new IndexedSpec();
switch (preTreat.PreType)
{
case SizeEnum.线线:
break;
case SizeEnum.线:
break;
case SizeEnum.:
break;
case SizeEnum.:
spec1.Code = $"in-{param.Name}";
spec1.ActualValue = double.Parse(param.Value);
break;
case SizeEnum.线:
break;
}
detectResult.realSpecs.Add(spec1);
}
//// 指定保存路径
//string filePath = @"D:\saved_image.jpg"; // 你可以根据需要更改路径和文件名
//// 使用WriteImage保存图像
//detectResult.VisionImageSet.HImage.WriteImage("jpeg", 0, filePath); // "jpeg" 表示图像格式0表示不使用压缩
HObject obj = OpenCVHelper.MatToHImage(MhImage);
HImage hImage = HalconHelper.ConvertHObjectToHImage(obj);
tool.InputImageDic["INPUT_Image"] = hImage;
if (!tool.RunProcedure(out string errorMsg, out _))
{
// detectResult.VisionImageSet.PreTreatedFlag = false;
LogAsync(DateTime.Now, LogLevel.Exception, $"{detectConfig.Name}预处理异常,{errorMsg}");
detectResult.IsPreTreatDone = false;
// HandleDetectDone(detectResult, detectConfig);
return;
}
var preTreatRet = tool.GetResultTuple("OUTPUT_Flag").I;
//double MatchScore = 1;
//MatchScore = tool.GetResultTuple("MatchScore");
detectResult.IsPreTreatDone = preTreatRet == 1;
// detectResult.IsPreTreatDone = detectResult.VisionImageSet.PreTreatedFlag = true;
// detectResult.VisionImageSet.PreTreatedTime = DateTime.Now;
//IndexedSpec spec1 = new IndexedSpec();
//spec1.Code = "score";
//spec1.ActualValue = MatchScore;
//detectResult.realSpecs.Add(spec1);
;
// 2023/10/16 新增预处理结果反馈如果预处理结果为NG直接返回
if (preTreatRet != 0)
{
detectResult.ResultState = ResultState.DetectNG;
detectResult.IsPreTreatNG = true;
// detectResult.VisionImageSet.DetectionResultImage = detectResult.VisionImageSet.MLImage.ConvertHImageToBitmap();
}
else
{
switch (preTreat.PreType)
{
case SizeEnum.线线:
isPreOutparams(ref detectResult, preTreat, tool, ref preTreatRet);
break;
case SizeEnum.线:
isPreOutparams(ref detectResult, preTreat, tool, ref preTreatRet);
break;
case SizeEnum.:
break;
case SizeEnum.:
{
isPreOutparams(ref detectResult, preTreat, tool, ref preTreatRet);
}
break;
case SizeEnum.线:
break;
}
}
}
}
}
}
catch (Exception ex)
{
LogAsync(DateTime.Now, LogLevel.Exception, $"{detectConfig.Name}尺寸预处理异常:{ex.GetExceptionMessage()}");
}
finally
{
//detectResult.VisionImageSet.HImage?.Dispose();
//detectResult.VisionImageSet.HImage = null;
}
}
public void isPreOutparams(ref DetectStationResult detectResult, SizeTreatParam preTreat, HDevEngineTool tool, ref int preTreatRet)
{
List<PreTreatParam> PreParams = new List<PreTreatParam>();
preoutparms(PreParams, preTreat.OutResultShow);
for (int i = 0; i < PreParams.Count; i++)
{
var param = PreParams[i];
double dParam = double.Parse(param.Value);
double heights = tool.GetResultTuple(param.Name).D;
switch (preTreat.PreType)
{
case SizeEnum.:
IndexedSpec spec2 = new IndexedSpec();
spec2.Code = $"out-{param.Name}";
spec2.ActualValue = Convert.ToDouble(param.Value);
detectResult.realSpecs.Add(spec2);
IndexedSpec spec1 = new IndexedSpec();
spec1.Code = $"actual-{param.Name}";
spec1.ActualValue = heights;
detectResult.realSpecs.Add(spec1);
break;
default: break;
}
if ((heights > dParam - preTreat.PrePix) && (heights < dParam + preTreat.PrePix))
{
}
else
{
preTreatRet = -1;
break;
}
}
if (preTreatRet != 0)
{
detectResult.ResultState = ResultState.DetectNG;
detectResult.IsPreTreatNG = true;
//detectResult.VisionImageSet.DetectionResultImage = detectResult.VisionImageSet.MLImage.ConvertHImageToBitmap();
}
else
{
// detectResult.VisionImageSet.DetectionResultImage = detectResult.VisionImageSet.MLImage.ConvertHImageToBitmap();
}
}
public void preoutparms(List<PreTreatParam> preTreatParams, string defectRows)
{
// 解析 ReslutShow 字符串,构建 PreTreatParam 列表
if (!string.IsNullOrEmpty(defectRows))
{
var keyValuePairs = defectRows.Split(';');
foreach (var pair in keyValuePairs)
{
var parts = pair.Split(':');
if (parts.Length == 2)
{
PreTreatParam param;
if (parts[1].Trim().Contains(","))
{
param = new PreTreatParam
{
Name = parts[0].Trim(), // 去除多余的空格
Value = parts[1].Trim() // 转换为 double失败则为0
};
}
else
{
double dvalue = double.TryParse(parts[1].Trim(), out double value) ? value : 0;
param = new PreTreatParam
{
Name = parts[0].Trim(), // 去除多余的空格
Value = dvalue.ToString() // 转换为 double失败则为0
};
}
preTreatParams.Add(param);
}
}
}
}
2025-03-16 13:11:08 +08:00
/// <summary>
/// 显示检测结果
/// </summary>
/// <param name="detectResult"></param>
private void DisplayDetectionResult(DetectStationResult detectResult,Mat result,string DetectionId)
{
//结果显示上传
Task.Run(() =>
{
try
{
string displayTxt = detectResult.ResultState.ToString() + "\r\n";
if (detectResult.DetectDetails != null && detectResult.DetectDetails?.Count > 0)
{
detectResult.DetectDetails.ForEach(d =>
{
displayTxt +=
$"{d.LabelName} score:{d.Score.ToString("f2")} area:{d.Area.ToString("f2")}\r\n";
});
}
2025-04-02 14:41:26 +08:00
if (detectResult.realSpecs != null && detectResult.realSpecs?.Count > 0)
{
detectResult.realSpecs.ForEach(d =>
{
displayTxt +=
$"{d.Code} :{d.ActualValue} \r\n";
});
}
Bitmap resultMask =result.ToBitmap();
2025-03-16 13:11:08 +08:00
//if (detectResult.VisionImageSet.DetectionResultImage == null && detectResult.VisionImageSet.SizeResultImage == null)
//{
// return;
//}
//else if (detectResult.VisionImageSet.DetectionResultImage == null && detectResult.VisionImageSet.SizeResultImage != null)
//{
// detectResult.VisionImageSet.DetectionResultImage = detectResult.VisionImageSet.SizeResultImage.CopyBitmap();
// resultMask = detectResult.VisionImageSet.DetectionResultImage.CopyBitmap();
//}
//else if (detectResult.VisionImageSet.DetectionResultImage != null && detectResult.VisionImageSet.SizeResultImage != null)
//{
// Mat img1 = ConvertBitmapToMat(detectResult.VisionImageSet.SizeResultImage.CopyBitmap()); // 第一张图片,已经带框
// Mat img2 = ConvertBitmapToMat(detectResult.VisionImageSet.DetectionResultImage.CopyBitmap()); // 第二张图片,已经带框
// // 合成两张图像:可以选择叠加或拼接
// Mat resultImg = new Mat();
// Cv2.AddWeighted(img1, 0.5, img2, 0.5, 0, resultImg); // 使用加权平均法合成图像
// resultMask = resultImg.ToBitmap();
//}
//else
//{
// resultMask = detectResult.VisionImageSet.DetectionResultImage.CopyBitmap();
//}
List<IShapeElement> detectionResultShapes =
new List<IShapeElement>(detectResult.DetectionResultShapes);
DetectResultDisplay resultDisplay = new DetectResultDisplay(detectResult, resultMask, displayTxt);
detectionResultShapes.Add(resultDisplay);
List<IShapeElement> detectionResultShapesClone = new List<IShapeElement>(detectionResultShapes);
DetectionDone(DetectionId, resultMask, detectionResultShapes);
2025-04-02 18:26:34 +08:00
detectResult.DetectionOriginImage = CopyBitmapWithLockBits(resultMask);
2025-04-02 14:41:26 +08:00
SaveDetectResultImageAsync(detectResult);
2025-03-16 13:11:08 +08:00
// SaveDetectResultCSVAsync(detectResult);
}
catch (Exception ex)
{
2025-04-02 18:26:34 +08:00
//LogAsync(DateTime.Now, LogLevel.Exception,
// $"{Name}显示{detectResult.DetectName}检测结果异常,{ex.GetExceptionMessage()}");
2025-03-16 13:11:08 +08:00
}
finally
{
}
});
}
2025-04-02 18:26:34 +08:00
public static Bitmap CopyBitmapWithLockBits(Bitmap original)
{
Bitmap copy = new Bitmap(original.Width, original.Height, original.PixelFormat);
BitmapData originalData = original.LockBits(
new Rectangle(0, 0, original.Width, original.Height),
ImageLockMode.ReadOnly,
original.PixelFormat
);
BitmapData copyData = copy.LockBits(
new Rectangle(0, 0, copy.Width, copy.Height),
ImageLockMode.WriteOnly,
copy.PixelFormat
);
int bytesPerPixel = Image.GetPixelFormatSize(original.PixelFormat) / 8;
int byteCount = originalData.Stride * original.Height;
byte[] buffer = new byte[byteCount];
System.Runtime.InteropServices.Marshal.Copy(originalData.Scan0, buffer, 0, byteCount);
System.Runtime.InteropServices.Marshal.Copy(buffer, 0, copyData.Scan0, byteCount);
original.UnlockBits(originalData);
copy.UnlockBits(copyData);
return copy;
}
2025-04-02 14:41:26 +08:00
/// <summary>
///图片异步保存
/// </summary>
2025-04-02 18:26:34 +08:00
public void SaveDetectResultImageAsync1(DetectStationResult detectResult)
2025-04-02 14:41:26 +08:00
{
string format = detectResult.ImageFormat.ToString().ToLower();
2025-04-02 18:26:34 +08:00
if(detectResult.ImageSaveDirectory!=null)
{
if (!Directory.Exists(detectResult.ImageSaveDirectory))
{
}
else
{
}
}else
{
return;
}
2025-04-02 14:41:26 +08:00
2025-04-02 18:26:34 +08:00
2025-04-02 14:41:26 +08:00
//根目录
string rootPath = Path.Combine(detectResult.ImageSaveDirectory,
2025-04-02 18:26:34 +08:00
DateTime.Now.ToString("yyyyMMdd"), detectResult.DetectName);
2025-04-02 14:41:26 +08:00
if (detectResult.ResultState != ResultState.OK)
{
// NG原图
if (detectResult.SaveNGOriginal && detectResult.DetectionOriginImage != null)
{
string prefix = Path.Combine(rootPath, "NGRawImages", detectResult.ResultLabel);
string fullname = Path.Combine(prefix, $"{detectResult.Pid}_NGRawImage_{detectResult.DetectName}_{detectResult.Id}.{format}");
SaveImageAsync(fullname, detectResult.DetectionOriginImage, detectResult.ImageFormat);
}
//NG结果图
if (detectResult.SaveOKDetect && detectResult.DetectionOriginImage != null)
{
// 没有预处理,则保存原始图+检测结果图
// if (detectResult.VisionImageSet.PreTreatedBitmap == null)
{
//string displayTxt = detectResult.ResultState.ToString() + "\r\n";
string displayTxt = "";
detectResult.DetectDetails.ForEach(d =>
{
displayTxt += $"{d.LabelName} score:{d.Score.ToString("f2")} area:{d.Area.ToString("f2")}\r\n";
});
if (detectResult.realSpecs != null && detectResult.realSpecs?.Count > 0)
{
detectResult.realSpecs.ForEach(d =>
{
displayTxt +=
$"{d.Code} score:{d.ActualValue} \r\n";
});
}
Bitmap resultMask = detectResult.DetectionOriginImage.CopyBitmap();
Bitmap preTreatedBitmap = detectResult.DetectionOriginImage.CopyBitmap();
List<IShapeElement> detectionResultShapes = new List<IShapeElement>(detectResult.DetectionResultShapes);
DetectResultDisplay resultDisplay = new DetectResultDisplay(detectResult, resultMask, displayTxt);
detectionResultShapes.Add(resultDisplay);
2025-03-07 16:29:38 +08:00
2025-04-02 14:41:26 +08:00
Bitmap resultMap = GetResultImage(resultMask, detectionResultShapes);
resultDisplay.Dispose();
detectionResultShapes.Clear();
Bitmap detectionFitImage = StaticHelper.HConnectBitmap(preTreatedBitmap, resultMap);
string prefix = Path.Combine(rootPath, "NGFitImages", detectResult.ResultLabel);
2025-04-02 18:26:34 +08:00
Directory.CreateDirectory(prefix); // 自动创建所有缺失的目录
2025-04-02 14:41:26 +08:00
string fullname = Path.Combine(prefix, $"{detectResult.Pid}_NGFitImage_{detectResult.DetectName}_{detectResult.Id}.{format}");
2025-04-02 18:26:34 +08:00
// SaveImageAsync(fullname, detectionFitImage, detectResult.ImageFormat);
// 使用回调或 Task.ContinueWith 确保保存完成后再释放资源
//SaveImageAsync(fullname, detectionFitImage, detectResult.ImageFormat)
// .ContinueWith(t =>
// {
// resultMask?.Dispose();
// preTreatedBitmap?.Dispose();
// resultMap?.Dispose();
// detectionFitImage?.Dispose();
// }, TaskScheduler.Default);
2025-04-02 14:41:26 +08:00
resultMask?.Dispose();
preTreatedBitmap?.Dispose();
resultMap?.Dispose();
detectionFitImage?.Dispose();
}
}
}
else
{ // OK原图
if (detectResult.SaveOKOriginal && detectResult.DetectionOriginImage != null)
{
string prefix = Path.Combine(rootPath, "OKRawImages", detectResult.ResultLabel);
string fullname = Path.Combine(prefix, $"{detectResult.Pid}_OKRawImage_{detectResult.DetectName}_{detectResult.Id}.{format}");
SaveImageAsync(fullname, detectResult.DetectionOriginImage, detectResult.ImageFormat);
}
//ok结果图
if (detectResult.SaveOKDetect && detectResult.DetectionOriginImage != null)
{
// 没有预处理,则保存原始图+检测结果图
// if (detectResult.VisionImageSet.PreTreatedBitmap == null)
{
//string displayTxt = detectResult.ResultState.ToString() + "\r\n";
string displayTxt = "";
detectResult.DetectDetails.ForEach(d =>
{
displayTxt += $"{d.LabelName} score:{d.Score.ToString("f2")} area:{d.Area.ToString("f2")}\r\n";
});
if (detectResult.realSpecs != null && detectResult.realSpecs?.Count > 0)
{
detectResult.realSpecs.ForEach(d =>
{
displayTxt +=
$"{d.Code} score:{d.ActualValue} \r\n";
});
}
Bitmap resultMask = detectResult.DetectionOriginImage.CopyBitmap();
Bitmap preTreatedBitmap = detectResult.DetectionOriginImage.CopyBitmap();
List<IShapeElement> detectionResultShapes = new List<IShapeElement>(detectResult.DetectionResultShapes);
DetectResultDisplay resultDisplay = new DetectResultDisplay(detectResult, resultMask, displayTxt);
detectionResultShapes.Add(resultDisplay);
Bitmap resultMap = GetResultImage(resultMask, detectionResultShapes);
2025-04-02 18:26:34 +08:00
2025-04-02 14:41:26 +08:00
Bitmap detectionFitImage = StaticHelper.HConnectBitmap(preTreatedBitmap, resultMap);
string prefix = Path.Combine(rootPath, "OKFitImages", detectResult.ResultLabel);
string fullname = Path.Combine(prefix, $"{detectResult.Pid}_" +
$"OKFitImage_{detectResult.DetectName}_{detectResult.Id}.{format}");
SaveImageAsync(fullname, detectionFitImage, detectResult.ImageFormat);
2025-04-02 18:26:34 +08:00
//resultDisplay.Dispose();
//detectionResultShapes.Clear();
//resultMask?.Dispose();
//preTreatedBitmap?.Dispose();
//resultMap?.Dispose();
//detectionFitImage?.Dispose();
2025-04-02 14:41:26 +08:00
}
}
}
}
2025-04-02 18:26:34 +08:00
2025-04-02 14:41:26 +08:00
public virtual Bitmap GetResultImage(Bitmap baseImage, List<IShapeElement> eleList)
{
try
{
// 重新生成画布 避免 无法从带有索引像素格式的图像创建graphics对象
Bitmap image = new Bitmap(baseImage.Width, baseImage.Height);
using (Graphics g = Graphics.FromImage(image))
{
g.DrawImage(baseImage, 0, 0);
eleList.ForEach(e =>
{
e.State = ElementState.Normal;
e.Draw(g);
});
}
return image;
}
catch (Exception ex)
{
LogAsync(DateTime.Now, LogLevel.Exception, $"获取叠加结果图片异常:{ex.GetExceptionMessage()}");
return null;
}
}
2025-04-02 18:26:34 +08:00
public void SaveDetectResultImageAsync(DetectStationResult detectResult)
{
if (detectResult.ImageSaveDirectory == null) return;
string format = detectResult.ImageFormat.ToString().ToLower();
string rootPath = Path.Combine(detectResult.ImageSaveDirectory,
DateTime.Now.ToString("yyyyMMdd"), detectResult.DetectName);
try
{
if (detectResult.ResultState != ResultState.OK)
{
SaveNGImages(detectResult, rootPath, format);
}
else
{
SaveOKImages(detectResult, rootPath, format);
}
}
catch (Exception ex)
{
// Logger.Error($"保存检测结果失败: {ex.Message}");
}
}
private void SaveNGImages(DetectStationResult result, string rootPath, string format)
{
// NG 原图
if (result.SaveNGOriginal && result.DetectionOriginImage != null)
{
string prefix = Path.Combine(rootPath, "NGRawImages", result.ResultLabel);
Directory.CreateDirectory(prefix);
string fullname = Path.Combine(prefix, $"{result.Pid}_NGRawImage_{result.DetectName}_{result.Id}.{format}");
SaveImageAsync(fullname, result.DetectionOriginImage, result.ImageFormat);
}
// NG 结果图
if (result.SaveOKDetect && result.DetectionOriginImage != null)
{
string displayTxt = BuildDisplayText(result);
using (Bitmap resultMask = result.DetectionOriginImage.CopyBitmap())
using (Bitmap preTreatedBitmap = result.DetectionOriginImage.CopyBitmap())
{
var detectionResultShapes = new List<IShapeElement>(result.DetectionResultShapes)
{
new DetectResultDisplay(result, resultMask, displayTxt)
};
using (Bitmap resultMap = GetResultImage(resultMask, detectionResultShapes))
using (Bitmap detectionFitImage = StaticHelper.HConnectBitmap(preTreatedBitmap, resultMap))
{
string prefix = Path.Combine(rootPath, "NGFitImages", result.ResultLabel);
Directory.CreateDirectory(prefix);
string fullname = Path.Combine(prefix, $"{result.Pid}_NGFitImage_{result.DetectName}_{result.Id}.{format}");
SaveImageAsync(fullname, detectionFitImage, result.ImageFormat);
}
}
}
}
private void SaveOKImages(DetectStationResult result, string rootPath, string format)
{
// OK 原图
if (result.SaveOKOriginal && result.DetectionOriginImage != null)
{
string prefix = Path.Combine(rootPath, "OKRawImages", result.ResultLabel);
Directory.CreateDirectory(prefix);
string fullname = Path.Combine(prefix, $"{result.Pid}_OKRawImage_{result.DetectName}_{result.Id}.{format}");
SaveImageAsync(fullname, result.DetectionOriginImage, result.ImageFormat);
}
// OK 结果图
if (result.SaveOKDetect && result.DetectionOriginImage != null)
{
string displayTxt = BuildDisplayText(result);
using (Bitmap resultMask = result.DetectionOriginImage.CopyBitmap())
using (Bitmap preTreatedBitmap = result.DetectionOriginImage.CopyBitmap())
{
var detectionResultShapes = new List<IShapeElement>(result.DetectionResultShapes)
{
new DetectResultDisplay(result, resultMask, displayTxt)
};
using (Bitmap resultMap = GetResultImage(resultMask, detectionResultShapes))
using (Bitmap detectionFitImage = StaticHelper.HConnectBitmap(preTreatedBitmap, resultMap))
{
string prefix = Path.Combine(rootPath, "OKFitImages", result.ResultLabel);
Directory.CreateDirectory(prefix);
string fullname = Path.Combine(prefix, $"{result.Pid}_OKFitImage_{result.DetectName}_{result.Id}.{format}");
SaveImageAsync(fullname, result.DetectionOriginImage, result.ImageFormat);
}
}
}
}
private string BuildDisplayText(DetectStationResult result)
{
StringBuilder sb = new StringBuilder();
result.DetectDetails.ForEach(d => sb.AppendLine($"{d.LabelName} score:{d.Score:f2} area:{d.Area:f2}"));
if (result.realSpecs?.Count > 0)
{
result.realSpecs.ForEach(d => sb.AppendLine($"{d.Code} score:{d.ActualValue}"));
}
return sb.ToString();
}
2025-03-07 16:29:38 +08:00
}
}