修改板卡

This commit is contained in:
JKJ 2025-03-12 09:21:06 +08:00
parent e7736217db
commit b8c83e459d
13 changed files with 2394 additions and 293 deletions

View File

@ -5,6 +5,26 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Platforms>AnyCPU;X64</Platforms>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Folder Include="Helper\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="OpenCvSharp4" Version="4.10.0.20241108" />
<PackageReference Include="OpenCvSharp4.Extensions" Version="4.10.0.20241108" />
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.10.0.20241108" />
</ItemGroup>
<ItemGroup>
<Reference Include="halcondotnet">
<HintPath>..\x64\Debug\halcondotnet.dll</HintPath>
</Reference>
<Reference Include="hdevenginedotnet">
<HintPath>..\x64\Debug\hdevenginedotnet.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

39
DH.Commons/GlobalVar.cs Normal file
View File

@ -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();
//}
}
}

View File

@ -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
/// <summary>
/// 处理过程名
/// </summary>
public string ProcedureName;
/// <summary>
/// hdev程序启动引擎
/// </summary>
private readonly HDevEngine myEngine;
/// <summary>
/// 过程载入工具 .hdvp
/// </summary>
private HDevProcedureCall procedureCall;
/// <summary>
/// 程序运行是否成功
/// </summary>
public bool IsSuccessful { get; set; } = false;
/// <summary>
/// 控制参数字典
/// </summary>
public Dictionary<string, HTuple> InputTupleDic { get; set; }
/// <summary>
/// 图形参数字典
/// </summary>
public Dictionary<string, HObject> InputImageDic { get; set; }
#endregion
#region
/// <summary>
/// 实例化 默认搜索路径为: 启动路径//Vision//
/// </summary>
public HDevEngineTool()
{
ProcedureName = "";
myEngine = new HDevEngine();
myEngine.SetProcedurePath(ProcedurePath);
InputImageDic = new Dictionary<string, HObject>();
InputTupleDic = new Dictionary<string, HTuple>();
}
/// <summary>
/// 实例化
/// </summary>
/// <param name="path">外部函数搜索路径</param>
public HDevEngineTool(string path)
{
myEngine = new HDevEngine();
myEngine.SetProcedurePath(path);
InputImageDic = new Dictionary<string, HObject>();
InputTupleDic = new Dictionary<string, HTuple>();
}
#endregion
/// <summary>
/// 设置函数运行所需参数
/// </summary>
/// <param name="_tupleDictionary">控制参数</param>
/// <param name="_imageDictionary">图形参数</param>
public void SetDictionary(Dictionary<string, HTuple> _tupleDictionary, Dictionary<string, HObject> _imageDictionary)
{
InputTupleDic = _tupleDictionary;
InputImageDic = _imageDictionary;
}
/// <summary>
/// 载入过程 .hdvp
/// </summary>
/// <param name="procedureName">过程名</param>
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;
}
}
/// <summary>
/// 执行过程
/// </summary>
[HandleProcessCorruptedStateExceptions]
public bool RunProcedure(out string errorMsg, out int timeElasped)
{
//lock (_runLock)
{
errorMsg = "";
Stopwatch sw = new Stopwatch();
sw.Start();
try
{
foreach (KeyValuePair<string, HTuple> pair in InputTupleDic)
{
procedureCall.SetInputCtrlParamTuple(pair.Key, pair.Value);
}
foreach (KeyValuePair<string, HObject> 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();
/// <summary>
/// 执行过程
/// </summary>
public Tuple<bool, Dictionary<string, HTuple>, Dictionary<string, HObject>, string, int> RunProcedure(Dictionary<string, HTuple> inputHTupleDict, Dictionary<string, HObject> inputImgDict, List<string> outputHTuples = null, List<string> outputObjs = null)
{
lock (_runLock)
{
string errorMsg = "";
int timeElasped = 0;
bool result = false;
Dictionary<string, HTuple> outputHTupleDict = new Dictionary<string, HTuple>();
Dictionary<string, HObject> outputObjDict = new Dictionary<string, HObject>();
Stopwatch sw = new Stopwatch();
sw.Start();
try
{
if (inputHTupleDict != null && inputHTupleDict.Count > 0)
{
foreach (KeyValuePair<string, HTuple> pair in inputHTupleDict)
{
procedureCall.SetInputCtrlParamTuple(pair.Key, pair.Value);
}
}
if (InputImageDic != null && inputImgDict.Count > 0)
{
foreach (KeyValuePair<string, HObject> 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<bool, Dictionary<string, HTuple>, Dictionary<string, HObject>, string, int> ret = new Tuple<bool, Dictionary<string, HTuple>, Dictionary<string, HObject>, 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<double> HTupleToDouble(this HTuple tuple)
{
List<double> list = new List<double>();
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<byte> lableList = new List<byte>() { 5, 30, 60, 90, 120, 150, 180, 210, 240, 255 };
Dictionary<double, Color> 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<double, Color> 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
}
}

View File

@ -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;
}
}
/// <summary>
/// 获取水平拼接图片
/// </summary>
/// <param name="map1"></param>
/// <param name="map2"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 把OpenCV图像转换到Halcon图像
/// </summary>
/// <param name="mImage">OpenCV图像_Mat</param>
/// <returns>Halcon图像_HObject</returns>
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;
}
}
/// <summary>
/// 从内存流中指定位置,读取数据
/// </summary>
/// <param name="curStream"></param>
/// <param name="startPosition"></param>
/// <param name="length"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 使用byte[]数据,生成三通道 BMP 位图
/// </summary>
/// <param name="originalImageData"></param>
/// <param name="originalWidth"></param>
/// <param name="originalHeight"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 像素点阵转换为bitmap 二值化图
/// </summary>
/// <param name="rawValues">byte[]数组</param>
/// <param name="width">图片的宽度</param>
/// <param name="height">图片的高度</param>
/// <returns>bitmap图片</returns>
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;
}
/// <summary>
/// 像素点阵转换为bitmap灰度图
/// </summary>
/// <param name="rawValues">byte[]数组</param>
/// <param name="width">图片的宽度</param>
/// <param name="height">图片的高度</param>
/// <returns>bitmap图片</returns>
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;
}
}
}

