diff --git a/DH.Commons/DH.Commons.csproj b/DH.Commons/DH.Commons.csproj
index 1c2b199..1920bc2 100644
--- a/DH.Commons/DH.Commons.csproj
+++ b/DH.Commons/DH.Commons.csproj
@@ -5,6 +5,26 @@
enable
enable
AnyCPU;X64
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\x64\Debug\halcondotnet.dll
+
+
+ ..\x64\Debug\hdevenginedotnet.dll
+
+
+
diff --git a/DH.Commons/GlobalVar.cs b/DH.Commons/GlobalVar.cs
new file mode 100644
index 0000000..ce615fc
--- /dev/null
+++ b/DH.Commons/GlobalVar.cs
@@ -0,0 +1,39 @@
+
+
+namespace XKRS.Common.Model
+{
+ public static class GlobalVar
+ {
+
+ //public const string SEPERATOR = "|";
+
+ //public static ContainerBuilder Builder { get; set; } = new ContainerBuilder();
+
+ //private static object containerLock = new object();
+
+ //private static IContainer container = null;
+ //public static IContainer Container
+ //{
+ // get
+ // {
+ // if (container == null)
+ // {
+ // lock (containerLock)
+ // {
+ // if (container == null)
+ // {
+ // container = Builder.Build();
+ // }
+ // }
+ // }
+
+ // return container;
+ // }
+ //}
+
+ //public static void InitialAutoFac()
+ //{
+ // Container = Builder.Build();
+ //}
+ }
+}
diff --git a/DH.Commons/Helper/HDevEngineTool.cs b/DH.Commons/Helper/HDevEngineTool.cs
new file mode 100644
index 0000000..bd6f51e
--- /dev/null
+++ b/DH.Commons/Helper/HDevEngineTool.cs
@@ -0,0 +1,677 @@
+using HalconDotNet;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Runtime.ExceptionServices;
+using System.Runtime.InteropServices;
+
+namespace XKRS.Common.Model
+{
+ public class HDevEngineTool : IDisposable
+ {
+ #region 常量
+
+ // path of external procedures
+ readonly string ProcedurePath = Environment.CurrentDirectory + "\\Vision\\";
+
+ #endregion
+
+ #region 成员变量
+
+ ///
+ /// 处理过程名
+ ///
+ public string ProcedureName;
+
+ ///
+ /// hdev程序启动引擎
+ ///
+ private readonly HDevEngine myEngine;
+
+ ///
+ /// 过程载入工具 .hdvp
+ ///
+ private HDevProcedureCall procedureCall;
+
+ ///
+ /// 程序运行是否成功
+ ///
+ public bool IsSuccessful { get; set; } = false;
+
+ ///
+ /// 控制参数字典
+ ///
+ public Dictionary InputTupleDic { get; set; }
+
+ ///
+ /// 图形参数字典
+ ///
+ public Dictionary InputImageDic { get; set; }
+
+ #endregion
+
+ #region 初始化
+ ///
+ /// 实例化 默认搜索路径为: 启动路径//Vision//
+ ///
+ public HDevEngineTool()
+ {
+ ProcedureName = "";
+ myEngine = new HDevEngine();
+ myEngine.SetProcedurePath(ProcedurePath);
+
+ InputImageDic = new Dictionary();
+ InputTupleDic = new Dictionary();
+ }
+
+ ///
+ /// 实例化
+ ///
+ /// 外部函数搜索路径
+ public HDevEngineTool(string path)
+ {
+ myEngine = new HDevEngine();
+ myEngine.SetProcedurePath(path);
+
+ InputImageDic = new Dictionary();
+ InputTupleDic = new Dictionary();
+ }
+ #endregion
+
+
+
+ ///
+ /// 设置函数运行所需参数
+ ///
+ /// 控制参数
+ /// 图形参数
+ public void SetDictionary(Dictionary _tupleDictionary, Dictionary _imageDictionary)
+ {
+ InputTupleDic = _tupleDictionary;
+ InputImageDic = _imageDictionary;
+ }
+
+
+
+ ///
+ /// 载入过程 .hdvp
+ ///
+ /// 过程名
+ public void LoadProcedure(string procedureName)
+ {
+ ProcedureName = procedureName;
+ try
+ {
+ HDevProcedure procedure = new HDevProcedure(procedureName);
+ procedureCall = new HDevProcedureCall(procedure);
+ }
+ catch (HDevEngineException Ex)
+ {
+ Trace.TraceInformation("HDevProgram {0} Load fail ,Error Line : {1}, Line number: {2}, Halcon error number : {3}", Ex.ProcedureName, Ex.LineText, Ex.LineNumber, Ex.HalconError);
+ return;
+ }
+ }
+
+
+
+ ///
+ /// 执行过程
+ ///
+ [HandleProcessCorruptedStateExceptions]
+ public bool RunProcedure(out string errorMsg, out int timeElasped)
+ {
+ //lock (_runLock)
+ {
+ errorMsg = "";
+ Stopwatch sw = new Stopwatch();
+ sw.Start();
+ try
+ {
+ foreach (KeyValuePair pair in InputTupleDic)
+ {
+ procedureCall.SetInputCtrlParamTuple(pair.Key, pair.Value);
+ }
+
+ foreach (KeyValuePair pair in InputImageDic)
+ {
+ procedureCall.SetInputIconicParamObject(pair.Key, pair.Value);
+ }
+
+ procedureCall.Execute();
+
+ IsSuccessful = true;
+ }
+ catch (HDevEngineException ex)
+ {
+ IsSuccessful = false;
+ errorMsg = $"HDevProgram {ex.ProcedureName} Run fail , Line number: {ex.LineNumber}, Halcon error number : {ex.HalconError},ex:{ex.Message}";
+ }
+ finally
+ {
+ sw.Stop();
+ timeElasped = (int)sw.ElapsedMilliseconds;
+ }
+ return IsSuccessful;
+ }
+ }
+
+ object _runLock = new object();
+ ///
+ /// 执行过程
+ ///
+ public Tuple, Dictionary, string, int> RunProcedure(Dictionary inputHTupleDict, Dictionary inputImgDict, List outputHTuples = null, List outputObjs = null)
+ {
+ lock (_runLock)
+ {
+ string errorMsg = "";
+ int timeElasped = 0;
+ bool result = false;
+ Dictionary outputHTupleDict = new Dictionary();
+ Dictionary outputObjDict = new Dictionary();
+
+ Stopwatch sw = new Stopwatch();
+ sw.Start();
+ try
+ {
+ if (inputHTupleDict != null && inputHTupleDict.Count > 0)
+ {
+ foreach (KeyValuePair pair in inputHTupleDict)
+ {
+ procedureCall.SetInputCtrlParamTuple(pair.Key, pair.Value);
+ }
+ }
+
+ if (InputImageDic != null && inputImgDict.Count > 0)
+ {
+ foreach (KeyValuePair pair in inputImgDict)
+ {
+ procedureCall.SetInputIconicParamObject(pair.Key, pair.Value);
+ }
+ }
+
+ procedureCall.Execute();
+
+ result = true;
+ }
+ catch (HDevEngineException ex)
+ {
+ result = false;
+ errorMsg += $"HDevProgram {ex.ProcedureName} Run fail , Line number: {ex.LineNumber}, Halcon error number : {ex.HalconError},ex:{ex.Message}";
+ }
+ finally
+ {
+ sw.Stop();
+ timeElasped = (int)sw.ElapsedMilliseconds;
+ }
+
+ if (result)
+ {
+ if (outputHTuples != null && outputHTuples.Count > 0)
+ {
+ outputHTuples.ForEach(t =>
+ {
+ try
+ {
+ outputHTupleDict[t] = procedureCall.GetOutputCtrlParamTuple(t);
+ }
+ catch (Exception ex)
+ {
+ result = false;
+ errorMsg += $"\r\n获取{t}结果异常:{ex.Message}";
+
+ outputHTupleDict[t] = null;
+ }
+ });
+ }
+
+ if (outputObjs != null && outputObjs.Count > 0)
+ {
+ outputObjs.ForEach(t =>
+ {
+ try
+ {
+ outputObjDict[t] = procedureCall.GetOutputIconicParamObject(t);
+ }
+ catch (Exception ex)
+ {
+ result = false;
+ errorMsg += $"\r\n获取{t}结果异常:{ex.Message}";
+
+ outputObjDict[t] = null;
+ }
+ });
+ }
+ }
+ Tuple, Dictionary, string, int> ret = new Tuple, Dictionary, string, int>(result, outputHTupleDict, outputObjDict, errorMsg, timeElasped);
+ return ret;
+ }
+ }
+
+ public HTuple GetResultTuple(string key)
+ {
+ try
+ {
+ if (IsSuccessful)
+ {
+ return procedureCall.GetOutputCtrlParamTuple(key);
+ }
+ else
+ {
+ return new HTuple();
+ }
+ }
+ catch (Exception ex)
+ {
+ return new HTuple();
+ }
+
+ }
+
+ public HObject GetResultObject(string key, bool ignoreError = false)
+ {
+ try
+ {
+ if (ignoreError || IsSuccessful)
+ {
+ return procedureCall.GetOutputIconicParamObject(key);
+ }
+ else
+ {
+ return new HObject();
+ }
+ }
+ catch (Exception ex)
+ {
+ return new HObject();
+ }
+ }
+
+ public void Dispose()
+ {
+ procedureCall?.Dispose();
+ myEngine?.Dispose();
+ }
+ }
+
+ public static class HalconHelper
+ {
+ [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
+ public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
+
+ public static HImage Convert8GrayBitmapToHImage(this Bitmap bmp)
+ {
+ HImage himage = new HImage();
+ try
+ {
+ //判断输入图像不为null
+ if (bmp == null)
+ {
+ return null;
+ }
+
+ {
+ //重绘himage
+ //HImage curImage = new HImage();
+ BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
+ himage.GenImage1("byte", bmp.Width, bmp.Height, bmpData.Scan0);
+ bmp.UnlockBits(bmpData);
+ //himage = curImage;
+ }
+ return himage;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static Bitmap ConvertHImageToBitmap(this HObject hImage)
+ {
+ HOperatorSet.CountChannels(hImage, out HTuple chanels);
+ if (chanels.I == 1)
+ {
+ return hImage.ConvertHImageTo8GrayBitmap();
+ }
+ else
+ {
+ return hImage.ConvertHImageToRGBBitmap();
+ //return hImage.HObject2BitmapRGB();
+ }
+ }
+
+ public static Bitmap HObject2BitmapRGB(this HObject hObject)
+ {
+ ////获取图像尺寸
+ HTuple width0, height0, type, width, height;
+ //获取图像尺寸
+ HOperatorSet.GetImageSize(hObject, out width0, out height0);
+ // 创建交错格式图像
+ HOperatorSet.InterleaveChannels(hObject, out HObject InterImage, "argb", "match", 255); //"rgb", 4 * width0, 0 "argb", "match", 255
+
+ //获取交错格式图像指针
+ HOperatorSet.GetImagePointer1(InterImage, out HTuple Pointer, out type, out width, out height);
+ IntPtr ptr = Pointer;
+ //构建新Bitmap图像
+ Bitmap res32 = new Bitmap(width / 4, height, width, PixelFormat.Format32bppArgb, ptr); // Format32bppArgb Format24bppRgb
+
+ //32位Bitmap转24位
+ var res24 = new Bitmap(res32.Width, res32.Height, PixelFormat.Format24bppRgb);
+ Graphics graphics = Graphics.FromImage(res24);
+ graphics.DrawImage(res32, new Rectangle(0, 0, res32.Width, res32.Height));
+
+ return res24;
+ }
+
+ public static Bitmap ConvertHImageTo8GrayBitmap(this HObject hImage)
+ {
+ try
+ {
+ HTuple type, width, height, pointer;
+ HOperatorSet.GetImagePointer1(hImage, out pointer, out type, out width, out height);
+
+ Bitmap bmp = new Bitmap(width.I, height.I, PixelFormat.Format8bppIndexed);
+ ColorPalette pal = bmp.Palette;
+ for (int i = 0; i <= 255; i++)
+ {
+ pal.Entries[i] = Color.FromArgb(255, i, i, i);
+ }
+ bmp.Palette = pal;
+
+ BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
+
+ if (width % 4 == 0)
+ {
+ CopyMemory(bitmapData.Scan0, (IntPtr)pointer.D, (uint)(bitmapData.Stride * height.I));
+ }
+ else
+ {
+ Parallel.For(0, height.I, h =>
+ {
+ CopyMemory(bitmapData.Scan0 + h * bitmapData.Stride, (IntPtr)(pointer.D + h * width.I), (uint)width.I);
+ });
+ }
+
+ bmp.UnlockBits(bitmapData);
+ return bmp;
+ }
+ catch (Exception ex)
+ {
+ return null;
+ }
+ }
+
+ public static Bitmap ConvertHImageToRGBBitmap(this HObject hImage)
+ {
+ try
+ {
+ HOperatorSet.GetImagePointer3(hImage, out HTuple pointRed, out HTuple pointGreen, out HTuple pointBlue, out HTuple type, out HTuple width, out HTuple height);
+ Bitmap image = new Bitmap(width.I, height.I, PixelFormat.Format24bppRgb);
+ BitmapData imageData = image.LockBits(new Rectangle(0, 0, width.I, height.I), ImageLockMode.ReadWrite, image.PixelFormat);
+ IntPtr pR = (IntPtr)pointRed.D;
+ IntPtr pG = (IntPtr)pointGreen.D;
+ IntPtr pB = (IntPtr)pointBlue.D;
+ Parallel.For(0, imageData.Height, h =>
+ {
+ Parallel.For(0, imageData.Width, w =>
+ {
+ int dest = h * imageData.Stride + w * 3;
+ int source = h * imageData.Width + w;
+
+ Marshal.WriteByte(imageData.Scan0, dest, Marshal.ReadByte(pB, source));
+ Marshal.WriteByte(imageData.Scan0, dest + 1, Marshal.ReadByte(pG, source));
+ Marshal.WriteByte(imageData.Scan0, dest + 2, Marshal.ReadByte(pR, source));
+ });
+ });
+
+ image.UnlockBits(imageData);
+ return image;
+ }
+ catch (Exception exc)
+ {
+ return null;
+ }
+ }
+
+ public static Bitmap ConvertHImageTo16GrayBitmap(this HImage originHImage)
+ {
+ //IntPtr pointer = hImage.GetImagePointer1(out string type, out int width, out int height);
+
+ //int widthIn4 = (int)Math.Ceiling(width / 4.0) * 4;
+
+ ////Bitmap bmp = new Bitmap(widthIn4, height, PixelFormat.Format48bppRgb);
+ //Bitmap showImage = new Bitmap(widthIn4, height, PixelFormat.Format48bppRgb);
+
+ //Rectangle rect = new Rectangle(0, 0, widthIn4, height);
+ ////BitmapData bitmapData = bmp.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format48bppRgb);
+ //BitmapData showImageData = showImage.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format48bppRgb);
+ //unsafe
+ //{
+ // byte* data = (byte*)pointer;
+ // //byte* bitmapBuffer = (byte*)bitmapData.Scan0;
+ // byte* showBitmapBuffer = (byte*)showImageData.Scan0;
+
+ // Parallel.For(0, width * height, i =>
+ // {
+ // int index = (i + 1) % width + widthIn4 * ((int)Math.Floor((double)(i + 1) / width)) - 1;
+
+ // //showBitmapBuffer[index * 6] = bitmapBuffer[index * 6] = data[i * 2];
+ // //showBitmapBuffer[index * 6 + 1] = bitmapBuffer[index * 6 + 1] = data[i * 2 + 1];
+ // showBitmapBuffer[index * 6] = data[i * 2];
+ // showBitmapBuffer[index * 6 + 1] = data[i * 2 + 1];
+ // });
+ //}
+
+ ////bmp.UnlockBits(bitmapData);
+ //showImage.UnlockBits(showImageData);
+
+ //return showImage;
+
+ // dev_set_draw('margin')
+ //read_image(Image, '0.tif')
+
+ HImage hImage = originHImage.Clone();
+
+ //* 如果16位图像非常暗的话,建议在这一步进行提亮,因为后面8位图像大幅度提亮易造成色阶断裂,出现不连续的像素块
+ // * scale_image(Image, Image, 25, 0)
+ //hImage = hImage.ScaleImage(25.0, 0.0);
+
+ //get_domain(Image, rectangle)
+ //* 获取全图中像素灰度值的最大和最小值
+ //min_max_gray(rectangle, Image, 0, Min, Max, range)
+ hImage.MinMaxGray(hImage.GetDomain(), 0, out double min, out double max, out double range);
+
+ //* 将16位图的灰度值映射到0 - 255上
+ double mult = 255.0 / (max - min);
+ double add = -mult * min;
+ hImage = hImage.ScaleImage(mult, add);
+
+ //* 转换为'byte'类型
+ //convert_image_type(Image_scaled, ImageConverted, 'byte')
+ hImage = hImage.ConvertImageType("byte");
+
+ Bitmap showImage = hImage.ConvertHImageTo8GrayBitmap();
+
+ hImage.Dispose();
+
+ return showImage;
+
+ //* 如果转换以后图像整体对比度太低的话,可以提高对比度(这里是对8位图像处理)
+ //Min:= 20
+ //Max:= 160
+ //Mult:= 255.0 / (Max - Min)
+ //Add:= -Mult * Min
+ //scale_image(ImageConverted, ImageConverted_scaled, Mult, Add)
+ }
+
+ public static List HTupleToDouble(this HTuple tuple)
+ {
+ List list = new List();
+
+ for (int i = 0; i < tuple.Length; i++)
+ {
+ list.Add(tuple[i].D);
+ }
+
+ return list;
+ }
+
+
+
+
+ public static HImage ConvertHObjectToHImage(this HObject obj)
+ {
+ HOperatorSet.CountChannels(obj, out HTuple channels);
+
+ HImage img = new HImage();
+ if (channels.I == 1)
+ {
+ HTuple pointer, type, width, height;
+ HOperatorSet.GetImagePointer1(obj, out pointer, out type, out width, out height);
+
+ img.GenImage1(type, width, height, pointer);
+ }
+ else
+ {
+ HTuple pRed, pGreen, pBlue, type, width, height;
+ HOperatorSet.GetImagePointer3(obj, out pRed, out pGreen, out pBlue, out type, out width, out height);
+
+ img.GenImage3(type, width, height, pRed, pGreen, pBlue);
+ }
+
+ return img;
+ }
+
+ #region 灰度图转换为伪彩图
+ public static Bitmap ConvertGrayImageToPesudoColorfulImage(this HImage hImage, double max = 0, double min = 0, double zoom = 1, bool isShowHeightTip = false, int zResolution = 100000)
+ {
+ hImage.GetImageSize(out int width, out int height);
+ hImage.MinMaxGray(new HRegion(0.0, 0.0, width, height), 3, out HTuple roiMin, out HTuple roiMax, out _);
+
+ if (max == 0)
+ {
+ max = roiMax;
+ }
+
+ if (min == 0)
+ {
+ min = roiMin;
+ }
+
+ double mult = 235 / (zoom * (max - min));
+ double add = (0 - mult) * min * zoom + 10;
+ HOperatorSet.ScaleImage(hImage, out HObject imageScaled, mult, add);
+ HOperatorSet.ConvertImageType(imageScaled, out imageScaled, "byte");
+ Stopwatch sw = new Stopwatch();
+ sw.Start();
+
+ HOperatorSet.GetImagePointer1(imageScaled, out HTuple pointer, out HTuple type, out _, out _);
+ Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
+ BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
+
+ unsafe
+ {
+ byte* data = (byte*)(IntPtr)pointer;
+ byte* bitmapDataBuff = (byte*)bitmapData.Scan0;
+
+ if (width % 4 != 0)
+ {
+ Parallel.For(0, height, h =>
+ {
+ Parallel.For(0, width, w =>
+ {
+ byte gray = data[h * width + w];
+ byte[] convertBytes = ConvertByteToColorfulArray(gray);
+
+ Marshal.Copy(convertBytes, 0, (IntPtr)(bitmapDataBuff + h * bitmapData.Stride + w * 3), 3);
+ });
+ });
+ }
+ else
+ {
+ Parallel.For(0, width * height, i =>
+ {
+ byte gray = data[i];
+ byte[] convertBytes = ConvertByteToColorfulArray(gray);
+
+ Marshal.Copy(convertBytes, 0, (IntPtr)(bitmapDataBuff + i * 3), 3);
+ });
+ }
+ }
+ bitmap.UnlockBits(bitmapData);
+
+ if (isShowHeightTip)
+ {
+ List lableList = new List() { 5, 30, 60, 90, 120, 150, 180, 210, 240, 255 };
+ Dictionary lableColorDict = lableList.ToDictionary(
+ u => (u - add) / (mult * zResolution),
+ u =>
+ {
+ byte[] colorBytes = ConvertByteToColorfulArray(u);
+ return Color.FromArgb(colorBytes[2], colorBytes[1], colorBytes[0]);
+ });
+
+ using (Graphics g = Graphics.FromImage(bitmap))
+ {
+ int rectHeight = (int)(bitmap.Height / (5.0 * lableColorDict.Count));
+ Font font = new Font("宋体", (int)(rectHeight * 0.75), GraphicsUnit.Pixel);
+
+ string lable = lableColorDict.ElementAt(0).Key.ToString("f3");
+ SizeF lableSize = g.MeasureString(lable, font);
+ int rectWidth = (int)(lableSize.Width * 1.5);
+
+ int startX = 0;
+ int startY = 0;
+ foreach (KeyValuePair pair in lableColorDict)
+ {
+ g.FillRectangle(new SolidBrush(pair.Value), startX, startY, rectWidth, rectHeight);
+ g.DrawString(pair.Key.ToString("f3"), font, new SolidBrush(Color.White), (float)(startX + (rectWidth - lableSize.Width) / 2.0), (float)(startY + (rectHeight - lableSize.Height) / 2.0));
+
+ startY += rectHeight;
+ }
+ }
+ }
+
+ sw.Stop();
+ //LogAsync(DateTime.Now, EnumHelper.LogLevel.Information, $"转换耗时{sw.ElapsedMilliseconds}ms");
+ return bitmap;
+ }
+
+ private static byte[] ConvertByteToColorfulArray(byte gray)
+ {
+ byte[] bytes = new byte[3];
+ if (gray == 0)
+ {
+ bytes[2] = 255;
+ bytes[1] = 255;
+ bytes[0] = 255;
+ }
+ if (gray > 0 && gray <= 63)
+ {
+ bytes[2] = 0;
+ bytes[+1] = (byte)(254 - 4 * gray);
+ bytes[0] = 255;
+ }
+ if (gray >= 64 && gray <= 127)
+ {
+ bytes[2] = 0;
+ bytes[1] = (byte)(4 * gray - 254);
+ bytes[0] = (byte)(510 - 4 * gray);
+ }
+ if (gray >= 128 && gray <= 191)
+ {
+ bytes[2] = (byte)(4 * gray - 510);
+ bytes[1] = 255;
+ bytes[0] = 0;
+ }
+ if (gray >= 192 && gray <= 255)
+ {
+ bytes[2] = 255;
+ bytes[1] = (byte)(1022 - 4 * gray);
+ bytes[0] = 0;
+ }
+
+ return bytes;
+ }
+ #endregion
+ }
+}
diff --git a/DH.Commons/Helper/OpenCVEngineTool.cs b/DH.Commons/Helper/OpenCVEngineTool.cs
new file mode 100644
index 0000000..86e5aff
--- /dev/null
+++ b/DH.Commons/Helper/OpenCVEngineTool.cs
@@ -0,0 +1,724 @@
+using HalconDotNet;
+using OpenCvSharp;
+using OpenCvSharp.Extensions;
+using System;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+
+namespace XKRS.Common.Model
+{
+ public class OpenCVEngineTool : IDisposable
+ {
+ public void Dispose()
+ {
+ throw new NotImplementedException();
+ }
+
+
+ }
+
+
+ public static class OpenCVHelper
+ {
+ [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
+ public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
+
+
+ public static byte[] MatToBytes(this Mat image)
+ {
+ if (image != null && image.Data != IntPtr.Zero)
+ {
+ int size = (int)(image.Total() * image.ElemSize());
+ byte[] bytes = new byte[size];
+ Marshal.Copy(image.Data, bytes, 0, size);
+ return bytes;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ ///
+ /// 获取水平拼接图片
+ ///
+ ///
+ ///
+ ///
+ public static Bitmap GetHConcatImage(Bitmap map1, Bitmap map2)
+ {
+ var mat1 = map1.ToMat();
+ var mat2 = map2.ToMat();
+ //var maxChannel = Math.Max(mat1.Channels(), mat2.Channels());
+ //var maxType = Math.Max(mat1.Type(), mat2.Type());
+
+ //转通道数
+ mat1 = mat1.CvtColor(ColorConversionCodes.GRAY2BGRA);
+ //转位深
+ mat1.ConvertTo(mat1, mat2.Type());
+ Mat resMat = new Mat(mat1.Height, mat1.Width, mat2.Type(), new Scalar(0));
+ Cv2.HConcat(mat1, mat2, resMat);
+ mat1.Dispose();
+ mat2.Dispose();
+ return resMat.ToBitmap();
+ }
+
+ public static Mat To3Channels(this Mat img)
+ {
+ if (img == null)
+ return null;
+ Mat resMat = new Mat(img.Rows, img.Cols, MatType.CV_8UC3);
+ Mat[] channels = new Mat[3]; ;
+ for (int i = 0; i < 3; i++)
+ {
+ channels[i] = img;
+ }
+ Cv2.Merge(channels, resMat);
+ img.Dispose();
+ img = null;
+ return resMat;
+ }
+ ///
+ /// 把OpenCV图像转换到Halcon图像
+ ///
+ /// OpenCV图像_Mat
+ /// Halcon图像_HObject
+ public static HObject MatToHImage(Mat mImage)
+ {
+ try
+ {
+ HObject hImage;
+ int matChannels = 0; // 通道数
+ Type matType = null;
+ uint width, height; // 宽,高
+ width = height = 0; // 宽,高初始化
+
+ // 获取通道数
+ matChannels = mImage.Channels();
+ if (matChannels == 0)
+ {
+ return null;
+ }
+ if (matChannels == 1) // 单通道
+ //if (true) // 单通道
+ {
+ IntPtr ptr; // 灰度图通道
+ Mat[] mats = mImage.Split();
+
+ // 改自:Mat.GetImagePointer1(mImage, out ptr, out matType, out width, out height); // ptr=2157902018096 cType=byte width=830 height=822
+ ptr = mats[0].Data; // 取灰度图值
+ matType = mImage.GetType(); // byte
+ height = (uint)mImage.Rows; // 高
+ width = (uint)mImage.Cols; // 宽
+
+ // 改自:hImage = new HObject(new OpenCvSharp.Size(width, height), MatType.CV_8UC1, newScalar(0));
+ byte[] dataGrayScaleImage = new byte[width * height]; //Mat dataGrayScaleImage = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1);
+
+ unsafe
+ {
+ fixed (byte* ptrdata = dataGrayScaleImage)
+ {
+
+ #region 按行复制
+ //for (int i = 0; i < height; i++)
+ //{
+ // CopyMemory((IntPtr)(ptrdata + width * i), new IntPtr((long)ptr + width *i), width);
+ //}
+
+ #endregion
+
+ CopyMemory((IntPtr)ptrdata, new IntPtr((long)ptr), width * height);
+ HOperatorSet.GenImage1(out hImage, "byte", width, height, (IntPtr)ptrdata);
+
+ }
+ }
+ return hImage;
+ }
+ else if (matChannels == 3) // 三通道
+ {
+ IntPtr ptrRed; // R通道图
+ IntPtr ptrGreen; // G通道图
+ IntPtr ptrBlue; // B通道图
+ Mat[] mats = mImage.Split();
+
+ ptrRed = mats[0].Data; // 取R通道值
+ ptrGreen = mats[1].Data; // 取G通道值
+ ptrBlue = mats[2].Data; // 取B通道值
+ matType = mImage.GetType(); // 类型
+ height = (uint)mImage.Rows; // 高
+ width = (uint)mImage.Cols; // 宽
+
+ // 改自:hImage = new HObject(new OpenCvSharp.Size(width, height), MatType.CV_8UC1, new Scalar(0));
+ byte[] dataRed = new byte[width * height]; //Mat dataGrayScaleImage = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1);
+ byte[] dataGreen = new byte[width * height];
+ byte[] dataBlue = new byte[width * height];
+
+ unsafe
+ {
+ fixed (byte* ptrdataRed = dataRed, ptrdataGreen = dataGreen, ptrdataBlue = dataBlue)
+ {
+
+ #region 按行复制
+ //HImage himg = new HImage("byte", width, height, (IntPtr)ptrdataRed);
+ //for (int i = 0; i < height; i++)
+ //{
+ // CopyMemory((IntPtr)(ptrdataRed + width * i), new IntPtr((long)ptrRed +width * i), width);
+ // CopyMemory((IntPtr)(ptrdataGreen + width * i), new IntPtr((long)ptrGreen+ width * i), width);
+ // CopyMemory((IntPtr)(ptrdataBlue + width * i), new IntPtr((long)ptrBlue +width * i), width);
+ //}
+
+ #endregion
+
+ CopyMemory((IntPtr)ptrdataRed, new IntPtr((long)ptrRed), width* height); // 复制R通道
+ CopyMemory((IntPtr)ptrdataGreen, new IntPtr((long)ptrGreen), width * height); // 复制G通道
+ CopyMemory((IntPtr)ptrdataBlue, new IntPtr((long)ptrBlue), width * height); // 复制B通道
+ HOperatorSet.GenImage3(out hImage, "byte", width, height, (IntPtr)ptrdataRed, (IntPtr)ptrdataGreen, (IntPtr)ptrdataBlue); // 合成
+ }
+ }
+ return hImage;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ catch (Exception ex)
+ {
+ throw ex;
+ }
+
+ }
+
+
+
+
+
+ public static Mat HImageToMat(this HObject hobj)
+ {
+ try
+ {
+ Mat mImage;
+ HTuple htChannels;
+ HTuple cType = null;
+ HTuple width, height;
+ width = height = 0;
+
+ HOperatorSet.CountChannels(hobj, out htChannels);
+
+ if (htChannels.Length == 0)
+ {
+ return null;
+ }
+ if (htChannels[0].I == 1)
+ {
+ HTuple ptr;
+ HOperatorSet.GetImagePointer1(hobj, out ptr, out cType, out width, out height);
+ mImage = new Mat(height, width, MatType.CV_8UC1, new Scalar(0));
+
+ unsafe
+ {
+ CopyMemory(mImage.Data, new IntPtr((byte*)ptr.IP), (uint)(width * height));// CopyMemory(要复制到的地址,复制源的地址,复制的长度)
+ }
+
+ return mImage;
+ }
+ else if (htChannels[0].I == 3)
+ {
+ HTuple ptrRed;
+ HTuple ptrGreen;
+ HTuple ptrBlue;
+
+ HOperatorSet.GetImagePointer3(hobj, out ptrRed, out ptrGreen, out ptrBlue, out cType, out width, out height);
+ Mat pImageRed = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1);
+ Mat pImageGreen = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1);
+ Mat pImageBlue = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1);
+ mImage = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC3, new Scalar(0, 0, 0));
+ unsafe
+ {
+ CopyMemory(pImageRed.Data, new IntPtr((byte*)ptrRed.IP), (uint)(width * height)); // CopyMemory(要复制到的地址,复制源的地址,复制的长度)_Red
+ CopyMemory(pImageGreen.Data, new IntPtr((byte*)ptrGreen.IP), (uint)(width * height)); // CopyMemory(要复制到的地址,复制源的地址,复制的长度)_Green
+ CopyMemory(pImageBlue.Data, new IntPtr((byte*)ptrBlue.IP), (uint)(width * height)); // CopyMemory(要复制到的地址,复制源的地址,复制的长度)_Blue
+
+ }
+ Mat[] multi = new Mat[] { pImageBlue, pImageGreen, pImageRed };
+ Cv2.Merge(multi, mImage);
+ pImageRed.Dispose();
+ pImageRed = null;
+ pImageGreen.Dispose();
+ pImageGreen = null;
+ pImageBlue.Dispose();
+ pImageBlue = null;
+ return mImage;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ catch (Exception ex)
+ {
+ throw ex;
+ }
+ }
+
+ ///
+ /// 从内存流中指定位置,读取数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static int ReadData(MemoryStream curStream, int startPosition, int length)
+ {
+ int result = -1;
+
+ byte[] tempData = new byte[length];
+ curStream.Position = startPosition;
+ curStream.Read(tempData, 0, length);
+ result = BitConverter.ToInt32(tempData, 0);
+
+ return result;
+ }
+
+ ///
+ /// 使用byte[]数据,生成三通道 BMP 位图
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Bitmap CreateColorBitmap(byte[] originalImageData, int originalWidth, int originalHeight, byte[] color_map)
+ {
+ // 指定8位格式,即256色
+ Bitmap resultBitmap = new Bitmap(originalWidth, originalHeight, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
+
+ // 将该位图存入内存中
+ MemoryStream curImageStream = new MemoryStream();
+ resultBitmap.Save(curImageStream, System.Drawing.Imaging.ImageFormat.Bmp);
+ curImageStream.Flush();
+
+ // 由于位图数据需要DWORD对齐(4byte倍数),计算需要补位的个数
+ int curPadNum = ((originalWidth * 8 + 31) / 32 * 4) - originalWidth;
+
+ // 最终生成的位图数据大小
+ int bitmapDataSize = ((originalWidth * 8 + 31) / 32 * 4) * originalHeight;
+
+ // 数据部分相对文件开始偏移,具体可以参考位图文件格式
+ int dataOffset = ReadData(curImageStream, 10, 4);
+
+
+ // 改变调色板,因为默认的调色板是32位彩色的,需要修改为256色的调色板
+ int paletteStart = 54;
+ int paletteEnd = dataOffset;
+ int color = 0;
+
+ for (int i = paletteStart; i < paletteEnd; i += 4)
+ {
+ byte[] tempColor = new byte[4];
+ tempColor[0] = (byte)color;
+ tempColor[1] = (byte)color;
+ tempColor[2] = (byte)color;
+ tempColor[3] = (byte)0;
+ color++;
+
+ curImageStream.Position = i;
+ curImageStream.Write(tempColor, 0, 4);
+ }
+
+ // 最终生成的位图数据,以及大小,高度没有变,宽度需要调整
+ byte[] destImageData = new byte[bitmapDataSize];
+ int destWidth = originalWidth + curPadNum;
+
+ // 生成最终的位图数据,注意的是,位图数据 从左到右,从下到上,所以需要颠倒
+ for (int originalRowIndex = originalHeight - 1; originalRowIndex >= 0; originalRowIndex--)
+ {
+ int destRowIndex = originalHeight - originalRowIndex - 1;
+
+ for (int dataIndex = 0; dataIndex < originalWidth; dataIndex++)
+ {
+ // 同时还要注意,新的位图数据的宽度已经变化destWidth,否则会产生错位
+ destImageData[destRowIndex * destWidth + dataIndex] = originalImageData[originalRowIndex * originalWidth + dataIndex];
+ }
+ }
+
+ // 将流的Position移到数据段
+ curImageStream.Position = dataOffset;
+
+ // 将新位图数据写入内存中
+ curImageStream.Write(destImageData, 0, bitmapDataSize);
+
+ curImageStream.Flush();
+
+ // 将内存中的位图写入Bitmap对象
+ resultBitmap = new Bitmap(curImageStream);
+
+ resultBitmap = Convert8to24(resultBitmap, color_map); // 转为3通道图像
+
+ return resultBitmap;
+ }
+
+ // 实现单通道到多通道
+ public static Bitmap Convert8to24(this Bitmap bmp, byte[] color_map)
+ {
+
+ Rectangle rect = new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height);
+ BitmapData bitmapData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);
+
+ //计算实际8位图容量
+ int size8 = bitmapData.Stride * bmp.Height;
+ byte[] grayValues = new byte[size8];
+
+ //// 申请目标位图的变量,并将其内存区域锁定
+ Bitmap TempBmp = new Bitmap(bmp.Width, bmp.Height, PixelFormat.Format24bppRgb);
+ BitmapData TempBmpData = TempBmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
+
+
+ //// 获取图像参数以及设置24位图信息
+ int stride = TempBmpData.Stride; // 扫描线的宽度
+ int offset = stride - TempBmp.Width; // 显示宽度与扫描线宽度的间隙
+ IntPtr iptr = TempBmpData.Scan0; // 获取bmpData的内存起始位置
+ int scanBytes = stride * TempBmp.Height;// 用stride宽度,表示这是内存区域的大小
+
+ // 下面把原始的显示大小字节数组转换为内存中实际存放的字节数组
+ byte[] pixelValues = new byte[scanBytes]; //为目标数组分配内存
+ System.Runtime.InteropServices.Marshal.Copy(bitmapData.Scan0, grayValues, 0, size8);
+
+ for (int i = 0; i < bmp.Height; i++)
+ {
+
+ for (int j = 0; j < bitmapData.Stride; j++)
+ {
+
+ if (j >= bmp.Width)
+ continue;
+
+ int indexSrc = i * bitmapData.Stride + j;
+ int realIndex = i * TempBmpData.Stride + j * 3;
+
+ // color_id:就是预测出来的结果
+ int color_id = (int)grayValues[indexSrc] % 256;
+
+ if (color_id == 0) // 分割中类别1对应值1,而背景往往为0,因此这里就将背景置为[0, 0, 0]
+ {
+ // 空白
+ pixelValues[realIndex] = 0;
+ pixelValues[realIndex + 1] = 0;
+ pixelValues[realIndex + 2] = 0;
+ }
+ else
+ {
+ // 替换为color_map中的颜色值
+ pixelValues[realIndex] = color_map[color_id * 3];
+ pixelValues[realIndex + 1] = color_map[color_id * 3 + 1];
+ pixelValues[realIndex + 2] = color_map[color_id * 3 + 2];
+ }
+ }
+ }
+
+ //Parallel.For(0, width * height, i =>
+ // {
+ // int index = (i + 1) % width + widthIn4 * ((i + 1) / width) - 1;
+
+ // showBitmapBuffer[index * 6] = bitmapBuffer[index * 6] = data[i * 2];
+ // showBitmapBuffer[index * 6 + 1] = bitmapBuffer[index * 6 + 1] = data[i * 2 + 1];
+ // });
+
+ // 用Marshal的Copy方法,将刚才得到的内存字节数组复制到BitmapData中
+ Marshal.Copy(pixelValues, 0, iptr, scanBytes);
+ TempBmp.UnlockBits(TempBmpData); // 解锁内存区域
+ bmp.UnlockBits(bitmapData);
+ return TempBmp;
+ }
+
+
+ // 获取伪彩色图的RGB值 -- 同时也是适用于检测框分类颜色
+ public static byte[] GetColorMap(int num_classes = 256)
+ {
+ num_classes += 1;
+ byte[] color_map = new byte[num_classes * 3];
+ for (int i = 0; i < num_classes; i++)
+ {
+ int j = 0;
+ int lab = i;
+ while (lab != 0)
+ {
+ color_map[i * 3] |= (byte)(((lab >> 0) & 1) << (7 - j));
+ color_map[i * 3 + 1] |= (byte)(((lab >> 1) & 1) << (7 - j));
+ color_map[i * 3 + 2] |= (byte)(((lab >> 2) & 1) << (7 - j));
+
+ j += 1;
+ lab >>= 3;
+ }
+ }
+
+ // 去掉底色
+ color_map = color_map.Skip(3).ToArray();
+ return color_map;
+ }
+
+ // GetGrayMap
+ public static byte[] GetGrayMap(int num_classes = 256)
+ {
+ byte[] color_map = new byte[num_classes];
+ for (int i = 0; i < num_classes; i++)
+ {
+ if (i <= 100)
+ color_map[i] = 0;
+ if (i > 100 && i <= 200)
+ color_map[i] = 100;
+ if (i > 200)
+ color_map[i] = 255;
+
+ }
+ return color_map;
+ }
+ ///
+ /// 像素点阵转换为bitmap 二值化图
+ ///
+ /// byte[]数组
+ /// 图片的宽度
+ /// 图片的高度
+ /// bitmap图片
+ public static Bitmap CreateBinaryBitmap(byte[] rawValues, int width, int height)
+ {
+ Bitmap bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
+ BitmapData bmpData = bmp.LockBits(new System.Drawing.Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
+ //获取图像参数
+ int stride = bmpData.Stride; // 扫描线的宽度
+ int offset = stride - width; // 显示宽度与扫描线宽度的间隙
+ IntPtr iptr = bmpData.Scan0; // 获取bmpData的内存起始位置
+ int scanBytes = stride * height;// 用stride宽度,表示这是内存区域的大小
+ //下面把原始的显示大小字节数组转换为内存中实际存放的字节数组
+ int posScan = 0, posReal = 0;// 分别设置两个位置指针,指向源数组和目标数组
+ byte[] pixelValues = new byte[scanBytes]; //为目标数组分配内存
+ for (int x = 0; x < height; x++)
+ {
+ //下面的循环节是模拟行扫描
+ for (int y = 0; y < width; y++)
+ {
+ pixelValues[posScan++] = rawValues[posReal++] == 0 ? (byte)0 : (byte)255;
+ }
+ posScan += offset; //行扫描结束,要将目标位置指针移过那段“间隙”
+ }
+ //用Marshal的Copy方法,将刚才得到的内存字节数组复制到BitmapData中
+ Marshal.Copy(pixelValues, 0, iptr, scanBytes);
+ bmp.UnlockBits(bmpData); // 解锁内存区域
+ //下面的代码是为了修改生成位图的索引表,从伪彩修改为灰度
+ ColorPalette tempPalette;
+ using (Bitmap tempBmp = new Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format8bppIndexed))
+ {
+ tempPalette = tempBmp.Palette;
+ }
+ for (int i = 0; i < 256; i++)
+ {
+ tempPalette.Entries[i] = System.Drawing.Color.FromArgb(i, i, i);
+ }
+
+ bmp.Palette = tempPalette;
+
+ return bmp;
+ }
+
+ ///
+ /// 像素点阵转换为bitmap灰度图
+ ///
+ /// byte[]数组
+ /// 图片的宽度
+ /// 图片的高度
+ /// bitmap图片
+ public static Bitmap CreateGrayBitmap(byte[] rawValues, int width, int height)
+ {
+ Bitmap bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
+ BitmapData bmpData = bmp.LockBits(new System.Drawing.Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
+ //获取图像参数
+ int stride = bmpData.Stride; // 扫描线的宽度
+ int offset = stride - width; // 显示宽度与扫描线宽度的间隙
+ IntPtr iptr = bmpData.Scan0; // 获取bmpData的内存起始位置
+ int scanBytes = stride * height;// 用stride宽度,表示这是内存区域的大小
+ //下面把原始的显示大小字节数组转换为内存中实际存放的字节数组
+ int posScan = 0, posReal = 0;// 分别设置两个位置指针,指向源数组和目标数组
+ byte[] pixelValues = new byte[scanBytes]; //为目标数组分配内存
+ for (int x = 0; x < height; x++)
+ {
+ //下面的循环节是模拟行扫描
+ for (int y = 0; y < width; y++)
+ {
+ pixelValues[posScan++] = rawValues[posReal++];
+ }
+ posScan += offset; //行扫描结束,要将目标位置指针移过那段“间隙”
+ }
+ //用Marshal的Copy方法,将刚才得到的内存字节数组复制到BitmapData中
+ Marshal.Copy(pixelValues, 0, iptr, scanBytes);
+ bmp.UnlockBits(bmpData); // 解锁内存区域
+ //下面的代码是为了修改生成位图的索引表,从伪彩修改为灰度
+ ColorPalette tempPalette;
+ using (Bitmap tempBmp = new Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format8bppIndexed))
+ {
+ tempPalette = tempBmp.Palette;
+ }
+ for (int i = 0; i < 256; i++)
+ {
+ tempPalette.Entries[i] = System.Drawing.Color.FromArgb(i, i, i);
+ }
+
+ bmp.Palette = tempPalette;
+
+ return bmp;
+ }
+
+
+ //分别基于像素(GetPixel和SetPixel)、基于内存、基于指针这三种方法增强图片对比度。
+ // 第一种方法:像素提取法。速度慢 基于像素:400-600ms
+ public static Bitmap MethodBaseOnPixel(Bitmap bitmap, int degree)
+ {
+ Color curColor;
+ int grayR, grayG, grayB;
+
+ double Deg = (100.0 + degree) / 100.0;
+ for (int i = 0; i < bitmap.Width; i++)
+ {
+ for (int j = 0; j < bitmap.Height; j++)
+ {
+ curColor = bitmap.GetPixel(i, j);
+ grayR = Convert.ToInt32((((curColor.R / 255.0 - 0.5) * Deg + 0.5)) * 255);
+ grayG = Convert.ToInt32((((curColor.G / 255.0 - 0.5) * Deg + 0.5)) * 255);
+ grayB = Convert.ToInt32((((curColor.B / 255.0 - 0.5) * Deg + 0.5)) * 255);
+ if (grayR < 0)
+ grayR = 0;
+ else if (grayR > 255)
+ grayR = 255;
+
+ if (grayB < 0)
+ grayB = 0;
+ else if (grayB > 255)
+ grayB = 255;
+
+ if (grayG < 0)
+ grayG = 0;
+ else if (grayG > 255)
+ grayG = 255;
+
+ bitmap.SetPixel(i, j, Color.FromArgb(grayR, grayG, grayB));
+ }
+ }
+
+ return bitmap;
+ }
+
+ // 第二种方法:基于内存 17-18ms
+ public static unsafe Bitmap MethodBaseOnMemory(Bitmap bitmap, int degree)
+ {
+ if (bitmap == null)
+ {
+ return null;
+ }
+ double Deg = (100.0 + degree) / 100.0;
+
+ int width = bitmap.Width;
+ int height = bitmap.Height;
+
+ int length = height * 3 * width;
+ byte[] RGB = new byte[length];
+
+ BitmapData data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
+
+ System.IntPtr Scan0 = data.Scan0;
+ System.Runtime.InteropServices.Marshal.Copy(Scan0, RGB, 0, length);
+
+ double gray = 0;
+ for (int i = 0; i < RGB.Length; i += 3)
+ {
+ for (int j = 0; j < 3; j++)
+ {
+ gray = (((RGB[i + j] / 255.0 - 0.5) * Deg + 0.5)) * 255.0;
+ if (gray > 255)
+ gray = 255;
+
+ if (gray < 0)
+ gray = 0;
+ RGB[i + j] = (byte)gray;
+ }
+ }
+
+ System.Runtime.InteropServices.Marshal.Copy(RGB, 0, Scan0, length);// 此处Copy是之前Copy的逆操作
+ bitmap.UnlockBits(data);
+ return bitmap;
+ }
+
+ //第三种方法:基于指针 20-23ms
+ public static unsafe Bitmap MethodBaseOnPtr(Bitmap b, int degree)
+ {
+ if (b == null)
+ {
+ return null;
+ }
+ try
+ {
+ double num = 0.0;
+ double num2 = (100.0 + degree) / 100.0;
+ num2 *= num2;
+ int width = b.Width;
+ int height = b.Height;
+ BitmapData bitmapdata = b.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
+ byte* numPtr = (byte*)bitmapdata.Scan0;
+
+ int offset = bitmapdata.Stride - (width * 3);
+ for (int i = 0; i < height; i++)
+ {
+ for (int j = 0; j < width; j++)
+ {
+ for (int k = 0; k < 3; k++)
+ {
+ num = ((((((double)numPtr[k]) / 255.0) - 0.5) * num2) + 0.5) * 255.0;
+ if (num < 0.0)
+ {
+ num = 0.0;
+ }
+ if (num > 255.0)
+ {
+ num = 255.0;
+ }
+ numPtr[k] = (byte)num;
+ }
+ numPtr += 3;
+
+ }
+ numPtr += offset;
+ }
+ b.UnlockBits(bitmapdata);
+ return b;
+ }
+ catch
+ {
+ return b;
+ }
+ }
+
+ public static double GetRoiArae(Mat src, Rect rect)
+ {
+ //初始面积为0
+ double Area = 0;
+ //获取感兴趣区域
+ src = src[rect];
+ //转为单通道
+ Mat gray = src.CvtColor(ColorConversionCodes.BGR2GRAY);
+ //二值化
+ Mat binary = gray.Threshold(0, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary);
+
+ //求轮廓 不连通会有多个闭合区域
+ OpenCvSharp.Point[][] contours;
+ HierarchyIndex[] hierarchy;
+ Cv2.FindContours(binary, out contours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxSimple);
+ for (int i = 0; i < contours.Count(); i++)
+ {
+ //所有面积相加
+ Area += Cv2.ContourArea(contours[i], false);
+ }
+ return Area;
+ }
+ }
+}
diff --git a/DH.Devices.Motion/MCDLL_NET_Code.cs b/DH.Devices.Motion/MCDLL_NET_Code.cs
index 080e5cb..67c8885 100644
--- a/DH.Devices.Motion/MCDLL_NET_Code.cs
+++ b/DH.Devices.Motion/MCDLL_NET_Code.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace XKRS.Device.SolidMotionCard
+namespace DH.Devices.Motion
{
public enum FuncRet
diff --git a/DH.Devices.Motion/MotionBase.cs b/DH.Devices.Motion/MotionBase.cs
index 9540fe6..9e8810c 100644
--- a/DH.Devices.Motion/MotionBase.cs
+++ b/DH.Devices.Motion/MotionBase.cs
@@ -73,7 +73,7 @@ namespace DH.Devices.Motion
[Category("机台配置")]
[DisplayName("机台类型")]
[Description("机台类型")]
- public MachineDiskType MachineDiskType { get; set; } = MachineDiskType.DoubleDisk;
+ public MachineDiskType MachineDiskType { get; set; } = MachineDiskType.SingleDisk;
@@ -111,12 +111,12 @@ namespace DH.Devices.Motion
[DisplayName("输出IO总数")]
public int OutputNums { get; set; } = 16;
- //[Category("IO配置")]
- //[DisplayName("IO定义集合")]
- //[Description("IO定义集合")]
+ [Category("IO配置")]
+ [DisplayName("IO定义集合")]
+ [Description("IO定义集合")]
//[TypeConverter(typeof(CollectionCountConvert))]
- //[Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))]
- //public List IODefinitionCollection { get; set; } = new List();
+ // [Editor(typeof(ComplexCollectionEditor), typeof(UITypeEditor))]
+ public List IODefinitionCollection { get; set; } = new List();
[Category("IO配置")]
[DisplayName("是否信号模式")]
@@ -194,35 +194,35 @@ namespace DH.Devices.Motion
public List BlowSettings { get; set; } = new List();
- //[Category("筛选配置")]
- //[DisplayName("转盘运转方向")]
- //[Description("转盘运转方向,顺时针或逆时针")]
+ [Category("筛选配置")]
+ [DisplayName("转盘运转方向")]
+ [Description("转盘运转方向,顺时针或逆时针")]
//[TypeConverter(typeof(EnumDescriptionConverter))]
- //public RotationDirectionEnum MotionDir { get; set; } = RotationDirectionEnum.Clockwise;
+ public RotationDirectionEnum MotionDir { get; set; } = RotationDirectionEnum.Clockwise;
[Category("筛选配置")]
[DisplayName("物料尺寸最大值")]
[Description("物料尺寸最大值,单位:脉冲")]
- public uint PieceMaxSize { get; set; } = 2000;
+ public uint PieceMaxSize { get; set; } = 20000;
[Category("筛选配置")]
[DisplayName("物料尺寸最小值")]
[Description("物料尺寸最小值,单位:脉冲")]
- public uint PieceMinSize { get; set; } = 1500;
+ public uint PieceMinSize { get; set; } = 10;
[Category("筛选配置")]
[DisplayName("物料最小间隔")]
[Description("物料最小间隔,单位:脉冲")]
- public uint MinDistance { get; set; } = 2000;
+ public uint MinDistance { get; set; } = 10;
[Category("筛选配置")]
[DisplayName("两个物料之间触发最小间隔时间")]
[Description("两个物料之间触发最小间隔时间,单位:ms")]
- public uint MinTimeInterval { get; set; } = 10;
+ public uint MinTimeInterval { get; set; } = 1;
@@ -550,7 +550,7 @@ namespace DH.Devices.Motion
[Category("回原点参数")]
[DisplayName("回原点方式")]
[Description("HomeMode:回原点方式")]
- public GoHomeMode HomeMode { get; set; } = GoHomeMode.Negative_Ne_Center_H_Positive_N_Stop_HNeO_Offset_Po;
+ public GoHomeMode HomeMode { get; set; } = GoHomeMode.Negative_Ne_Center_H_Positive_N_Index_HPoO_Offset_Po;
[Category("回原点参数")]
diff --git a/DH.Devices.Motion/SLDMotion.cs b/DH.Devices.Motion/SLDMotion.cs
index 5b20630..bc504fd 100644
--- a/DH.Devices.Motion/SLDMotion.cs
+++ b/DH.Devices.Motion/SLDMotion.cs
@@ -2,9 +2,10 @@
using DH.Devices.Motion;
using MCDLL_NET;
using System.Diagnostics;
+using static System.Collections.Specialized.BitVector32;
-namespace XKRS.Device.SolidMotionCard
+namespace DH.Devices.Motion
{
@@ -150,22 +151,32 @@ namespace XKRS.Device.SolidMotionCard
.ToDictionary(a => a.AxisIndex, a => new ManualResetEvent(true));
// 初始化时关闭所有轴,停止筛选 begin =======
- AllMoveStop();
- AllAxisOff();
+ //AllMoveStop();
+
+ // CMCDLL_NET.MCF_Axis_Stop_Net(0, AxisStopMode.AxisStopIMD, 0);
+
+ //CMCDLL_NET.MCF_Set_Axis_Stop_Profile_Net(0, 50000, 0, 0, 0);
+ // CMCDLL_NET.MCF_Axis_Stop_Net(0, AxisStopMode.AxisStopDEC, 0);
+ AxisStop();
+ //AllAxisOff();
+ var ret = CMCDLL_NET.MCF_Set_Servo_Enable_Net(0, (ushort)ServoLogic.Servo_Open, 0);
StopSorting();
// 初始化时关闭所有轴,停止筛选 end =======
- AllAxisOn();
+ //AllAxisOn();
Start();
MonitorPosition();
MonitorAxisStatus();
- MonitorPieces();
+
CustomStart();
+
+
+ MonitorPieces();
isconnected = true;
-
+
}
catch
{
@@ -409,8 +420,10 @@ namespace XKRS.Device.SolidMotionCard
public override void Stop()
{
//base.Stop();
- AllMoveStop();
- AllAxisOff();
+ AxisStop();
+ int ret = CMCDLL_NET.MCF_Set_Servo_Enable_Net(0, (ushort)ServoLogic.Servo_Open, 0);
+
+ // AllAxisOff();
for (ushort station = 0; station < BoardCount; station++)
{
@@ -849,7 +862,14 @@ namespace XKRS.Device.SolidMotionCard
return ret == (short)FuncRet.Function_Success;
});
}
-
+ //方案2:不使用外部文本框输入参数,直接写入参数
+
+ public void JOGRun(double MaxV,double MaxA)
+ {
+ int ret = CMCDLL_NET.MCF_Set_Pulse_Mode_Net(0, (ushort)PulseMode.Pulse_Dir_H, 0);
+ ret = CMCDLL_NET.MCF_Set_Servo_Enable_Net(0, (ushort)ServoLogic.Servo_Close, 0);
+ ret=CMCDLL_NET.MCF_JOG_Net(0, MaxV, MaxA, 0);
+ }
///
/// 点位到点位运动
///
@@ -1381,13 +1401,38 @@ namespace XKRS.Device.SolidMotionCard
}
}
+
+
+ public void AxisStop()
+ {
+ short rtn;
+ ushort StationNumber = 0;
+ for (ushort a = 0; a < 4; a++)
+ {
+ rtn = CMCDLL_NET.MCF_Set_Axis_Stop_Profile_Net(a, 10000, 100000, 1, StationNumber);//设置轴S型停止曲线参数
+ rtn = CMCDLL_NET.MCF_Axis_Stop_Net(a, 1, StationNumber);//设置轴为平滑停止模式
+ }
+ }
+ public bool CArdReset()
+ {
+
+ // ConvertFromAxis(startAxisIndex, out ushort station, out ushort axis);
+
+ var ret = CMCDLL_NET.MCF_Set_Position_Net(0, 0, 0);
+ var ret2 = CMCDLL_NET.MCF_Set_Encoder_Net(0, 0, 0);
+
+ return ret2 == 0 ? true : false;
+
+ }
+
+
///
/// 某个轴运动停止
///
/// axisNo
/// 0表示平滑停止,1表示紧急停止
///
- public async Task MoveStop(int axisNum, int option)
+ public async Task MoveStop(int axisNum, int option)
{
return await _taskFactory.StartNew(() =>
{
diff --git a/DH.Devices.Vision/DH.Devices.Vision.csproj b/DH.Devices.Vision/DH.Devices.Vision.csproj
index 9ff2894..6ca65e5 100644
--- a/DH.Devices.Vision/DH.Devices.Vision.csproj
+++ b/DH.Devices.Vision/DH.Devices.Vision.csproj
@@ -14,6 +14,7 @@
+
diff --git a/DH.Devices.Vision/DetectionConfig.cs b/DH.Devices.Vision/DetectionConfig.cs
index 9cea844..90afdb6 100644
--- a/DH.Devices.Vision/DetectionConfig.cs
+++ b/DH.Devices.Vision/DetectionConfig.cs
@@ -324,6 +324,29 @@ namespace DH.Devices.Vision
[Description("是否加入检测工位")]
public bool IsAddStation { get; set; } = true;
+ [Category("1.预处理(视觉算子)")]
+ [DisplayName("预处理-算法文件路径")]
+ // [Description("预处理算法文件路径配置")][Editor(typeof(FileDialogEditor), typeof(UITypeEditor))]
+ public string HalconAlgorithemPath_Pre { get; set; }
+
+ // [Category("1.预处理(视觉算子)")]
+ //[DisplayName("预处理-输出结果的SPEC标准")]
+ //[Description("预处理输出结果的SPEC标准配置")]
+
+ // public List OutputSpec_Pre { get; set; } = new List();
+
+ [Category("1.预处理(视觉算子)")]
+ [DisplayName("预处理-参数列表")]
+ [Description("预处理-参数列表")]
+
+ public List PreTreatParams { get; set; } = new List();
+
+ [Category("1.预处理(视觉算子)")]
+ [DisplayName("预处理-输出参数列表")]
+ [Description("预处理-输出参数列表")]
+
+ public List OUTPreTreatParams { get; set; } = new List();
+
[Category("2.中检测(深度学习)")]
[DisplayName("中检测-模型类型")]
[Description("模型类型:ImageClassification-图片分类;ObjectDetection:目标检测;Segmentation-图像分割")]
diff --git a/DH.Devices.Vision/SimboVisionMLBase.cs b/DH.Devices.Vision/SimboVisionMLBase.cs
index 0164094..485093e 100644
--- a/DH.Devices.Vision/SimboVisionMLBase.cs
+++ b/DH.Devices.Vision/SimboVisionMLBase.cs
@@ -2,6 +2,7 @@
using OpenCvSharp;
using System;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
@@ -85,6 +86,30 @@ namespace DH.Devices.Vision
}
+ }
+ public class PreTreatParam
+ {
+
+ ///
+ /// 参数名称
+ ///
+ ///
+ [Category("预处理参数")]
+ [DisplayName("参数名称")]
+ [Description("参数名称")]
+ public string Name { get; set; }
+
+
+ ///
+ /// 参数值
+ ///
+ ///
+ [Category("预处理参数")]
+ [DisplayName("参数值")]
+ [Description("参数值")]
+ public string Value { get; set; }
+
+
}
public static class MLGPUEngine
{
diff --git a/DH.Devices.Vision/SimboVisionModel.cs b/DH.Devices.Vision/SimboVisionModel.cs
new file mode 100644
index 0000000..b07f3e6
--- /dev/null
+++ b/DH.Devices.Vision/SimboVisionModel.cs
@@ -0,0 +1,35 @@
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DH.Devices.Vision
+{
+ //工站 模型检测引擎
+ public class SimboStationMLEngineSet
+ {
+ public bool IsUseGPU { get; set; }
+ ///
+ /// GPU设备号
+ ///
+ public int GPUNo { get; set; }
+ ///
+ /// CPU线程号
+ ///
+ public int CPUNo { get; set; }
+ ///
+ /// 检测配置ID
+ ///
+ public string DetectionId { get; set; }
+
+ public string DetectionName { get; set; }
+
+ ///
+ /// 深度学习模型
+ ///
+ public SimboVisionMLBase StationMLEngine { get; set; }
+
+ }
+}
diff --git a/DHSoftware/DHSoftware.csproj b/DHSoftware/DHSoftware.csproj
index dbb3345..56e99eb 100644
--- a/DHSoftware/DHSoftware.csproj
+++ b/DHSoftware/DHSoftware.csproj
@@ -19,6 +19,7 @@
+
@@ -27,6 +28,12 @@
..\x64\Debug\DVPCameraCS64.dll
+
+ ..\x64\Debug\halcondotnet.dll
+
+
+ ..\x64\Debug\hdevenginedotnet.dll
+
\ No newline at end of file
diff --git a/DHSoftware/MainWindow.cs b/DHSoftware/MainWindow.cs
index 90b5eba..ddf998d 100644
--- a/DHSoftware/MainWindow.cs
+++ b/DHSoftware/MainWindow.cs
@@ -1,12 +1,15 @@
using AntdUI;
using AntdUI.Svg;
+using DH.Commons.Enums;
using DH.Devices.Camera;
+using DH.Devices.Motion;
using DH.Devices.PLC;
using DH.Devices.Vision;
using DHSoftware.Languages;
using DHSoftware.Models;
using DHSoftware.Utils;
using DVPCameraType;
+using HalconDotNet;
using Microsoft.Win32;
using OpenCvSharp;
using System;
@@ -21,6 +24,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
+using XKRS.Common.Model;
using static AntdUI.Math3D;
using Camera = DHSoftware.Models.Camera;
@@ -215,6 +219,7 @@ namespace DHSoftware
public List Cameras { get; } = new List();
public Dictionary Dectection { get; } = new Dictionary();
public XinJEPLCTcpNet PLC { get; } = new XinJEPLCTcpNet();
+ SLDMotion sLDMotion = new SLDMotion();
private void MainWindow_Load(object sender, EventArgs e)
{
@@ -264,9 +269,11 @@ namespace DHSoftware
public volatile int ProductNum_Total = 0;
public volatile int ProductNum_OK = 0;
private readonly object _cameraSummaryLock = new object();
- List detectionList = new List();
+ List DetectionConfigs = new List();
+ List SimboStationMLEngineList = new List();
+ Dictionary HalconToolDict = new Dictionary();
public List RecongnitionLabelList { get; set; } = new List();
- public DateTime sraerttime;
+ public DateTime startTime;
private void HandleStartButton()
{
CurrentMachine = true;
@@ -299,10 +306,14 @@ namespace DHSoftware
- var det1 = new DetectionConfig("相机1", MLModelType.ObjectDetection, @"D:\DHSoftware\DHSoftware\Models\yolov3.cfg", false, "Cam1");
- var det2 = new DetectionConfig("相机2", MLModelType.ObjectDetection, @"D:\DHSoftware\DHSoftware\Models\yolov3.cfg", false, "Cam2");
- var det3 = new DetectionConfig("相机3", MLModelType.ObjectDetection, @"D:\DHSoftware\DHSoftware\Models\yolov3.cfg", false, "Cam3");
- var det4 = new DetectionConfig("相机4", MLModelType.ObjectDetection, @"D:\DHSoftware\DHSoftware\Models\yolov3.cfg", false, "Cam4");
+ var det1 = new DetectionConfig("相机1", MLModelType.ObjectDetection, @"D:\PROJECTS\X015\Vision\Cam1.onnx", false, "Cam1");
+ var det2 = new DetectionConfig("相机2", MLModelType.ObjectDetection, @"D:\PROJECTS\X015\Vision\Cam2.onnx", false, "Cam2");
+ var det3 = new DetectionConfig("相机3", MLModelType.ObjectDetection, @"D:\PROJECTS\X015\Vision\Cam3.onnx", false, "Cam3");
+ var det4 = new DetectionConfig("相机4", MLModelType.ObjectDetection, @"D:\PROJECTS\X015\Vision\Cam4.onnx", false, "Cam4");
+ var det5 = new DetectionConfig("相机5", MLModelType.ObjectDetection, @"D:\PROJECTS\X015\Vision\Cam5.onnx", false, "Cam5");
+ var det6 = new DetectionConfig("相机6", MLModelType.ObjectDetection, @"D:\PROJECTS\X015\Vision\Cam6.onnx", false, "Cam6");
+ var det7 = new DetectionConfig("相机7", MLModelType.ObjectDetection, @"D:\PROJECTS\X015\Vision\Cam7.onnx", false, "Cam7");
+ var det8 = new DetectionConfig("相机8", MLModelType.ObjectDetection, @"D:\PROJECTS\X015\Vision\Cam8.onnx", false, "Cam8");
List CameraCollects=new List();
CameraCollects.Add(new RelatedCamera("Cam1"));
List CameraCollects2 = new List();
@@ -313,43 +324,125 @@ namespace DHSoftware
CameraCollects4.Add(new RelatedCamera("Cam4"));
List CameraCollects5 = new List();
CameraCollects5.Add(new RelatedCamera("Cam5"));
+ List CameraCollects6 = new List();
+ CameraCollects6.Add(new RelatedCamera("Cam6"));
+ List CameraCollects7 = new List();
+ CameraCollects7.Add(new RelatedCamera("Cam7"));
+ List CameraCollects8 = new List();
+ CameraCollects8.Add(new RelatedCamera("Cam8"));
+
float Conf = 0.5f;
+
+
det1.CameraCollects = CameraCollects;
det1.ModelconfThreshold = Conf;
det1.ModelWidth = 640;
det1.ModelHeight = 640;
- det1.in_lable_path = " D:\\PROJECTS\\MaodingTest1\\Vision\\cam1.txt";
-
+ det1.in_lable_path = "D:\\PROJECTS\\X015\\Vision\\Cam1.txt";
+ det1.IsEnabled = true;
det2.CameraCollects = CameraCollects2;
det2.ModelconfThreshold = Conf;
det2.ModelWidth = 640;
det2.ModelHeight = 640;
- det2.in_lable_path = " D:\\PROJECTS\\MaodingTest1\\Vision\\cam2.txt";
+ det2.in_lable_path = "D:\\PROJECTS\\X015\\Vision\\Cam2.txt";
+ det2.IsEnabled = true;
det3.CameraCollects = CameraCollects3;
det3.ModelconfThreshold = Conf;
det3.ModelWidth = 640;
det3.ModelHeight = 640;
- det3.in_lable_path = " D:\\PROJECTS\\MaodingTest1\\Vision\\cam3.txt";
+ det3.in_lable_path = "D:\\PROJECTS\\X015\\Vision\\Cam3.txt";
+ det3.IsEnabled = true;
det4.CameraCollects = CameraCollects4;
det4.ModelconfThreshold = Conf;
det4.ModelWidth = 640;
det4.ModelHeight = 640;
- det4.in_lable_path = " D:\\PROJECTS\\MaodingTest1\\Vision\\cam4.txt";
+ det4.in_lable_path = "D:\\PROJECTS\\X015\\Vision\\Cam4.txt";
+ det4.IsEnabled = true;
+
+
+
+ det5.CameraCollects = CameraCollects5;
+ det5.ModelconfThreshold = Conf;
+ det5.ModelWidth = 640;
+ det5.ModelHeight = 640;
+ det5.in_lable_path = "D:\\PROJECTS\\X015\\Vision\\Cam5.txt";
+ det5.IsEnabled = true;
+
+ det6.CameraCollects = CameraCollects6;
+ det6.ModelconfThreshold = Conf;
+ det6.ModelWidth = 640;
+ det6.ModelHeight = 640;
+ det6.in_lable_path = "D:\\PROJECTS\\X015\\Vision\\Cam6.txt";
+ det6.IsEnabled = true;
+
+ det7.CameraCollects = CameraCollects7;
+ det7.ModelconfThreshold = Conf;
+ det7.ModelWidth = 640;
+ det7.ModelHeight = 640;
+ det7.in_lable_path = "D:\\PROJECTS\\X015\\Vision\\Cam7.txt";
+ det7.IsEnabled = true;
+
+ det8.CameraCollects = CameraCollects8;
+ det8.ModelconfThreshold = Conf;
+ det8.ModelWidth = 640;
+ det8.ModelHeight = 640;
+ det8.in_lable_path = "D:\\PROJECTS\\X015\\Vision\\Cam8.txt";
+ det8.IsEnabled = true;
+
+ DetectionConfigs.Add(det1);
+ DetectionConfigs.Add(det2);
+ DetectionConfigs.Add(det3);
+ DetectionConfigs.Add(det4);
+ DetectionConfigs.Add(det5);
+ DetectionConfigs.Add(det6);
+ DetectionConfigs.Add(det7);
+ DetectionConfigs.Add(det8);
- detectionList.Add(det1);
- detectionList.Add(det2);
- detectionList.Add(det3);
- detectionList.Add(det4);
Cameras.Clear();
HKCameras.Clear();
Dectection.Clear();
_cameraRelatedDetectionDict = new();
+
+#if false
+ for (int i = 1; i <= 8; i++)
+ {
+ HikVisionCamera camera = new HikVisionCamera();
+ camera.CameraName = $"Cam{i}";
+ camera.CameraIP = $"192.168.{i}.1";
+ camera.ComputerIP = $"192.168.{i}.1";
+ camera.CameraConnect();
+ camera.OnHImageOutput += OnCameraHImageOutput;
+ HKCameras.Add(camera);
+
+
+ }
+#else
+ Do3ThinkCamera do3ThinkCamera1 = new Do3ThinkCamera();
+
+ do3ThinkCamera1.dvpStreamFormat = dvpStreamFormat.S_RAW8;
+ do3ThinkCamera1.CameraName = "Cam1";
+ do3ThinkCamera1.CameraConnect();
+ do3ThinkCamera1.OnHImageOutput += OnCameraHImageOutput;
+ Cameras.Add(do3ThinkCamera1);
+ for (int i=2;i<=8;i++)
+ {
+
+ Do3ThinkCamera do3ThinkCamera2 = new Do3ThinkCamera();
+ do3ThinkCamera2.dvpStreamFormat = dvpStreamFormat.S_RGB24;
+ do3ThinkCamera2.CameraName = $"Cam{i}";
+ Cameras.Add(do3ThinkCamera2);
+ do3ThinkCamera2.CameraConnect();
+ do3ThinkCamera2.OnHImageOutput += OnCameraHImageOutput;
+ }
- detectionList.ForEach(detection =>
+#endif
+
+
+ DetectionConfigs.ForEach(detection =>
{
detection.CameraCollects.ForEach(cam =>
@@ -372,84 +465,117 @@ namespace DHSoftware
);
});
string inferenceDevice = "CPU";
- //for (int i = 1; i <= 8; i++)
- //{
- // HikVisionCamera camera = new HikVisionCamera();
- // camera.CameraName = $"Cam{i}";
- // camera.CameraIP = $"192.168.{i}.1";
- // camera.ComputerIP = $"192.168.{i}.1";
- // camera.CameraConnect();
- // camera.OnHImageOutput += OnCameraHImageOutput;
- // HKCameras.Add(camera);
- // var simbo_1 = new SimboObjectDetection
- // {
-
- // };
- // MLInit mLInit_1;
-
-
- // mLInit_1 = new MLInit($"D:\\PROJECTS\\MaodingTest1\\Vision\\cam{i}.onnx", "images", inferenceDevice, 640, 640);
-
-
- // simbo_1.Load(mLInit_1);
- // Dectection.Add(camera.CameraName, simbo_1);
- //}
//Add the code for the "启动" button click here
- Do3ThinkCamera do3ThinkCamera1 = new Do3ThinkCamera();
-
- do3ThinkCamera1.dvpStreamFormat = dvpStreamFormat.S_MONO8;
- do3ThinkCamera1.CameraName = "Cam1";
- Do3ThinkCamera do3ThinkCamera2 = new Do3ThinkCamera();
- do3ThinkCamera2.dvpStreamFormat = dvpStreamFormat.S_RGB24;
- do3ThinkCamera2.CameraName = "Cam2";
- Cameras.Add(do3ThinkCamera1);
- Cameras.Add(do3ThinkCamera2);
- do3ThinkCamera1.CameraConnect();
- do3ThinkCamera2.CameraConnect();
- do3ThinkCamera1.OnHImageOutput += OnCameraHImageOutput;
- do3ThinkCamera2.OnHImageOutput += OnCameraHImageOutput;
- var simbo1 = new SimboObjectDetection();
- MLInit mLInit;
+ //初始化Halcon工具
+ InitialHalconTools();
-
- mLInit = new MLInit($"D:\\PROJECTS\\MaodingTest1\\Vision\\cam1.onnx", "images", inferenceDevice, 640, 640);
-
-
- simbo1.Load(mLInit);
-
-
- Dectection.Add(det1.Id, simbo1);
-
- var simbo2 = new SimboObjectDetection();
- MLInit mLInit2;
+ //深度学习模型加载
+ bool resultOK =InitialSimboMLEnginesAsync();
+ if (resultOK)
+ {
+ //初始化失败
+ // return;
+ }
+ //位置比较卡
-
- mLInit2 = new MLInit($"D:\\PROJECTS\\MaodingTest1\\Vision\\cam2.onnx", "images", inferenceDevice, 640, 640);
+ sLDMotion.AxisSettings = new List();
+ AxisSetting axis1=new AxisSetting();
+ axis1.AxisIndex = 0;
+ axis1.AxisName = "转盘1";
+ axis1.IsAxisEnabled = true;
+ //axis1.AlarmLogic = AxisDirection.Positive;
+ sLDMotion.IODefinitionCollection=new List();
+ Motion(sLDMotion.IODefinitionCollection);
- simbo2.Load(mLInit2);
-
- Dectection.Add(det2.Id, simbo2);
- PLC.IP = "192.168.6.6";
- PLC.Port = 502;
- PLC.PLCConnect();
- PLC.OnNewPieces -= MainMotion_NewPieces;
- PLC.OnNewPieces += MainMotion_NewPieces;
+ sLDMotion.SnapshotSettings = new List();
+ int[] cameraPositions = { 7613, 24161, 33608, 39702, 45701 };
+
+ for (int i = 0; i < 5; i++)
+ {
+ sLDMotion.SnapshotSettings.Add(new SnapshotSetting
+ {
+ IsEnabled = true,
+ CameraIO = sLDMotion.IODefinitionCollection.FirstOrDefault(t => t.IOType == IOType.OUTPUT && t.IOIndex == i),
+ CameraPosition = cameraPositions[i],
+ StationNumber = 0
+ });
+ }
+
+
+
+ sLDMotion.BlowSettings = new List();
+ int[] BlowPositions = { 61353, 68566 };
+
+ for (int i = 0; i < 2; i++)
+ {
+ sLDMotion.BlowSettings.Add(new BlowSetting
+ {
+ IsEnabled = true,
+ BlowIO = sLDMotion.IODefinitionCollection.FirstOrDefault(t => t.IOType == IOType.OUTPUT && t.IOIndex == i),
+ BlowPosition = BlowPositions[i],
+ StationNumber = 0
+ });
+ }
+
+ //SnapshotSetting sna1 = new SnapshotSetting();
+ //sna1.IsEnabled = true;
+ //sna1.CameraIO= sLDMotion.IODefinitionCollection.FirstOrDefault(t => t.IOType == IOType.OUTPUT && t.IOIndex == 0);
+ //sna1.CameraPosition = 17000;
+ //sna1.StationNumber = 0;
+
+
+
+ // sLDMotion.SnapshotSettings.Add(sna1);
+ sLDMotion.AxisSettings.Add(axis1);
+ sLDMotion.Init();
+ // sLDMotion.Start();
+
+ //PLC.IP = "192.168.6.6";
+ //PLC.Port = 502;
+ //PLC.PLCConnect();
+ //PLC.OnNewPieces -= MainMotion_NewPieces;
+ //PLC.OnNewPieces += MainMotion_NewPieces;
ProductBaseCount = 2;
for (int i = 0; i < ProductBaseCount * ProductListMulti; i++)
{
ConcurrentDictionary products = new ConcurrentDictionary();
_productLists.Add(products);
}
- sraerttime=DateTime.Now;
+ sLDMotion.AxisStop();
+ bool e=sLDMotion.CArdReset();
+ sLDMotion.JOGRun(10000, 100000);
+ startTime =DateTime.Now;
}
+ public void Motion(List iODefinitions)
+ {
+ for (int i = 0; i < 16; i++)
+ {
+ iODefinitions.Add(new IODefinition
+ {
+ IOType = IOType.INPUT,
+ IOIndex = i,
+ IODesc = $"入料传感器{i + 1}"
+ });
+ }
+ for (int i = 0; i < 16; i++)
+ {
+ iODefinitions.Add(new IODefinition
+ {
+ IOType = IOType.OUTPUT,
+ IOIndex = i,
+ IODesc = $"入料传感器{i + 1}"
+ });
+ }
+ }
+
private uint PieceCount = 0;
private List> _productLists = new List>();
private int ProductListMulti = 2;
@@ -457,11 +583,7 @@ namespace DHSoftware
private int PieceNumberToIndex(uint pn)
{
// 物料编号,取余 集合数量
- //int multiple = (int)(pn / ProductBaseCount) % 2;
- //int offset = (int)(pn % ProductBaseCount);
- //int ret = (ProductBaseCount * multiple) + offset;
-
- //int ret = (int)(pn % ProductBaseCount);
+
int ret = (int)(pn % (ProductBaseCount * ProductListMulti));
return ret;
}
@@ -503,6 +625,302 @@ namespace DHSoftware
//OnUpdateCT?.Invoke(objData, ctTime);
});
}
+ ///
+ /// 初始化深度学习工具
+ ///
+ private bool InitialSimboMLEnginesAsync()
+ {
+ //深度学习 模型加载
+ var resultOK = MLLoadModel();
+ return resultOK;
+ }
+ ///
+ /// 深度学习 模型加载
+ ///
+ ///
+ private bool MLLoadModel()
+ {
+ bool resultOK = false;
+ try
+ {
+ SimboStationMLEngineList = new List();
+ // _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;
+ }
+ ///
+ /// 单个模型加载
+ ///
+ ///
+ ///
+ ///
+ 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)
+ {
+ case MLModelType.ImageClassification:
+ break;
+ case MLModelType.ObjectDetection:
+ mLEngineSet.StationMLEngine = new SimboObjectDetection();
+ break;
+ case MLModelType.SemanticSegmentation:
+
+ break;
+ case MLModelType.InstanceSegmentation:
+ mLEngineSet.StationMLEngine = new SimboInstanceSegmentation();
+ break;
+ case MLModelType.ObjectGPUDetection:
+ 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);
+ }
+ //LogAsync(DateTime.Now, LogLevel.Information, $"模型加载成功;是否GPU:{isGPU} CoreInx:{coreInx} - {dc.Name}" + $" {dc.ModelType.GetEnumDescription()}:{dc.ModelPath}");
+ }
+ }
+ catch (Exception ex)
+ {
+ //throw new ProcessException($"异常:是否GPU:{isGPU} CoreInx:{coreInx} - {dc.Name}模型加载异常:{ex.GetExceptionMessage()}");
+ }
+ return mLEngineSet;
+ }
+ private void InitialHalconTools()
+ {
+ HOperatorSet.SetSystem("parallelize_operators", "true");
+ HOperatorSet.SetSystem("reentrant", "true");
+ HOperatorSet.SetSystem("global_mem_cache", "exclusive");
+
+ HalconToolDict = new Dictionary();
+
+ 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;
+ }
+ }
+
+ ///
+ /// 预处理
+ ///
+ ///
+ ///
+ 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;
+
+ 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;
+
+ for (int i = 0; i < detectConfig.OUTPreTreatParams.Count; i++)
+ {
+ var param = detectConfig.OUTPreTreatParams[i];
+ tool.InputTupleDic[param.Name] = double.Parse(param.Value);
+ }
+
+
+
+
+ // 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)
+ {
+
+ }
+ finally
+ {
+ //detectResult.VisionImageSet.HImage?.Dispose();
+ //detectResult.VisionImageSet.HImage = null;
+ // MhImage?.Dispose();
+ //MhImage = null;
+ }
+
+ }
+ ///
+ /// 相机回调
+ ///
+ ///
+ ///
+ ///
private void OnCameraHImageOutput(DateTime dt, CameraBase camera, Mat imageSet)
{
// 获取该相机的拍照计数
@@ -521,127 +939,216 @@ namespace DHSoftware
// 找到产品存放在哪个队列里
ConcurrentDictionary tmpDic = _productLists[index];
- try
+ try
+ {
+ int retryTimes = 100;
+ while (product == null && retryTimes > 0)
{
- int retryTimes = 100;
- while (product == null && retryTimes > 0)
+ if (tmpDic.ContainsKey(productNumber))
{
- if (tmpDic.ContainsKey(productNumber))
- {
- product = tmpDic[productNumber];
- }
- else
- {
- Thread.Sleep(20);
- }
- retryTimes--;
+ product = tmpDic[productNumber];
}
- // 如果产品为空,则销毁图片,提示错误
- if (null == product)
+ else
{
- List pnList = tmpDic.Keys.ToList();
+ Thread.Sleep(20);
+ }
+ retryTimes--;
+ }
+ // 如果产品为空,则销毁图片,提示错误
+ if (null == product)
+ {
+ List pnList = tmpDic.Keys.ToList();
- string pnStr = "";
- if (pnList != null && pnList.Count > 0)
- {
- pnStr = string.Join(",", pnList);
- }
-
- //LogAsync(DateTime.Now, LogLevel.Error, $"{camera.Name} 未找到产品,编号:{productNumber},队列{index}数量:{tmpDic.Count},列表:{pnStr}");
- localImageSet.Dispose();
- return;
+ string pnStr = "";
+ if (pnList != null && pnList.Count > 0)
+ {
+ pnStr = string.Join(",", pnList);
}
- // LogAsync(DateTime.Now, LogLevel.Information, $"{camera.Name} 找到产品{productNumber},队列{index}数量:{tmpDic.Count}");
+ //LogAsync(DateTime.Now, LogLevel.Error, $"{camera.Name} 未找到产品,编号:{productNumber},队列{index}数量:{tmpDic.Count},列表:{pnStr}");
+ localImageSet.Dispose();
+ return;
+ }
- if (!_cameraRelatedDetectionDict.ContainsKey(camera.CameraName))
- {
+ // LogAsync(DateTime.Now, LogLevel.Information, $"{camera.Name} 找到产品{productNumber},队列{index}数量:{tmpDic.Count}");
- localImageSet.Dispose();
- // LogAsync(DateTime.Now, LogLevel.Warning, $"{camera.Name} 找到产品{productNumber},但是没有推理1");
+ if (!_cameraRelatedDetectionDict.ContainsKey(camera.CameraName))
+ {
- return;
- }
+ localImageSet.Dispose();
+ // LogAsync(DateTime.Now, LogLevel.Warning, $"{camera.Name} 找到产品{productNumber},但是没有推理1");
+
+ return;
+ }
- double totalTime = 0.0;
- List resultStates = new List();
- List? detectionDict = _cameraRelatedDetectionDict[camera.CameraName];
-
+ double totalTime = 0.0;
+ List resultStates = new List();
+ List? detectionDict = _cameraRelatedDetectionDict[camera.CameraName];
+
for (int i = 0; i < detectionDict.Count; i++)
{
string detectionId = detectionDict[i];
- try
+
+ DetectionConfig detectConfig = null;
+ //找到对应的配置
+ if (!string.IsNullOrWhiteSpace(detectionId))
{
- 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)
+ {
+
+ //未能获得检测配置
+ return;
+ }
+
+ // 1. 预处理
+ using (Mat inferenceImage = localImageSet.Clone()) // 仅在此处克隆,确保推理过程中 Mat 有独立副本
+ {
+ DetectStationResult detectResult = new DetectStationResult();
+ #region 1.预处理
+
+ using (Mat PreTMat = inferenceImage.Clone())
{
- detectConfig = detectionList.FirstOrDefault(u => u.Id == detectionId);
- }
- else
- {
- detectConfig = detectionList.FirstOrDefault(u => u.CameraSourceId == camera.CameraName);
+ PreTreated(detectConfig, detectResult, PreTMat);
}
- if (detectConfig == null)
- {
- //未能获得检测配置
- return;
+
+ #endregion
+ if (detectResult.IsPreTreatNG)
+ {
+ detectResult.ResultState = ResultState.DetectNG;
+ detectResult.IsPreTreatDone = true;
+ detectResult.IsMLDetectDone = false;
+
}
- // 1. 预处理
- using (Mat inferenceImage = localImageSet.Clone()) // 仅在此处克隆,确保推理过程中 Mat 有独立副本
+
+
+ if (!string.IsNullOrWhiteSpace(detectConfig.ModelPath) && detectConfig.IsEnabled)
{
- #region 1.预处理
- #endregion
- #region 2.深度学习推理
- var req = new MLRequest();
- req.mImage = inferenceImage;
- req.ResizeWidth = 640;
- req.ResizeHeight = 640;
- req.confThreshold = 0.5f;
- req.iouThreshold = 0.3f;
- req.out_node_name = "output0";
- req.in_lable_path = "D:\\PROJECTS\\MaodingTest1\\Vision\\cam1.txt";
-
- 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");
- #endregion
- this.BeginInvoke(new MethodInvoker(delegate ()
- {
- pictureBox1.Image?.Dispose(); // 释放旧图像
- pictureBox1.Image = result.ResultMap;
- richTextBox1.AppendText($"推理成功 {productNumber}, {result.IsSuccess} 耗时 {sw.ElapsedMilliseconds}ms\n");
- }));
- req.mImage.Dispose();
-#if true
-
- #region 3.后处理
- DetectStationResult detectResult = new DetectStationResult();
- if (result == null || (result != null && !result.IsSuccess))
+ 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;
}
- if (result != null && result.IsSuccess)
+
+ #region 2.深度学习推理
+ //LogAsync(DateTime.Now, LogLevel.Information, $"{detectConfig.Name} 产品{detectResult.TempPid} 模型检测执行");
+
+ if (!string.IsNullOrWhiteSpace(detectConfig.ModelPath))
{
- detectResult.DetectDetails = result.ResultDetails;
- if (detectResult.DetectDetails != null)
+ 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.in_lable_path = detectConfig.in_lable_path;
+
+ req.confThreshold = detectConfig.ModelconfThreshold;
+ req.iouThreshold = 0.3f;
+ req.segmentWidth = 320;
+
+ switch (detectConfig.ModelType)
{
+ case MLModelType.ImageClassification:
+ break;
+ case MLModelType.ObjectDetection:
+
+ break;
+ case MLModelType.SemanticSegmentation:
+ break;
+ case MLModelType.InstanceSegmentation:
+ break;
+ case MLModelType.ObjectGPUDetection:
+
+ break;
+ default:
+ break;
}
- else
+
+ // LogAsync(DateTime.Now, LogLevel.Information, $"{detectConfig.Name} 产品{detectResult.TempPid} RunInference BEGIN");
+ mlWatch.Start();
+ //20230802改成多线程推理 RunInferenceFixed
+
+ var result = mlSet.StationMLEngine.RunInference(req);
+ // 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} 耗时 {mlWatch.ElapsedMilliseconds}ms\n");
+ }));
+ req.mImage.Dispose();
+
+
+
+
+ if (result == null || (result != null && !result.IsSuccess))
{
detectResult.IsMLDetectDone = false;
}
+ if (result != null && result.IsSuccess)
+ {
+ detectResult.DetectDetails = result.ResultDetails;
+ if (detectResult.DetectDetails != null)
+ {
+ }
+ else
+ {
+ detectResult.IsMLDetectDone = false;
+ }
+ }
}
-
#endregion
+
+
+
#region 3.后处理
#endregion
//根据那些得分大于阈值的推理结果,判断产品是否成功
@@ -721,109 +1228,86 @@ namespace DHSoftware
.FirstOrDefault()?.Key ?? ResultState.OK;
detectResult.ResultLabel = detectResult.ResultLabel;
detectResult.ResultLabelCategoryId = detectResult.ResultLabel;//TODO:设置优先级
-
#endregion
+
resultStates.Add(detectResult.ResultState);
product.ResultCollection.Add(detectResult);
-#endif
+
}
-
+
+
}
- catch (Exception ex)
+
+
+ }
+
+ product.InferenceOne(() =>
{
- // LogAsync(DateTime.Now, LogLevel.Information, $"{camera.Name} 推理异常,物料编号:{productNumber},检测项:{d}, {ex.GetExceptionMessage}");
- }
- }
-
-
-
-
- product.InferenceOne(() =>
- {
- ;
- }, () =>
- {
- ;
- });
-
- // LogAsync(DateTime.Now, LogLevel.Information, $"{camera.Name} 推理完成,产品{productNumber}");
-
- if (!product.InferenceFinished())
- {
-
- return;
- }
- ProductNum_Total++;
- CalculateOEE();
- this.BeginInvoke(new MethodInvoker(delegate ()
- {
-
- int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
-
- richTextBox1.AppendText($"统计结果成功,{productNumber}吹气!\n");
-
- // 设置回原来的滚动位置
- richTextBox1.SelectionStart = richTextBox1.TextLength;
- richTextBox1.ScrollToCaret();
- }));
- #region 6. 统计产品结果
- product.ProductResult = product.ResultCollection.Any(u => u.ResultState != ResultState.OK)
- ? ResultState.B_NG
- : ResultState.OK;
- product.ProductLabelCategory = product.ProductResult.GetEnumDescription();
- product.ProductLabel = product.ProductResult.GetEnumDescription();
- #endregion
- #region 7.产品吹气
-
- #endregion
-
-
-
-
-
- // 出列
- ProductData temp = null;
-
- int tryTimes = 10;
- while (temp == null && tryTimes > 0)
- {
- if (tmpDic.TryRemove(productNumber, out temp))
+ ;
+ }, () =>
{
- break;
+ ;
+ });
+
+ // LogAsync(DateTime.Now, LogLevel.Information, $"{camera.Name} 推理完成,产品{productNumber}");
+
+ if (!product.InferenceFinished())
+ {
+
+ return;
}
-
- tryTimes--;
- Thread.Sleep(5);
- }
- if (temp == null)
- {
- string logStr = $"{DateTime.Now}产品{productNumber}出列失败:true,"+
- $"当前队列产品数量:{tmpDic.Count}";
+ ProductNum_Total++;
+ CalculateOEE();
this.BeginInvoke(new MethodInvoker(delegate ()
{
int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
- richTextBox1.AppendText(logStr);
+ richTextBox1.AppendText($"统计结果成功,{productNumber} 吹气!\n");
// 设置回原来的滚动位置
richTextBox1.SelectionStart = richTextBox1.TextLength;
richTextBox1.ScrollToCaret();
}));
- }
- else
- {
- try
+ #region 6. 统计产品结果
+ product.ProductResult = product.ResultCollection.Any(u => u.ResultState != ResultState.OK)
+ ? ResultState.B_NG
+ : ResultState.OK;
+ product.ProductLabelCategory = product.ProductResult.GetEnumDescription();
+ product.ProductLabel = product.ProductResult.GetEnumDescription();
+ #endregion
+ #region 7.产品吹气
+
+ #endregion
+
+
+
+
+
+ // 出列
+ ProductData temp = null;
+
+ int tryTimes = 10;
+ while (temp == null && tryTimes > 0)
{
- string logStr = $"{DateTime.Now}产品{productNumber}出列成功:true," +
- $"产品结果:{temp.ProductResult.GetEnumDescription()}," +
- $"当前队列产品数量:{tmpDic.Count}";
+ if (tmpDic.TryRemove(productNumber, out temp))
+ {
+ break;
+ }
+
+ tryTimes--;
+ Thread.Sleep(5);
+ }
+ if (temp == null)
+ {
+ string logStr = $"{DateTime.Now}产品{productNumber}出列失败:true," +
+ $"当前队列产品数量:{tmpDic.Count}";
this.BeginInvoke(new MethodInvoker(delegate ()
{
@@ -835,35 +1319,55 @@ namespace DHSoftware
richTextBox1.SelectionStart = richTextBox1.TextLength;
richTextBox1.ScrollToCaret();
}));
- //重新生成实例 销毁之前的实例
- var saveData = temp.GetProductData();
- using(StreamWriter sw=new StreamWriter("D://123log.txt",true,Encoding.UTF8))
- {
- sw.WriteLine(logStr);
- }
-
}
- catch (Exception) { }
- finally
+ else
{
- // temp.Dispose();
- temp = null;
+ try
+ {
+ string logStr = $"{DateTime.Now}产品{productNumber}出列成功:true," +
+ $"产品结果:{temp.ProductResult.GetEnumDescription()}," +
+ $"当前队列产品数量:{tmpDic.Count}";
+ this.BeginInvoke(new MethodInvoker(delegate ()
+ {
+
+ int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;
+
+ richTextBox1.AppendText(logStr);
+
+ // 设置回原来的滚动位置
+ richTextBox1.SelectionStart = richTextBox1.TextLength;
+ richTextBox1.ScrollToCaret();
+ }));
+ //重新生成实例 销毁之前的实例
+ var saveData = temp.GetProductData();
+ using (StreamWriter sw = new StreamWriter("D://123log.txt", true, Encoding.UTF8))
+ {
+ sw.WriteLine(logStr);
+ }
+
+ }
+ catch (Exception) { }
+ finally
+ {
+ // temp.Dispose();
+ temp = null;
+ }
}
+
+ // UpdateCT((float)(dtNow - _ctTime).TotalSeconds);
+ //_ctTime = dtNow;
+ // });
+
+
+ }
+ catch (Exception ex)
+ {
+ //LogAsync(DateTime.Now, LogLevel.Error, $"流程检测未捕获的异常:{ex.GetExceptionMessage()}");
+ product?.Dispose();
}
-
- // UpdateCT((float)(dtNow - _ctTime).TotalSeconds);
- //_ctTime = dtNow;
- // });
-
-
}
- catch (Exception ex)
- {
- //LogAsync(DateTime.Now, LogLevel.Error, $"流程检测未捕获的异常:{ex.GetExceptionMessage()}");
- product?.Dispose();
- }
- }
- });
+
+ });
}
public void SetResult()
{
@@ -895,11 +1399,12 @@ namespace DHSoftware
// Add the code for the "停止" button click here
PLC.TurntableStop();
CurrentMachine = true;
+ sLDMotion.Stop();
}
public int UPH=0;
public void CalculateOEE()
{
- TimeSpan timeSpan = DateTime.Now - sraerttime;
+ TimeSpan timeSpan = DateTime.Now - startTime;
UPH = (int)(ProductNum_Total / timeSpan.TotalHours) + 100;
//UPM = (int)UPH / 60;