View File

@ -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

View File

@ -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<IODefinition>), typeof(UITypeEditor))]
//public List<IODefinition> IODefinitionCollection { get; set; } = new List<IODefinition>();
// [Editor(typeof(ComplexCollectionEditor<IODefinition>), typeof(UITypeEditor))]
public List<IODefinition> IODefinitionCollection { get; set; } = new List<IODefinition>();
[Category("IO配置")]
[DisplayName("是否信号模式")]
@ -194,35 +194,35 @@ namespace DH.Devices.Motion
public List<BlowSetting> BlowSettings { get; set; } = new List<BlowSetting>();
//[Category("筛选配置")]
//[DisplayName("转盘运转方向")]
//[Description("转盘运转方向,顺时针或逆时针")]
[Category("筛选配置")]
[DisplayName("转盘运转方向")]
[Description("转盘运转方向,顺时针或逆时针")]
//[TypeConverter(typeof(EnumDescriptionConverter<RotationDirectionEnum>))]
//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("回原点参数")]

View File

@ -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);
}
/// <summary>
/// 点位到点位运动
/// </summary>
@ -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;
}
/// <summary>
/// 某个轴运动停止
/// </summary>
/// <param name="axisNum">axisNo</param>
/// <param name="option">0表示平滑停止1表示紧急停止</param>
/// <returns></returns>
public async Task<bool> MoveStop(int axisNum, int option)
public async Task<bool> MoveStop(int axisNum, int option)
{
return await _taskFactory.StartNew(() =>
{

View File

@ -14,6 +14,7 @@
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="OpenCvSharp4" Version="4.10.0.20241108" />

View File

@ -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<IndexedSpec> OutputSpec_Pre { get; set; } = new List<IndexedSpec>();
[Category("1.预处理(视觉算子)")]
[DisplayName("预处理-参数列表")]
[Description("预处理-参数列表")]
public List<PreTreatParam> PreTreatParams { get; set; } = new List<PreTreatParam>();
[Category("1.预处理(视觉算子)")]
[DisplayName("预处理-输出参数列表")]
[Description("预处理-输出参数列表")]
public List<PreTreatParam> OUTPreTreatParams { get; set; } = new List<PreTreatParam>();
[Category("2.中检测(深度学习)")]
[DisplayName("中检测-模型类型")]
[Description("模型类型ImageClassification-图片分类ObjectDetection目标检测Segmentation-图像分割")]

View File

@ -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
{
/// <summary>
/// 参数名称
/// </summary>
///
[Category("预处理参数")]
[DisplayName("参数名称")]
[Description("参数名称")]
public string Name { get; set; }
/// <summary>
/// 参数值
/// </summary>
///
[Category("预处理参数")]
[DisplayName("参数值")]
[Description("参数值")]
public string Value { get; set; }
}
public static class MLGPUEngine
{

View File

@ -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; }
/// <summary>
/// GPU设备号
/// </summary>
public int GPUNo { get; set; }
/// <summary>
/// CPU线程号
/// </summary>
public int CPUNo { get; set; }
/// <summary>
/// 检测配置ID
/// </summary>
public string DetectionId { get; set; }
public string DetectionName { get; set; }
/// <summary>
/// 深度学习模型
/// </summary>
public SimboVisionMLBase StationMLEngine { get; set; }
}
}

View File

@ -19,6 +19,7 @@
<ItemGroup>
<ProjectReference Include="..\DH.Devices.Camera\DH.Devices.Camera.csproj" />
<ProjectReference Include="..\DH.Devices.Motion\DH.Devices.Motion.csproj" />
<ProjectReference Include="..\DH.Devices.PLC\DH.Devices.PLC.csproj" />
<ProjectReference Include="..\DH.Devices.Vision\DH.Devices.Vision.csproj" />
</ItemGroup>
@ -27,6 +28,12 @@
<Reference Include="DVPCameraCS64">
<HintPath>..\x64\Debug\DVPCameraCS64.dll</HintPath>
</Reference>
<Reference Include="halcondotnet">
<HintPath>..\x64\Debug\halcondotnet.dll</HintPath>
</Reference>
<Reference Include="hdevenginedotnet">
<HintPath>..\x64\Debug\hdevenginedotnet.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

File diff suppressed because it is too large Load Diff