Compare commits

...

5 Commits

Author SHA1 Message Date
a9d02a5a9d 修改界面 2025-03-12 17:18:39 +08:00
JKJ
b8c83e459d 修改板卡 2025-03-12 09:21:06 +08:00
e7736217db 小转盘基本都能出列 2025-03-10 17:18:45 +08:00
0314f4d403 修改瞅瞅 2025-03-10 13:41:12 +08:00
4df6b668bf 上传视觉检测模块 2025-03-07 16:29:38 +08:00
40 changed files with 12349 additions and 851 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>

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -54,4 +55,492 @@ namespace DH.Commons.Enums
=25
}
public enum StreamFormat
{
[Description("8位图像")]
S_RAW8 = 0,
[Description("10位图像")]
S_RAW10 = 1,
[Description("12位图像")]
S_RAW12 = 2,
[Description("14位图像")]
S_RAW14 = 3,
[Description("16位图像")]
S_RAW16 = 4,
[Description("BGR三通道24比特图像")]
S_BGR24 = 10,
[Description("BGRA四通道32比特图像")]
S_BGR32 = 11,
[Description("BGRA四通道48比特图像")]
S_BGR48 = 12,
[Description("BGRA四通道64比特图像")]
S_BGR64 = 13,
[Description("RGB三通道24比特图像")]
S_RGB24 = 14,
[Description("RGBA四通道32比特图像")]
S_RGB32 = 15,
[Description("RGBA四通道48比特图像")]
S_RGB48 = 16,
[Description("RGBA四通道64比特图像")]
S_RGB64 = 17,
[Description("YUV411")]
S_YCBCR_411 = 20,
[Description("YUV422")]
S_YCBCR_422 = 21,
[Description("YUV444")]
S_YCBCR_444 = 22,
[Description("8位灰度图像")]
S_MONO8 = 30,
[Description("10位灰度图像")]
S_MONO10 = 31,
[Description("12位灰度图像")]
S_MONO12 = 32,
[Description("14位灰度图像")]
S_MONO14 = 33,
[Description("16位灰度图像")]
S_MONO16 = 34,
S_B8_G8_R8 = 40,
S_B16_G16_R16 = 44
}
/// <summary>
/// 主板型号
/// </summary>
public enum BoardModelEnum
{
EC3216 = 0,
EC3224,
EC3416,
}
/// <summary>
/// 扩展板类型
/// </summary>
public enum ExtensionBoardEnum
{
[Description("未外接扩展板")]
None,
[Description("一个IO扩展板")]
ExtIO_1,
[Description("一个EC3216扩展板")]
ExtEC3216_1,
[Description("一个EC3224扩展板")]
ExtEC3224_1,
[Description("一个EC3416扩展板")]
ExtEC3416_1,
}
/// <summary>
/// 转盘类型
/// </summary>
public enum MachineDiskType
{
[Description("单转盘")]
SingleDisk = 1,
[Description("双转盘")]
DoubleDisk = 2,
}
/// <summary>
/// 运动板卡 IO 类型IN OUT
/// </summary>
public enum IOType
{
[Description("INPUT")]
INPUT = 0,
[Description("OUTPUT")]
OUTPUT = 1
}
public enum IOValue
{
[Description("关闭")]
FALSE = 0,
[Description("开启")]
TRUE = 1,
[Description("反转")]
REVERSE = 2,
}
public enum RotationDirectionEnum
{
[Description("顺时针(正方向)")]
Clockwise = 0,
[Description("逆时针(负方向)")]
AntiClockwise = 1,
}
/// <summary>
/// IO预定义类型 主要针对输出
/// </summary>
public enum IOPrestatement
{
[Description("自定义")]
Customized = 0,
[Description("指示灯-黄")]
Light_Yellow = 1,
[Description("指示灯-绿")]
Light_Green = 2,
[Description("指示灯-红")]
Light_Red = 3,
[Description("蜂鸣器")]
Beep = 4,
[Description("照明灯")]
Light = 5,
[Description("急停")]
EmergencyStop = 99,
}
/// <summary>
/// 相机信号IO输出模式
/// </summary>
public enum ActionMode
{
[Description("IO断路输出")]
OpenCircuit = 1,
[Description("IO开漏输出低电平")]
LowLevel = 2,
[Description("取反IO")]
Reverse = 3,
[Description("输出500us低脉冲")]
OutputPulse500us = 5,
[Description("输出1ms低脉冲")]
OutputPulse1ms = 6,
[Description("输出2ms低脉冲")]
OutputPulse2ms = 9,
[Description("输出3ms低脉冲")]
OutputPulse3ms = 10,
[Description("输出4ms低脉冲")]
OutputPulse4ms = 11,
[Description("输出5ms低脉冲")]
OutputPulse5ms = 12,
[Description("输出6ms低脉冲")]
OutputPulse6ms = 13,
[Description("输出7ms低脉冲")]
OutputPulse7ms = 14,
[Description("输出8ms低脉冲")]
OutputPulse8ms = 15,
[Description("输出9ms低脉冲")]
OutputPulse9ms = 16,
[Description("输出10ms低脉冲")]
OutputPulse10ms = 17,
[Description("输出20ms低脉冲")]
OutputPulse20ms = 18,
[Description("输出30ms低脉冲")]
OutputPulse30ms = 19,
[Description("输出40ms低脉冲")]
OutputPulse40ms = 20,
[Description("输出50ms低脉冲")]
OutputPulse50ms = 21,
[Description("输出60ms低脉冲")]
OutputPulse60ms = 22,
[Description("输出70ms低脉冲")]
OutputPulse70ms = 23,
[Description("输出80ms低脉冲")]
OutputPulse80ms = 24,
[Description("输出90ms低脉冲")]
OutputPulse90ms = 25,
[Description("输出100ms低脉冲")]
OutputPulse100ms = 26,
[Description("输出200ms低脉冲")]
OutputPulse200ms = 27,
[Description("输出300ms低脉冲")]
OutputPulse300ms = 28,
}
/// <summary>
/// 吹气信号IO输出模式
/// </summary>
public enum BlowType
{
[Description("OK吹气口")]
OK,
[Description("NG吹气口")]
NG,
[Description("吹气口1")]
Blow1,
[Description("吹气口2")]
Blow2,
[Description("吹气口3")]
Blow3,
[Description("吹气口4")]
Blow4,
[Description("吹气口5")]
Blow5,
[Description("吹气口6")]
Blow6,
}
/// <summary>
/// 来料检测位号,目前支持两路
/// </summary>
public enum BitInputNumberEnum
{
[Description("第0路")]
BitInput0 = 0,
[Description("第1路")]
BitInput1,
}
/// <summary>
/// 电平
/// </summary>
public enum LogicLevelEnum
{
[Description("低电平")]
LowLevel = 0,
[Description("高电平")]
HighLevel,
}
/// <summary>
/// 捕捉位置模式
/// </summary>
public enum PositionSourceEnum
{
[Description("指令位置")]
CommandPosition = 0,
[Description("编码器位置")]
EncoderPosition = 1,
}
/// <summary>
/// 来料检测捕获位置
/// </summary>
public enum SortingInputPositionModeEnum
{
[Description("前部")]
Front = 0,
[Description("中间")]
Middle,
}
/// <summary>
/// 回原点模式1
/// </summary>
public enum GoHomeMode
{
// Negative: 负极限、负方向
// Positive: 正极限、正方向
// NeL负限开关
// N
//[ColorSelect("Gray")]
//[FontColorSelect("Black")]
[Description("1 负极限:负限开关_中间:无_正极限:无_Index位置:负限位正边_偏移:正方向")]
Negative_Ne_Center_N_Positive_N_Index_NePo_Offset_Po = 1,
[Description("2 负极限:无_中间:无_正极限:正限开关_Index位置:正限位负边_偏移:负方向")]
Negative_N_Center_N_Positive_Po_Index_PoNe_Offset_Ne = 2,
[Description("3 负极限:无_中间:无_正极限:原点开关_Index位置:原点负边外侧_偏移:负方向")]
Negative_N_Center_N_Positive_H_Index_HNeO_Offset_Ne = 3,
[Description("4 负极限:无_中间:无_正极限:原点开关_Index位置:原点负边内侧_偏移:正方向")]
Negative_N_Center_N_Positive_H_Index_HNeI_Offset_Po = 4,
[Description("5 负极限:原点开关_中间:无_正极限:无_Index位置:原点正边外侧_偏移:正方向")]
Negative_H_Center_N_Positive_N_Index_HPoO_Offset_Po = 5,
[Description("6 负极限:原点开关_中间:无_正极限:无_Index位置:原点正边内侧_偏移:负方向")]
Negative_H_Center_N_Positive_N_Index_HPoI_Offset_Ne = 6,
[Description("7 负极限:无_中间:原点开关_正极限:正限开关_Index位置:原点负边外侧_偏移:负方向")]
Negative_N_Center_H_Positive_Po_Index_HNeO_Offset_Ne = 7,
[Description("8 负极限:无_中间:原点开关_正极限:正限开关_Index位置:原点负边内侧_偏移:正方向")]
Negative_N_Center_H_Positive_Po_Index_HNeI_Offset_Po = 8,
[Description("9 负极限:无_中间:原点开关_正极限:正限开关_Index位置:原点正边内侧_偏移:负方向")]
Negative_N_Center_H_Positive_Po_Index_HPoI_Offset_Ne = 9,
[Description("10 负极限:无_中间:原点开关_正极限:正限开关_Index位置:原点正边外侧_偏移:正方向")]
Negative_N_Center_H_Positive_Po_Index_HPoO_Offset_Po = 10,
[Description("11 负极限:负限开关_中间:原点开关_正极限:无_Index位置:原点正边外侧_偏移:正方向")]
Negative_Ne_Center_H_Positive_N_Index_HPoO_Offset_Po = 11,
[Description("12 负极限:负限开关_中间:原点开关_正极限:无_Index位置:原点正边内侧_偏移:负方向")]
Negative_Ne_Center_H_Positive_N_Index_HPoI_Offset_Ne = 12,
[Description("13 负极限:负限开关_中间:原点开关_正极限:无_Index位置:原点负边内侧_偏移:正方向")]
Negative_Ne_Center_H_Positive_N_Index_HNeI_Offset_Po = 13,
[Description("14 负极限:负限开关_中间:原点开关_正极限:无_Index位置:原点负边外侧_偏移:负方向")]
Negative_Ne_Center_H_Positive_N_Index_HNeO_Offset_Ne = 14,
[Description("17 负极限:负限开关_中间:无_正极限:无_停止位置:负限位正边_偏移:正方向")]
Negative_Ne_Center_N_Positive_N_Stop_NePo_Offset_Po = 17,
[Description("18 负极限:无_中间:无_正极限:正限开关_停止位置:正极限负边_偏移:负方向")]
Negative_N_Center_N_Positive_Po_Stop_PoNe_Offset_Ne = 18,
[Description("19 负极限:无_中间:无_正极限:原点开关_停止位置:原点负边外侧_偏移:负方向")]
Negative_N_Center_N_Positive_H_Stop_HNeO_Offset_Ne = 19,
[Description("20 负极限:无_中间:无_正极限:原点开关_停止位置:原点负边内侧_偏移:正方向")]
Negative_N_Center_N_Positive_H_Stop_HNeI_Offset_Po = 20,
[Description("21 负极限:原点开关_中间:无_正极限:无_停止位置:原点正边外侧_偏移:正方向")]
Negative_H_Center_N_Positive_N_Stop_HPoO_Offset_Po = 21,
[Description("22 负极限:原点开关_中间:无_正极限:无_停止位置:原点正边内侧_偏移:负方向")]
Negative_H_Center_N_Positive_N_Stop_HPoI_Offset_Ne = 22,
[Description("23 负极限:无_中间:原点开关_正极限:正限开关_停止位置:原点负边外侧_偏移:负方向")]
Negative_N_Center_H_Positive_Po_Stop_HNeO_Offset_Ne = 23,
[Description("24 负极限:无_中间:原点开关_正极限:正限开关_停止位置:原点负边内侧_偏移:正方向")]
Negative_N_Center_H_Positive_Po_Stop_HNeI_Offset_Po = 24,
[Description("25 负极限:无_中间:原点开关_正极限:正限开关_停止位置:原点正边内侧_偏移:负方向")]
Negative_N_Center_H_Positive_Po_Stop_HPoI_Offset_Ne = 25,
[Description("26 负极限:无_中间:原点开关_正极限:正限开关_停止位置:原点正边外侧_偏移:正方向")]
Negative_N_Center_H_Positive_Po_Stop_HPoO_Offset_Po = 26,
[Description("27 负极限:负限开关_中间:原点开关_正极限:无_停止位置:原点正边外侧_偏移:正方向")]
Negative_Ne_Center_H_Positive_N_Stop_HPoO_Offset_Ne = 27,
[Description("28 负极限:负限开关_中间:原点开关_正极限:无_停止位置:原点正边内侧_偏移:负方向")]
Negative_Ne_Center_H_Positive_N_Stop_HPoI_Offset_Po = 28,
[Description("29 负极限:负限开关_中间:原点开关_正极限:无_停止位置:原点负边内侧_偏移:正方向")]
Negative_Ne_Center_H_Positive_N_Stop_HNeI_Offset_Ne = 29,
[Description("30 负极限:负限开关_中间:原点开关_正极限:无_停止位置:原点负边外侧_偏移:负方向")]
Negative_Ne_Center_H_Positive_N_Stop_HNeO_Offset_Po = 30,
[Description("33 负极限:无_中间:无_正极限:无_Index位置:负方向Index_偏移:负方向")]
Negative_N_Center_N_Positive_N_Index_NeIndex_Offset_Ne = 33,
[Description("34 负极限:无_中间:无_正极限:无_Index位置:正方向Index_偏移:正方向")]
Negative_N_Center_N_Positive_N_Index_PoIndex_Offset_Po = 34,
}
/// <summary>
/// 马达/运动板卡运行模式
/// </summary>
public enum MotionMode
{
/// <summary>
/// 普通点位运动
/// </summary>
[Description("普通点位运动")]
P2P = 1,
/// <summary>
/// 找正限位运动
/// </summary>
[Description("找正限位运动")]
FindPositive = 4,
/// <summary>
/// 离开正限位
/// </summary>
[Description("离开正限位")]
LeavePositive = 5,
/// <summary>
/// 找负限位运动
/// </summary>
[Description("找负限位运动")]
FindNegative = 6,
/// <summary>
/// 离开负限位
/// </summary>
[Description("离开负限位")]
LeaveNegative = 7,
/// <summary>
/// 找原点运动
/// </summary>
[Description("回原点运动")]
GoHome = 8,
/// <summary>
/// Jog模式
/// </summary>
[Description("Jog模式")]
Jog = 9,
///// <summary>
///// 读数头找原点方式
///// </summary>
//[Description("找原点inde")]
//FindOriIndex = 10,
///// <summary>
///// 插补模式
///// </summary>
//[Description("插补模式")]
//Coordinate = 11
}
}

View File

@ -0,0 +1,277 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XKRS.Common.Model.SolidMotionCard
{
/// <summary>
/// 回零状态
/// </summary>
public enum SearchHomeState
{
/// <summary>
/// 回零成功
/// </summary>
[Description("回零成功")]
HomeSucess = 0,
/// <summary>
/// 回零错误
/// </summary>
[Description("回零错误")]
HomeError = 31,
/// <summary>
/// 正在回零点
/// </summary>
[Description("正在回零点")]
Homing = 32,
}
/// <summary>
/// 0.3 坐标模式
/// </summary>
public enum PositionMode
{
/// <summary>
/// 绝对位置模式
/// </summary>
[Description("绝对位置模式")]
Position_Absolute = 0,
/// <summary>
/// 相对位置模式
/// </summary>
[Description("相对位置模式")]
Position_Opposite = 1,
}
/// <summary>
/// 0.4 单轴点动曲线类型
/// </summary>
public enum Profile
{
/// <summary>
/// T型曲线
/// </summary>
[Description("T型曲线")]
Profile_T = 0,
/// <summary>
/// S型曲线
/// </summary>
[Description("S型曲线")]
Profile_S = 1,
}
/// <summary>
/// 3.1 伺服使能设置
/// </summary>
public enum ServoLogic
{
/// <summary>
/// 触点闭合
/// </summary>
[Description("触点闭合")]
Servo_Close = 0,
/// <summary>
/// 触点打开
/// </summary>
[Description("触点打开")]
Servo_Open = 1,
}
/// <summary>
/// 3.2 报警复位电平设置
/// </summary>
public enum AlarmLogic
{
/// <summary>
/// 触点闭合
/// </summary>
[Description("触点闭合")]
Alarm_Close = 0,
/// <summary>
/// 触点打开
/// </summary>
[Description("触点打开")]
Alarm_Open = 1,
}
/// <summary>
/// 3.6
/// </summary>
public enum HomeState
{
/// <summary>
/// 触点闭合,硬件灯亮
/// </summary>
[Description("触点闭合,硬件灯亮")]
Home_Close = 0,
/// <summary>
/// 触点打开,硬件灯灭
/// </summary>
[Description("触点打开,硬件灯灭")]
Home_Open = 1,
}
/// <summary>
/// 4.1 脉冲模式
/// </summary>
public enum PulseMode
{
/// <summary>
/// 脉冲方向(默认)
/// </summary>
[Description("模式0")]
Pulse_Dir_H = 0,
/// <summary>
/// 脉冲方向
/// </summary>
[Description("模式1")]
Pulse_Dir_L = 1,
/// <summary>
/// 双脉冲
/// </summary>
[Description("模式2")]
Pulse_CW_CCW = 2,
/// <summary>
/// 双脉冲
/// </summary>
[Description("模式3")]
Pulse_CCW_CW = 3,
/// <summary>
/// AB相位
/// </summary>
[Description("模式4")]
Pulse_AB = 4,
/// <summary>
/// AB相位
/// </summary>
[Description("模式5")]
Pulse_BA = 5,
}
/****************************************************************************************************************
5
*****************************************************************************************************************/
//5.1 EMG_Mode
public enum EMG_Mode
{
[Description("不使用紧急停止功能")]
EMG_Trigger_Close = 0, //不使用紧急停止功能
[Description("低电平触发紧急停止")]
EMG_Trigger_Low_IMD = 1, //低电平触发紧急停止
[Description("低电平触发减速停止")]
EMG_Trigger_Low_DEC = 2,//低电平触发减速停止
[Description("高电平触发紧急停止")]
EMG_Trigger_High_IMD = 3, //高电平触发紧急停止
}
/// <summary>
/// 6.1.1 正负限位触发电平
/// </summary>
public enum LimitLogic
{
/// <summary>
/// 低电平触发
/// </summary>
[Description("低电平触发")]
Low_Logic = 0,
/// <summary>
/// 高电平触发
/// </summary>
[Description("高电平触发")]
High_Logic = 1,
}
/// <summary>
/// 6.1.2 回零限位触发电平
/// </summary>
public enum HomeLogic
{
/// <summary>
/// 低电平触发
/// </summary>
[Description("低电平触发")]
Low_Logic = 0,
/// <summary>
/// 高电平触发
/// </summary>
[Description("高电平触发")]
High_Logic = 1,
}
/// <summary>
/// 6.1.3 Index触发电平
/// </summary>
public enum IndexLogic
{
/// <summary>
/// 低电平触发
/// </summary>
[Description("低电平触发")]
Low_Logic = 0,
/// <summary>
/// 高电平触发
/// </summary>
[Description("高电平触发")]
High_Logic = 1,
}
}

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

@ -1,5 +1,5 @@
using System.ComponentModel;
using System.Drawing.Imaging;
using DH.Commons.Enums;
using DVPCameraType;
using OpenCvSharp;
@ -21,8 +21,12 @@ namespace DH.Devices.Camera
public string SerialNumber { get; set; } = string.Empty;
public string CameraName { get; set; } = string.Empty;
public dvpStreamFormat dvpStreamFormat = dvpStreamFormat.S_RGB24;
public string CameraIP { get; set; } = string.Empty;
public string ComputerIP { get; set; } = string.Empty;
// public StreamFormat dvpStreamFormat = dvpStreamFormat.;
public dvpStreamFormat dvpStreamFormat = dvpStreamFormat.S_RGB24;
[Category("采图模式")]
[Description("是否传感器直接硬触发。true传感器硬触发不通过软件触发false通过软件触发IO 的硬触发模式")]
[DisplayName("是否传感器直接硬触发")]

View File

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<BaseOutputPath>..\</BaseOutputPath>
@ -11,16 +12,29 @@
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<ItemGroup>
<Compile Include="CameraBase.cs" />
<Compile Include="Do3ThinkCamera.cs" />
<Compile Include="HikVisionCamera.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="OpenCvSharp4" Version="4.10.0.20241108" />
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.10.0.20241108" />
<PackageReference Include="System.Drawing.Common" Version="9.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DH.Commons\DH.Commons.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="DVPCameraCS64">
<HintPath>..\X64\Debug\DVPCameraCS64.dll</HintPath>
</Reference>
<Reference Include="MvCameraControl.Net">
<HintPath>..\x64\Debug\MvCameraControl.Net.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View File

@ -12,7 +12,7 @@ namespace DH.Devices.Camera
public class Do3ThinkCamera : CameraBase
{
private dvpCameraInfo stDevInfo = new dvpCameraInfo();
private dvpStatus nRet = dvpStatus.DVP_STATUS_OK;
private DVPCamera.dvpEventCallback pCallBackFunc;
@ -24,7 +24,7 @@ namespace DH.Devices.Camera
public Double m_dfDisplayCount = 0;
public Do3ThinkCamera()
{
}
@ -57,7 +57,7 @@ namespace DH.Devices.Camera
throw new Exception($"Create device failed:{nRet:x8}");
}
nRet = DVPCamera.dvpSetTargetFormat(m_handle, dvpStreamFormat);
nRet = DVPCamera.dvpSetTargetFormat(m_handle, (dvpStreamFormat)dvpStreamFormat);
if (dvpStatus.DVP_STATUS_OK != nRet)
{
throw new Exception($"Set image format failed:{nRet:x8}");
@ -66,7 +66,7 @@ namespace DH.Devices.Camera
dvpCameraInfo camerainfo = new dvpCameraInfo();
nRet = DVPCamera.dvpGetCameraInfo(m_handle, ref camerainfo);
SerialNumber= camerainfo.SerialNumber;
SerialNumber = camerainfo.SerialNumber;
// ch:注册异常回调函数 | en:Register Exception Callback
//nRet = DVPCamera.dvpRegisterEventCallback(m_handle, pCallBackFunc, dvpEvent.EVENT_DISCONNECTED, IntPtr.Zero);
//if (nRet != dvpStatus.DVP_STATUS_OK)
@ -87,82 +87,82 @@ namespace DH.Devices.Camera
//}
//else
//{
// ch:设置触发模式为on || en:set trigger mode as on
nRet = DVPCamera.dvpSetTriggerState(m_handle, true);
if (dvpStatus.DVP_STATUS_OK != nRet)
{
throw new Exception("Set TriggerMode failed!");
}
// ch:设置触发模式为on || en:set trigger mode as on
nRet = DVPCamera.dvpSetTriggerState(m_handle, true);
if (dvpStatus.DVP_STATUS_OK != nRet)
{
throw new Exception("Set TriggerMode failed!");
}
// 硬触发
//if (IIConfig.IsHardwareTrigger)
//{
// ch:触发源选择:1 - Line1; | en:Trigger source select:1 - Line1;
nRet = DVPCamera.dvpSetTriggerSource(m_handle, dvpTriggerSource.TRIGGER_SOURCE_LINE1);
if (dvpStatus.DVP_STATUS_OK != nRet)
{
throw new Exception("Set Line1 Trigger failed!");
}
// 硬触发
//if (IIConfig.IsHardwareTrigger)
//{
// ch:触发源选择:1 - Line1; | en:Trigger source select:1 - Line1;
nRet = DVPCamera.dvpSetTriggerSource(m_handle, dvpTriggerSource.TRIGGER_SOURCE_LINE1);
if (dvpStatus.DVP_STATUS_OK != nRet)
{
throw new Exception("Set Line1 Trigger failed!");
}
// ch:注册回调函数 | en:Register image callback
ImageCallback = new DVPCamera.dvpStreamCallback(ImageCallbackFunc);
nRet = DVPCamera.dvpRegisterStreamCallback(m_handle, ImageCallback, dvpStreamEvent.STREAM_EVENT_PROCESSED, IntPtr.Zero);
if (dvpStatus.DVP_STATUS_OK != nRet)
{
throw new Exception("Register image callback failed!");
}
//}
//else // 软触发
//{
// nRet = DVPCamera.dvpSetTriggerSource(m_handle, dvpTriggerSource.TRIGGER_SOURCE_SOFTWARE);
// if (dvpStatus.DVP_STATUS_OK != nRet)
// {
// throw new Exception("Set Software Trigger failed!");
// }
//}
// ch:注册回调函数 | en:Register image callback
ImageCallback = new DVPCamera.dvpStreamCallback(ImageCallbackFunc);
nRet = DVPCamera.dvpRegisterStreamCallback(m_handle, ImageCallback, dvpStreamEvent.STREAM_EVENT_PROCESSED, IntPtr.Zero);
if (dvpStatus.DVP_STATUS_OK != nRet)
{
throw new Exception("Register image callback failed!");
}
//}
//else // 软触发
//{
// nRet = DVPCamera.dvpSetTriggerSource(m_handle, dvpTriggerSource.TRIGGER_SOURCE_SOFTWARE);
// if (dvpStatus.DVP_STATUS_OK != nRet)
// {
// throw new Exception("Set Software Trigger failed!");
// }
//}
// ch:开启抓图 || en: start grab image
nRet = DVPCamera.dvpStart(m_handle);
if (dvpStatus.DVP_STATUS_OK != nRet)
{
throw new Exception($"Start grabbing failed:{nRet:x8}");
}
//// 曝光
//if (IIConfig.DefaultExposure != 0)
//{
// SetExposure(IIConfig.DefaultExposure);
//}
//// 增益
//if (IIConfig.Gain >= 0)
//{
// SetGain(IIConfig.Gain);
//}
//SetPictureRoi(IIConfig.VelocityPara.A_Pic_X, IIConfig.VelocityPara.A_Pic_Y, IIConfig.VelocityPara.Width, IIConfig.VelocityPara.Hight);
// ch:开启抓图 || en: start grab image
nRet = DVPCamera.dvpStart(m_handle);
if (dvpStatus.DVP_STATUS_OK != nRet)
{
throw new Exception($"Start grabbing failed:{nRet:x8}");
}
//// 曝光
//if (IIConfig.DefaultExposure != 0)
//{
// SetExposure(IIConfig.DefaultExposure);
//}
//// 增益
//if (IIConfig.Gain >= 0)
//{
// SetGain(IIConfig.Gain);
//}
//SetPictureRoi(IIConfig.VelocityPara.A_Pic_X, IIConfig.VelocityPara.A_Pic_Y, IIConfig.VelocityPara.Width, IIConfig.VelocityPara.Hight);
//// 设置 触发延迟
//if (IIConfig.TriggerDelay > 0)
//{
// nRet = DVPCamera.dvpSetTriggerDelay(m_handle, IIConfig.TriggerDelay);
// if (nRet != dvpStatus.DVP_STATUS_OK)
// {
// throw new Exception("Set TriggerDelay failed!");
// }
//}
//// 设置 触发延迟
//if (IIConfig.TriggerDelay > 0)
//{
// nRet = DVPCamera.dvpSetTriggerDelay(m_handle, IIConfig.TriggerDelay);
// if (nRet != dvpStatus.DVP_STATUS_OK)
// {
// throw new Exception("Set TriggerDelay failed!");
// }
//}
//// 信号消抖
//if (IIConfig.LineDebouncerTime > 0)
//{
// nRet = DVPCamera.dvpSetTriggerJitterFilter(m_handle, IIConfig.LineDebouncerTime);
// if (nRet != dvpStatus.DVP_STATUS_OK)
// {
// throw new Exception($"LineDebouncerTime set failed:{nRet}");
// }
//}
//// 信号消抖
//if (IIConfig.LineDebouncerTime > 0)
//{
// nRet = DVPCamera.dvpSetTriggerJitterFilter(m_handle, IIConfig.LineDebouncerTime);
// if (nRet != dvpStatus.DVP_STATUS_OK)
// {
// throw new Exception($"LineDebouncerTime set failed:{nRet}");
// }
//}
//IIConfig.PropertyChanged -= IIConfig_PropertyChanged;
//IIConfig.PropertyChanged += IIConfig_PropertyChanged;
//IIConfig.PropertyChanged -= IIConfig_PropertyChanged;
//IIConfig.PropertyChanged += IIConfig_PropertyChanged;
return true;
return true;
}
catch
{
@ -258,20 +258,20 @@ namespace DH.Devices.Camera
/// <exception cref="Exception"></exception>
private void SetExposure(double exposure)
{
// 关闭自动曝光
nRet = DVPCamera.dvpSetAeOperation(m_handle, dvpAeOperation.AE_OP_OFF);
if (nRet != dvpStatus.DVP_STATUS_OK)
{
throw new Exception($"Exposure set failed:{nRet}");
}
// 设置曝光值
nRet = DVPCamera.dvpSetExposure(m_handle, exposure);
if (nRet != dvpStatus.DVP_STATUS_OK)
{
throw new Exception($"Exposure set failed:{nRet}");
}
}
// 关闭自动曝光
nRet = DVPCamera.dvpSetAeOperation(m_handle, dvpAeOperation.AE_OP_OFF);
if (nRet != dvpStatus.DVP_STATUS_OK)
{
throw new Exception($"Exposure set failed:{nRet}");
}
// 设置曝光值
nRet = DVPCamera.dvpSetExposure(m_handle, exposure);
if (nRet != dvpStatus.DVP_STATUS_OK)
{
throw new Exception($"Exposure set failed:{nRet}");
}
}
/// <summary>
@ -308,15 +308,23 @@ namespace DH.Devices.Camera
public int ImageCallbackFunc(uint handle, dvpStreamEvent _event, IntPtr pContext, ref dvpFrame refFrame, IntPtr pBuffer)
{
Mat cvImage = new Mat();
if (this.CameraName.Equals("Cam1"))
{
Console.WriteLine( );
}
if (this.CameraName.Equals("Cam2"))
{
Console.WriteLine();
}
try
{
Interlocked.Increment(ref SnapshotCount);
int nWidth = refFrame.iWidth;
int nHeight = refFrame.iHeight;
Mat cvImage = new Mat();
// 根据图像格式创建Mat
switch (refFrame.format)
@ -335,9 +343,11 @@ namespace DH.Devices.Camera
break;
default:
throw new NotSupportedException($"Unsupported format: {refFrame.format}");
cvImage = Mat.FromPixelData(nHeight, nWidth, MatType.CV_8UC1, pBuffer);
break;
}
OnHImageOutput?.Invoke(DateTime.Now, this, cvImage);
Mat smat = cvImage.Clone();
OnHImageOutput?.Invoke(DateTime.Now, this, smat);
@ -347,7 +357,11 @@ namespace DH.Devices.Camera
}
catch (Exception ex)
{
}
finally
{
cvImage?.Dispose();
}
return 0;
}

View File

@ -0,0 +1,492 @@
using System.Diagnostics;
using OpenCvSharp;
using MvCamCtrl.NET;
using System.Runtime.InteropServices;
using System.Xml.Linq;
using DH.Commons.Enums;
using static MvCamCtrl.NET.MyCamera;
namespace DH.Devices.Camera
{
public class HikVisionCamera : CameraBase
{
readonly MyCamera cameraObj = new MyCamera();
MyCamera.MV_CC_DEVICE_INFO stDevInfo = new MyCamera.MV_CC_DEVICE_INFO();
int nRet = MyCamera.MV_OK;
MyCamera.cbExceptiondelegate pCallBackFunc;
public MyCamera.cbOutputExdelegate ImageCallback;
MyCamera.MV_FRAME_OUT _frame = new MyCamera.MV_FRAME_OUT();
readonly ManualResetEvent _snapHandle = new ManualResetEvent(false);
bool _snapFlag = false;
public HikVisionCamera()
{
}
public override bool CameraConnect()
{
try
{
pCallBackFunc = new MyCamera.cbExceptiondelegate(cbExceptiondelegate);
#region IP连接相机
stDevInfo.nTLayerType = MyCamera.MV_GIGE_DEVICE;
MyCamera.MV_GIGE_DEVICE_INFO stGigEDev = new MyCamera.MV_GIGE_DEVICE_INFO();
var parts = CameraIP.Split('.');
int nIp1 = Convert.ToInt32(parts[0]);
int nIp2 = Convert.ToInt32(parts[1]);
int nIp3 = Convert.ToInt32(parts[2]);
int nIp4 = Convert.ToInt32(parts[3]);
stGigEDev.nCurrentIp = (uint)((nIp1 << 24) | (nIp2 << 16) | (nIp3 << 8) | nIp4);
parts = ComputerIP.Split('.');
nIp1 = Convert.ToInt32(parts[0]);
nIp2 = Convert.ToInt32(parts[1]);
nIp3 = Convert.ToInt32(parts[2]);
nIp4 = Convert.ToInt32(parts[3]);
stGigEDev.nNetExport = (uint)((nIp1 << 24) | (nIp2 << 16) | (nIp3 << 8) | nIp4);
IntPtr stGigeInfoPtr = Marshal.AllocHGlobal(216);
Marshal.StructureToPtr(stGigEDev, stGigeInfoPtr, false);
stDevInfo.SpecialInfo.stGigEInfo = new Byte[540];
Marshal.Copy(stGigeInfoPtr, stDevInfo.SpecialInfo.stGigEInfo, 0, 540);
//释放内存空间
Marshal.FreeHGlobal(stGigeInfoPtr);
#endregion
// ch:创建设备 | en: Create device
nRet = cameraObj.MV_CC_CreateDevice_NET(ref stDevInfo);
if (MyCamera.MV_OK != nRet)
{
throw new Exception($"Create device failed:{nRet:x8}");
}
// ch:打开设备 | en:Open device
nRet = cameraObj.MV_CC_OpenDevice_NET();
if (MyCamera.MV_OK != nRet)
{
throw new Exception($"Open device failed:{nRet:x8}");
}
// ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
if (stDevInfo.nTLayerType == MyCamera.MV_GIGE_DEVICE)
{
int nPacketSize = cameraObj.MV_CC_GetOptimalPacketSize_NET();
if (nPacketSize > 0)
{
nRet = cameraObj.MV_CC_SetIntValue_NET("GevSCPSPacketSize", (uint)nPacketSize);
if (nRet != MyCamera.MV_OK)
{
Console.WriteLine("Warning: Set Packet Size failed {0:x8}", nRet);
}
}
else
{
Console.WriteLine("Warning: Get Packet Size failed {0:x8}", nPacketSize);
}
}
// ch:注册异常回调函数 | en:Register Exception Callback
nRet = cameraObj.MV_CC_RegisterExceptionCallBack_NET(pCallBackFunc, IntPtr.Zero);
if (MyCamera.MV_OK != nRet)
{
throw new Exception($"Register expection callback failed:{nRet}");
}
GC.KeepAlive(pCallBackFunc);
// ch:设置采集连续模式 | en:Set Continues Aquisition Mode
cameraObj.MV_CC_SetEnumValue_NET("AcquisitionMode", 2);// ch:工作在连续模式 | en:Acquisition On Continuous Mode
//if (IIConfig.IsContinueMode)
//{
// cameraObj.MV_CC_SetEnumValue_NET("TriggerMode", 0); // ch:连续模式 | en:Continuous
// // ch:注册回调函数 | en:Register image callback
// ImageCallback = new MyCamera.cbOutputExdelegate(ImageCallbackFunc);
// nRet = cameraObj.MV_CC_RegisterImageCallBackEx_NET(ImageCallback, IntPtr.Zero);
// if (MyCamera.MV_OK != nRet)
// {
// throw new Exception("Register image callback failed!");
// }
//}
//else
//{
// ch:设置触发模式为off || en:set trigger mode as off
nRet = cameraObj.MV_CC_SetEnumValue_NET("TriggerMode", 1);
if (MyCamera.MV_OK != nRet)
{
throw new Exception("Set TriggerMode failed!");
}
//if (IIConfig.IsHardwareTrigger)
//{
// ch:触发源选择:0 - Line0; | en:Trigger source select:0 - Line0;
// 1 - Line1;
// 2 - Line2;
// 3 - Line3;
// 4 - Counter;
// 7 - Software;
nRet = cameraObj.MV_CC_SetEnumValue_NET("TriggerSource", 0);
if (MyCamera.MV_OK != nRet)
{
throw new Exception("Set Line0 Trigger failed!");
}
// ch:注册回调函数 | en:Register image callback
ImageCallback = new MyCamera.cbOutputExdelegate(ImageCallbackFunc);
nRet = cameraObj.MV_CC_RegisterImageCallBackEx_NET(ImageCallback, IntPtr.Zero);
if (MyCamera.MV_OK != nRet)
{
throw new Exception("Register image callback failed!");
}
//}
//else
//{
// nRet = cameraObj.MV_CC_SetEnumValue_NET("TriggerSource", 7);
// if (MyCamera.MV_OK != nRet)
// {
// throw new Exception("Set Software Trigger failed!");
// }
//}
//}
// ch:开启抓图 || en: start grab image
nRet = cameraObj.MV_CC_StartGrabbing_NET();
if (MyCamera.MV_OK != nRet)
{
throw new Exception($"Start grabbing failed:{nRet:x8}");
}
//if (IConfig.DefaultExposure != 0)
//{
// cameraObj.MV_CC_SetEnumValue_NET("ExposureAuto", 0);
// nRet = cameraObj.MV_CC_SetFloatValue_NET("ExposureTime", IConfig.DefaultExposure);
// if (nRet != MyCamera.MV_OK)
// {
// throw new Exception($"Exposure set failed:{nRet}");
// }
//}
//if (IIConfig.Gain >= 0)
//{
// nRet = cameraObj.MV_CC_SetFloatValue_NET("Gain", IIConfig.Gain);
// if (nRet != MyCamera.MV_OK)
// {
// throw new Exception($"Gain set failed:{nRet}");
// }
//}
// 设置 触发延迟
//if (IIConfig.TriggerDelay > 0)
//{
// nRet = cameraObj.MV_CC_SetFloatValue_NET("TriggerDelay", IIConfig.TriggerDelay);
// if (MyCamera.MV_OK != nRet)
// {
// throw new Exception("Set TriggerDelay failed!");
// }
//}
//if (IIConfig.LineDebouncerTime > 0)
//{
// nRet = cameraObj.MV_CC_SetIntValue_NET("LineDebouncerTime", (uint)IIConfig.LineDebouncerTime);
// if (nRet != MyCamera.MV_OK)
// {
// throw new Exception($"LineDebouncerTime set failed:{nRet}");
// }
//}
//IIConfig.PropertyChanged -= IIConfig_PropertyChanged;
//IIConfig.PropertyChanged += IIConfig_PropertyChanged;
return true;
}
catch (Exception ex)
{
return false;
}
}
private void IIConfig_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
//if (e.PropertyName == "IsHardwareTrigger" && !IIConfig.IsContinueMode)
//{
// // ch:停止抓图 | en:Stop grab image
// nRet = cameraObj.MV_CC_StopGrabbing_NET();
// if (MyCamera.MV_OK != nRet)
// {
// throw new Exception($"Stop grabbing failed{nRet:x8}");
// }
// if (IIConfig.IsHardwareTrigger)
// {
// // ch:触发源选择:0 - Line0; | en:Trigger source select:0 - Line0;
// // 1 - Line1;
// // 2 - Line2;
// // 3 - Line3;
// // 4 - Counter;
// // 7 - Software;
// nRet = cameraObj.MV_CC_SetEnumValue_NET("TriggerSource", 0);
// if (MyCamera.MV_OK != nRet)
// {
// throw new Exception("Set Line0 Trigger failed!");
// }
// // ch:注册回调函数 | en:Register image callback
// ImageCallback = new MyCamera.cbOutputExdelegate(ImageCallbackFunc);
// nRet = cameraObj.MV_CC_RegisterImageCallBackEx_NET(ImageCallback, IntPtr.Zero);
// if (MyCamera.MV_OK != nRet)
// {
// throw new Exception("Register image callback failed!");
// }
// }
// else
// {
// nRet = cameraObj.MV_CC_SetEnumValue_NET("TriggerSource", 7);
// if (MyCamera.MV_OK != nRet)
// {
// throw new Exception("Set Software Trigger failed!");
// }
// }
// // ch:开启抓图 || en: start grab image
// nRet = cameraObj.MV_CC_StartGrabbing_NET();
// if (MyCamera.MV_OK != nRet)
// {
// throw new Exception($"Start grabbing failed:{nRet:x8}");
// }
// if (IConfig.DefaultExposure != 0)
// {
// cameraObj.MV_CC_SetEnumValue_NET("ExposureAuto", 0);
// nRet = cameraObj.MV_CC_SetFloatValue_NET("ExposureTime", IConfig.DefaultExposure);
// if (nRet != MyCamera.MV_OK)
// {
// throw new Exception($"Exposure set failed:{nRet}");
// }
// }
// if (IIConfig.Gain >= 0)
// {
// nRet = cameraObj.MV_CC_SetFloatValue_NET("Gain", IIConfig.Gain);
// if (nRet != MyCamera.MV_OK)
// {
// throw new Exception($"Gain set failed:{nRet}");
// }
// }
// // 设置 触发延迟
// if (IIConfig.TriggerDelay > 0)
// {
// nRet = cameraObj.MV_CC_SetFloatValue_NET("TriggerDelay", IIConfig.TriggerDelay);
// if (MyCamera.MV_OK != nRet)
// {
// throw new Exception("Set TriggerDelay failed!");
// }
// }
// if (IIConfig.LineDebouncerTime > 0)
// {
// nRet = cameraObj.MV_CC_SetIntValue_NET("LineDebouncerTime", (uint)IIConfig.LineDebouncerTime);
// if (nRet != MyCamera.MV_OK)
// {
// throw new Exception($"LineDebouncerTime set failed:{nRet}");
// }
// }
//}
}
public override bool CameraDisConnect()
{
//IIConfig.PropertyChanged -= IIConfig_PropertyChanged;
//base.Stop();
// ch:停止抓图 | en:Stop grab image
try
{
nRet = cameraObj.MV_CC_StopGrabbing_NET();
if (MyCamera.MV_OK != nRet)
{
throw new Exception($"Stop grabbing failed{nRet:x8}");
}
// ch:关闭设备 | en:Close device
nRet = cameraObj.MV_CC_CloseDevice_NET();
if (MyCamera.MV_OK != nRet)
{
throw new Exception($"Close device failed{nRet:x8}");
}
// ch:销毁设备 | en:Destroy device
nRet = cameraObj.MV_CC_DestroyDevice_NET();
if (MyCamera.MV_OK != nRet)
{
throw new Exception($"Destroy device failed:{nRet:x8}");
}
return true;
}
catch (Exception ex)
{
return false ;
}
}
void ImageCallbackFunc(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
{
Mat cvImage = new Mat();
try
{
Interlocked.Increment(ref SnapshotCount);
int nWidth = pFrameInfo.nWidth;
int nHeight = pFrameInfo.nHeight;
switch (pFrameInfo.enPixelType)
{
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR8:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG8:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB8:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG8:
cvImage = Mat.FromPixelData(nHeight, nWidth, MatType.CV_8UC1, pData);
break;
case MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed:
cvImage = Mat.FromPixelData(nHeight, nWidth, MatType.CV_8UC3, pData);
Cv2.CvtColor(cvImage, cvImage, ColorConversionCodes.RGB2BGR);
break;
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BGR8_Packed:
cvImage = Mat.FromPixelData(nHeight, nWidth, MatType.CV_8UC3, pData);
break;
case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8:
cvImage = Mat.FromPixelData(nHeight, nWidth, MatType.CV_8UC1, pData);
break;
default:
throw new NotSupportedException($"Unsupported pixel type: {pFrameInfo.enPixelType}");
}
OnHImageOutput?.Invoke(DateTime.Now, this, cvImage);
}
catch (Exception ex)
{
}
finally
{
cvImage?.Dispose();
}
}
public MvGvspPixelType GetMvGvspPixelType(StreamFormat streamFormat)
{
switch (streamFormat)
{
// 原始数据格式映射
case StreamFormat.S_RAW8:
return MvGvspPixelType.PixelType_Gvsp_Mono8;
case StreamFormat.S_RAW10:
return MvGvspPixelType.PixelType_Gvsp_Mono10_Packed;
case StreamFormat.S_RAW12:
return MvGvspPixelType.PixelType_Gvsp_Mono12_Packed;
case StreamFormat.S_RAW14:
return MvGvspPixelType.PixelType_Gvsp_Mono14;
case StreamFormat.S_RAW16:
return MvGvspPixelType.PixelType_Gvsp_Mono16;
// RGB/BGR格式映射
case StreamFormat.S_BGR24:
return MvGvspPixelType.PixelType_Gvsp_BGR8_Packed;
case StreamFormat.S_BGR32:
return MvGvspPixelType.PixelType_Gvsp_BGRA8_Packed;
case StreamFormat.S_RGB24:
return MvGvspPixelType.PixelType_Gvsp_RGB8_Packed;
case StreamFormat.S_RGB32:
return MvGvspPixelType.PixelType_Gvsp_RGBA8_Packed;
case StreamFormat.S_BGR48:
return MvGvspPixelType.PixelType_Gvsp_BGR10_Packed;
case StreamFormat.S_RGB48:
return MvGvspPixelType.PixelType_Gvsp_RGB16_Packed;
// YUV格式映射
case StreamFormat.S_YCBCR_411:
return MvGvspPixelType.PixelType_Gvsp_YCBCR411_8_CBYYCRYY;
case StreamFormat.S_YCBCR_422:
return MvGvspPixelType.PixelType_Gvsp_YUV422_YUYV_Packed;
case StreamFormat.S_YCBCR_444:
return MvGvspPixelType.PixelType_Gvsp_YUV444_Packed;
// 灰度图像映射
case StreamFormat.S_MONO8:
return MvGvspPixelType.PixelType_Gvsp_Mono8;
case StreamFormat.S_MONO10:
return MvGvspPixelType.PixelType_Gvsp_Mono10;
case StreamFormat.S_MONO12:
return MvGvspPixelType.PixelType_Gvsp_Mono12;
case StreamFormat.S_MONO14:
return MvGvspPixelType.PixelType_Gvsp_Mono14;
case StreamFormat.S_MONO16:
return MvGvspPixelType.PixelType_Gvsp_Mono16;
// 特殊格式映射
case StreamFormat.S_B8_G8_R8:
return MvGvspPixelType.PixelType_Gvsp_RGB8_Planar;
case StreamFormat.S_B16_G16_R16:
return MvGvspPixelType.PixelType_Gvsp_RGB16_Planar;
default:
throw new ArgumentException($"Unsupported stream format: {streamFormat}");
}
}
// ch:回调函数 | en:Callback function
private void cbExceptiondelegate(uint nMsgType, IntPtr pUser)
{
//if (nMsgType == MyCamera.MV_EXCEPTION_DEV_DISCONNECT)
//{
// if (CurrentState != EnumHelper.DeviceState.DSClose)
// {
// int reTryTimes = 3;
// do
// {
// try
// {
// Task.Delay(1000).Wait();
// Stop();
// Start();
// reTryTimes = -1;
// }
// catch (Exception ex)
// {
// reTryTimes--;
// if (reTryTimes > 0)
// {
// LogAsync(DateTime.Now, LogLevel.Information, $"{this.Name}重新连接异常,{ex.GetExceptionMessage()}");
// }
// else
// {
// throw ex;
// }
// }
// } while (reTryTimes > 0);
// }
//}
}
}
}

View File

@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<BaseOutputPath>..\</BaseOutputPath>
<AppendTargetFrameworkToOutputPath>output</AppendTargetFrameworkToOutputPath>
<UseWindowsForms>true</UseWindowsForms>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<ItemGroup>
<Compile Include="MCDLL_NET.cs" />
<Compile Include="MCDLL_NET_Code.cs" />
<Compile Include="MCDLL_NET_SORTING.cs" />
<Compile Include="MotionBase.cs" />
<Compile Include="SLDMotion.cs" />
<Compile Include="SolidMotionCardEnum.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DH.Commons\DH.Commons.csproj" />
</ItemGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DH.Devices.Motion
{
public enum FuncRet
{
/// <summary>
/// 正常命令执行成功
/// </summary>
Function_Success = 0,
/// <summary>
/// 打开站点不成功
/// </summary>
ERR_Open_Station_Fail = -18,
}
}

View File

@ -0,0 +1,338 @@
using System.Runtime.InteropServices;
/********************************************************************************************************************************************************************
1 ,
2 10,
3 便使
4 OK与NG占用同一个通道
********************************************************************************************************************************************************************/
namespace MCDLL_NET
{
public class CMCDLL_NET_Sorting
{
/********************************************************************************************************************************************************************
1
********************************************************************************************************************************************************************/
//1.0 筛选功能初始化函数 必须在 MCF_Open_Net() 前调用
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Init_Net")]
public static extern short MCF_Sorting_Init_Net(ushort StationNumber = 0);
//1.1 控制卡打开关闭函数 [1,100] [0,99] 宏定义1.1
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Open_Net")]
public static extern short MCF_Open_Net(ushort Connection_Number, ref ushort Station_Number, ref ushort Station_Type);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Open_Net")]
public static extern short MCF_Get_Open_Net(ref ushort Connection_Number, ref ushort Station_Number, ref ushort Station_Type);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Close_Net")]
public static extern short MCF_Close_Net();
//1.2 链接超时紧急停止函数 [0,60000]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_Link_TimeOut_Net")]
public static extern short MCF_Set_Link_TimeOut_Net(uint Time_1MS, uint TimeOut_Output, ushort StationNumber = 0);
// 链接超时紧急停止触发使能函数
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_Trigger_Output_Bit_Net")]
public static extern short MCF_Set_Trigger_Output_Bit_Net(ushort Bit_Output_Number, ushort Bit_Output_Enable, ushort StationNumber = 0);
//1.3 链接监测函数
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Link_State_Net")]
public static extern short MCF_Get_Link_State_Net(ushort StationNumber = 0);
/********************************************************************************************************************************************************************
2
********************************************************************************************************************************************************************/
//2.1 通用IO全部输出函数 [OUT31,OUT0] [0,99] [10000,10099]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_Output_Net")]
public static extern short MCF_Set_Output_Net(uint All_Output_Logic, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Output_Net")]
public static extern short MCF_Get_Output_Net(ref uint All_Output_Logic, ushort StationNumber = 0);
//2.2 通用IO按位输出函数 宏定义2.3.1 宏定义2.3.2 [0,99] [10000,10099]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_Output_Bit_Net")]
public static extern short MCF_Set_Output_Bit_Net(ushort Bit_Output_Number, ushort Bit_Output_Logic, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Output_Bit_Net")]
public static extern short MCF_Get_Output_Bit_Net(ushort Bit_Output_Number, ref ushort Bit_Output_Logic, ushort StationNumber = 0);
//2.4 通用IO全部输入函数 [Input31,Input0] [Input48,Input32] [0,99] [10000,10099]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Input_Net")]
public static extern short MCF_Get_Input_Net(ref uint All_Input_Logic1, ref uint All_Input_Logic2, ushort StationNumber = 0);
//2.5 通用IO按位输入函数 宏定义2.4.1 宏定义2.4.2 [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Input_Bit_Net")]
public static extern short MCF_Get_Input_Bit_Net(ushort Bit_Input_Number, ref ushort Bit_Input_Logic, ushort StationNumber = 0);
/********************************************************************************************************************************************************************
3
********************************************************************************************************************************************************************/
//3.1 伺服使能设置函数 宏定义0.0 宏定义3.1 [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_Servo_Enable_Net")]
public static extern short MCF_Set_Servo_Enable_Net(ushort Axis, ushort Servo_Logic, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Servo_Enable_Net")]
public static extern short MCF_Get_Servo_Enable_Net(ushort Axis, ref ushort Servo_Logic, ushort StationNumber = 0);
//3.2 伺服报警复位设置函数 宏定义0.0 宏定义3.2 [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_Servo_Alarm_Reset_Net")]
public static extern short MCF_Set_Servo_Alarm_Reset_Net(ushort Axis, ushort Alarm_Logic, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Servo_Alarm_Reset_Net")]
public static extern short MCF_Get_Servo_Alarm_Reset_Net(ushort Axis, ref ushort Alarm_Logic, ushort StationNumber = 0);
//3.3 伺服报警输入获取函数 宏定义0.0 宏定义3.3 [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Servo_Alarm_Net")]
public static extern short MCF_Get_Servo_Alarm_Net(ushort Axis, ref ushort Servo_Alarm_State, ushort StationNumber = 0);
/********************************************************************************************************************************************************************
4
********************************************************************************************************************************************************************/
//4.1 脉冲通道输出设置函数 宏定义0.0 宏定义4.1 [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_Pulse_Mode_Net")]
public static extern short MCF_Set_Pulse_Mode_Net(ushort Axis, uint Pulse_Mode, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Pulse_Mode_Net")]
public static extern short MCF_Get_Pulse_Mode_Net(ushort Axis, ref uint Pulse_Mode, ushort StationNumber = 0);
//4.2 位置设置函数 宏定义0.0 [-2^31,(2^31-1)] [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_Position_Net")]
public static extern short MCF_Set_Position_Net(ushort Axis, int Position, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Position_Net")]
public static extern short MCF_Get_Position_Net(ushort Axis, ref int Position, ushort StationNumber = 0);
//4.3 编码器设置函数 宏定义0.0 [-2^31,(2^31-1)] [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_Encoder_Net")]
public static extern short MCF_Set_Encoder_Net(ushort Axis, int Encoder, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Encoder_Net")]
public static extern short MCF_Get_Encoder_Net(ushort Axis, ref int Encoder, ushort StationNumber = 0);
//4.4 速度获取 宏定义0.0 [-2^15,(2^15-1)] [-2^15,(2^15-1)] [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Vel_Net")]
public static extern short MCF_Get_Vel_Net(ushort Axis, ref double Command_Vel, ref double Encode_Vel, ushort StationNumber = 0);
/********************************************************************************************************************************************************************
5
********************************************************************************************************************************************************************/
//5.1 通用IO输入复用做为紧急停止函数 宏定义2.4.1 宏定义5.1 [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_EMG_Bit_Net")]
public static extern short MCF_Set_EMG_Bit_Net(ushort EMG_Input_Number, ushort EMG_Mode, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_EMG_Output_Net")]
public static extern short MCF_Set_EMG_Output_Net(ushort EMG_Input_Number, ushort EMG_Mode, uint EMG_Output, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_EMG_Output_Enable_Net")]
public static extern short MCF_Set_EMG_Output_Enable_Net(ushort Bit_Output_Number, ushort Bit_Output_Enable, ushort StationNumber = 0);
//5.11 轴状态触发停止运动查询函数 宏定义0.0 MC_Retrun.h[0,28] [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Axis_State_Net")]
public static extern short MCF_Get_Axis_State_Net(ushort Axis, ref short Reason, ushort StationNumber = 0);
/********************************************************************************************************************************************************************
7
********************************************************************************************************************************************************************/
//7.1 速度控制函数 宏定义0.0 (0,10M]P/S (0,1T]P^2/S [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_JOG_Net")]
public static extern short MCF_JOG_Net(ushort Axis, double dMaxV, double dMaxA, ushort StationNumber = 0);
//7.4 单轴曲线函数 宏定义0.0 [0,dMaxV] (0,10M]P/S (0,1T]P^2/S (0,100T]P^3/S [0,dMaxV] 宏定义0.4 [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_Axis_Profile_Net")]
public static extern short MCF_Set_Axis_Profile_Net(ushort Axis, double dV_ini, double dMaxV, double dMaxA, double dJerk, double dV_end, ushort Profile, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Axis_Profile_Net")]
public static extern short MCF_Get_Axis_Profile_Net(ushort Axis, ref double dV_ini, ref double dMaxV, ref double dMaxA, ref double dJerk, ref double dV_end, ref ushort Profile, ushort StationNumber = 0);
//7.5 单轴运动函数 宏定义0.0 [-2^31,(2^31-1)] 宏定义0.3 [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Uniaxial_Net")]
public static extern short MCF_Uniaxial_Net(ushort Axis, int dDist, ushort Position_Mode, ushort StationNumber = 0);
//7.6 单轴停止曲线函数 宏定义0.0 (0,1T]P^2/S (0,100T]P^3/S 宏定义0.4 [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_Axis_Stop_Profile_Net")]
public static extern short MCF_Set_Axis_Stop_Profile_Net(ushort Axis, double dMaxA, double dJerk, ushort Profile, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Axis_Stop_Profile_Net")]
public static extern short MCF_Get_Axis_Stop_Profile_Net(ushort Axis, ref double dMaxA, ref double dJerk, ref ushort Profile, ushort StationNumber = 0);
//7.7 轴停止函数 宏定义0.0 宏定义7.7 [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Axis_Stop_Net")]
public static extern short MCF_Axis_Stop_Net(ushort Axis, ushort Axis_Stop_Mode, ushort StationNumber = 0);
/********************************************************************************************************************************************************************
16
********************************************************************************************************************************************************************/
//16.1 设置光源模式(1MS阻塞函数) 宏定义16.1.1 0关闭 1:24V常亮 2:24V频闪 3:48V爆闪
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_Light_Mode_Net")]
public static extern short MCF_Set_Light_Mode_Net(ushort Channel, ushort Light_Mode, ushort StationNumber = 0);
//16.2 设置电流保护(1MS阻塞函数) 宏定义16.1.1 [0,15000] 单位MA Over_Current/1000*0.1*11/3.3 * 4095
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_Light_Current_Net")]
public static extern short MCF_Set_Light_Current_Net(ushort Channel, ushort Max_Current, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Light_Current_1_4_Net")]
public static extern short MCF_Get_Light_Current_1_4_Net(ref ushort Current_1, ref ushort Current_2, ref ushort Current_3, ref ushort Current_4, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Light_Current_5_8_Net")]
public static extern short MCF_Get_Light_Current_5_8_Net(ref ushort Current_5, ref ushort Current_6, ref ushort Current_7, ref ushort Current_8, ushort StationNumber = 0);
//16.3 设置光源输出(1MS阻塞函数) 宏定义16.1.1 常亮:[0,255] 频闪[0,1000]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_Light_Output_Net")]
public static extern short MCF_Set_Light_Output_Net(ushort Channel, ushort Light_Size, ushort StationNumber = 0);
/********************************************************************************************************************************************************************
17
********************************************************************************************************************************************************************/
//17.1 模块版本号 [0x00000000,0xFFFFFFFF] [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Version_Net")]
public static extern short MCF_Get_Version_Net(ref uint Version, ushort StationNumber = 0);
//17.2 序列号 [0x00000000,0xFFFFFFFF] [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Serial_Number_Net")]
public static extern short MCF_Get_Serial_Number_Net(ref long Serial_Number, ushort StationNumber = 0);
//17.3 模块运行时间 [0x00000000,0xFFFFFFFF] [0,99] 单位:秒
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Get_Run_Time_Net")]
public static extern short MCF_Get_Run_Time_Net(ref uint Run_Time, ushort StationNumber = 0);
//17.4 Flash 读写功能目前暂时大小2Kbytes,也即定义一个 unsigned int Array[256] 存放数据
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Flash_Write_Net")]
public static extern short MCF_Flash_Write_Net(uint Pass_Word_Setup, ref uint Flash_Write_Data, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Flash_Read_Net")]
public static extern short MCF_Flash_Read_Net(uint Pass_Word_Check, ref uint Flash_Read_Data, ushort StationNumber = 0);
//17.8 系统定时回调函数
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_CallBack_Net")]
public static extern short MCF_Set_CallBack_Net(int CallBack, uint Time_1MS);
/********************************************************************************************************************************************************************
101 ,, 102,103,104
********************************************************************************************************************************************************************/
//101.1 设置参数前必须调用先关闭筛选功能
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Close_Net")]
public static extern short MCF_Sorting_Close_Net(ushort StationNumber = 0);
/********************************************************************************************************************************************************************
102 ,
********************************************************************************************************************************************************************/
//102.1 物件最大最小尺寸
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Piece_Size_Net")]
public static extern short MCF_Sorting_Set_Piece_Size_Net(uint Max_Size, uint Min_Size, ushort StationNumber = 0);
//102.2 物件安全距离,安全时间
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Piece_Place_Net")]
public static extern short MCF_Sorting_Set_Piece_Place_Net(uint Min_Distance, uint Min_Time_Intervel, ushort StationNumber = 0);
//102.3 来料检测设置
// 来料检测使能(默认Bit_Output_0,Bit_Output_1开,0关 1开) [Bit_Input_0,Bit_Input_3]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Input_Enable_Net")]
public static extern short MCF_Sorting_Set_Input_Enable_Net(ushort Bit_Input_Number, ushort Bit_Input_Enable, ushort StationNumber = 0);
// 来料检测电平(默认全部低电平, 0低电平 1高电平) [Bit_Input_0,Bit_Input_3]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Input_Logic_Net")]
public static extern short MCF_Sorting_Set_Input_Logic_Net(ushort Bit_Input_Number, ushort Bit_Input_Logic, ushort StationNumber = 0);
// 来料检测编码器(默认全部跟随Axis_1编码器) [Bit_Input_0,Bit_Input_3]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Input_Source_Net")]
public static extern short MCF_Sorting_Set_Input_Source_Net(ushort Bit_Input_Number, ushort Axis, ushort Source, ushort StationNumber = 0);
// 来料检测捕获位置(默认全部捕获前部, 0前部 1中间) [Bit_Input_0,Bit_Input_3]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Input_Position_Net")]
public static extern short MCF_Sorting_Set_Input_Position_Net(ushort Bit_Input_Number, ushort Mode, ushort StationNumber = 0);
//102.4 DI00 检测不连续物件强制保持连续
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Piece_Keep_Net")]
public static extern short MCF_Sorting_Set_Piece_Keep_Net(uint Keep_Length, ushort StationNumber = 0);
//102.5 DI00 物件检测无料超时停止轴运动(默认时间0,表示不启动) [0,60000] &Array[DO00,DO15],0:低 1:高 2:关闭
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Input_0_TimeOut_Net")]
public static extern short MCF_Sorting_Set_Input_0_TimeOut_Net(uint Time_1MS, ref uint TimeOut_Output, ushort StationNumber = 0);
//102.6 通用IO按位输入滤波函数 [Bit_Input_0,Bit_Input_1] [1,100]MS [0,99]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Set_Input_Filter_Time_Bit_Net")]
public static extern short MCF_Set_Input_Filter_Time_Bit_Net(ushort Bit_Input_Number, uint Filter_Time_1MS, ushort StationNumber = 0);
//102.7 多个来料检测绑定相机触发,OK吹气,NG吹气 [Bit_Input_1]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Input_Bind_Net")]
public static extern short MCF_Sorting_Set_Input_Bind_Net(ushort Bit_Input_Number, ushort Camera_Start_Number, ushort Bond_Start_Number, ushort StationNumber = 0);
/********************************************************************************************************************************************************************
103 OK,NG安全保护参数,
********************************************************************************************************************************************************************/
//103.1 物件吹气OK超时停止轴运动(默认时间0,表示不启动) [0,60000] &Array[DO00,DO15],0:低 1:高 2:关闭
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Trig_Blow_OK_TimeOut_Net")]
public static extern short MCF_Sorting_Set_Trig_Blow_OK_TimeOut_Net(uint Time_1MS, ref uint TimeOut_Output, ushort StationNumber = 0);
//103.2 物件吹气连续NG停止轴运动(默认时间0,表示不启动) [0,60000] &Array[DO00,DO15],0:低 1:高 2:关闭
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Trig_Blow_NG_NumberOut_Net")]
public static extern short MCF_Sorting_Set_Trig_Blow_NG_NumberOut_Net(uint NG_Number, ref uint NumberOut_Output, ushort StationNumber = 0);
//103.3 HMC3432S/HMC3412S 可以设置物件重新检测确定功能,以此判定是否误吹
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Blow_Check_Again_Net")]
public static extern short MCF_Sorting_Set_Blow_Check_Again_Net(ushort Bit_Input_Number, ushort Bit_Input_Logic, int Input_Position, uint Piece_Size,
ushort Blow_OK_Check,
ushort Blow_NG_Check,
ushort Blow_1_Check,
ushort Blow_2_Check,
ushort Blow_3_Check,
ushort Blow_4_Check,
ushort Blow_5_Check,
ushort Blow_6_Check,
ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Get_Blow_Check_Lose_Number_Net")]
public static extern short MCF_Sorting_Get_Blow_Check_Lose_Number_Net(ref uint Lose_Number, ushort StationNumber = 0);
/********************************************************************************************************************************************************************
104 ,
********************************************************************************************************************************************************************/
//104.1 HMC3432S 可以配置相机和吹气个数 [1,30] [1,30]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Camera_Blow_Config_Net")]
public static extern short MCF_Sorting_Camera_Blow_Config_Net(ushort Camera_Number, ushort Blow_Number, ushort StationNumber = 0);
//104.2 设置相机参数 与检测装置的相对位置 编码器反馈的运行方向
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Camera_Net")]
public static extern short MCF_Sorting_Set_Camera_Net(ushort Camera_Number, int Camera_Position, ushort Motion_Dir, ushort Action_Mode, ushort Action_IO, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Camera_Light_Frequency_Net")]
public static extern short MCF_Sorting_Set_Camera_Light_Frequency_Net(ushort Camera_Number, ushort Light_Number, ushort Frequency_Enable, ushort StationNumber = 0);
//104.3 设置运动控制卡触发相机拍照后,延时多少毫秒计数增加1,一般设置为 大于 控制卡从触发相机拍照到软件出图像结果需要的时间,
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Trig_Camera_Delay_Count_Net")]
public static extern short MCF_Sorting_Set_Trig_Camera_Delay_Count_Net(ushort Camera_Number, double Camera_Delay_Count_MS, ushort StationNumber = 0);
//104.4 设置OK吹气参数
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Blow_OK_Net")]
public static extern short MCF_Sorting_Set_Blow_OK_Net(int Blow_OK_Position, ushort Motion_Dir, ushort Action_Mode, ushort Action_IO, ushort StationNumber = 0);
//104.5 设置NG吹气参数
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Blow_NG_Net")]
public static extern short MCF_Sorting_Set_Blow_NG_Net(int Blow_NG_Position, ushort Motion_Dir, ushort Action_Mode, ushort Action_IO, ushort StationNumber = 0);
//104.6 设置吹气1到30参数 [1,30]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Blow_Net")]
public static extern short MCF_Sorting_Set_Blow_Net(ushort Blow_Number, int Blow_Position, ushort Motion_Dir, ushort Action_Mode, ushort Action_IO, ushort StationNumber = 0);
/********************************************************************************************************************************************************************
105 102,103,104
********************************************************************************************************************************************************************/
//105.1 筛选启动函数,在设置好参数后启动
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Start_Net")]
public static extern short MCF_Sorting_Start_Net(ushort Mode = 0, ushort StationNumber = 0);
/********************************************************************************************************************************************************************
106
********************************************************************************************************************************************************************/
//106.0 设置相机处理结果最短时间和最大超时时间,允许连续超时最大个数
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Camera_Handle_Time_Net")]
public static extern short MCF_Sorting_Set_Camera_Handle_Time_Net(ushort Camera_Number, double Handle_Time_1MS, double Handle_TimeOut_1MS, uint Handle_TimeOut_Number, ushort StationNumber = 0);
//106.1 吹气模式0用户综合所有相机结果后发送吹气指令
// 用户在图像处理回调函数中调用该函数通知图像处理结果
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Camera_Result_Data_Net")]
public static extern short MCF_Sorting_Set_Camera_Result_Data_Net(ushort Camera_Number, uint Result_Data, ushort StationNumber = 0);
// 用户开辟线程检查物料最新的图像结果
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Get_Camera_Result_Updata_Net")]
public static extern short MCF_Sorting_Get_Camera_Result_Updata_Net(ushort Camera_Number, ref uint Piece_Number, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Get_Camera_Result_Buffer_Net")]
public static extern short MCF_Sorting_Get_Camera_Result_Buffer_Net(ushort Camera_Number, uint Piece_Number, ref uint Result_Buffer, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Get_Camera_Handle_Time_Net")]
public static extern short MCF_Sorting_Get_Camera_Handle_Time_Net(ushort Camera_Number, uint Piece_Number, ref uint Handle_Time, ushort StationNumber = 0);
// 用户根据图像结果吹气
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Trig_Blow_OK_Net")]
public static extern short MCF_Sorting_Set_Trig_Blow_OK_Net(uint Piece_Number, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Trig_Blow_NG_Net")]
public static extern short MCF_Sorting_Set_Trig_Blow_NG_Net(uint Piece_Number, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Trig_Blow_Net")]
public static extern short MCF_Sorting_Set_Trig_Blow_Net(ushort Blow_Number, uint Piece_Number, ushort StationNumber = 0);
//106.2 吹气模式1用户直接发送每个相机结果控制卡自动综合结果后吹气
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Camera_Result_OK_Net")]
public static extern short MCF_Sorting_Set_Camera_Result_OK_Net(ushort Camera_Number, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Camera_Result_NG_Net")]
public static extern short MCF_Sorting_Set_Camera_Result_NG_Net(ushort Camera_Number, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Get_Blow_Result_OK_Net")]
public static extern short MCF_Sorting_Get_Blow_Result_OK_Net(ref uint Result_OK_Number, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Get_Blow_Result_NG_Net")]
public static extern short MCF_Sorting_Get_Blow_Result_NG_Net(ref uint Result_NG_Number, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Get_Blow_Result_Miss_Net")]
public static extern short MCF_Sorting_Get_Blow_Result_Miss_Net(ref uint Result_Miss_Number, ushort StationNumber = 0);
//106.3 吹气模式2用户不需要发送相机结果控制卡通过IO综合结果后吹气,全程通过硬件实现,可以直接替代PLC (0,500]
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Camera_Result_Input_OK_Net")]
public static extern short MCF_Sorting_Set_Camera_Result_Input_OK_Net(ushort Camera_Number, ushort Input_Number, ushort Logic, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Set_Camera_Result_Input_NG_Net")]
public static extern short MCF_Sorting_Set_Camera_Result_Input_NG_Net(ushort Camera_Number, ushort Input_Number, ushort Logic, ushort StationNumber = 0);
/********************************************************************************************************************************************************************
107 ,,
********************************************************************************************************************************************************************/
//107.0 筛选监测函数
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Get_State_Net")]
public static extern short MCF_Sorting_Get_State_Net(ref ushort State, ushort StationNumber = 0);
//107.1 获取DI00物件不合格计数个数
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Get_Piece_Pass_Net")]
public static extern short MCF_Sorting_Get_Piece_Pass_Net(ushort Piece_Input_Number, ref uint Piece_Pass, ushort StationNumber = 0);
//107.2 获取DI00物件计数个数
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Get_Piece_State_Net")]
public static extern short MCF_Sorting_Get_Piece_State_Net(ushort Piece_Input_Number, //物件计数的输入端口号
ref uint Piece_Find, //物件匹配统计数量
ref uint Piece_Size, //物件大小10组
ref uint Piece_Distance_To_next, //物件间距10组
ref uint Piece_Cross_Camera, //物件经过所有相机个数
ushort StationNumber = 0);
//107.3 获取判断控制卡触发相机拍照计数,图像结果输出结果一定要先于延时后的控制卡相机拍照计数,而且要一一对应,否则做为图像异常或者漏拍处理
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Get_Trig_Camera_Count_Net")]
public static extern short MCF_Sorting_Get_Trig_Camera_Count_Net(ushort Camera_Number, ref uint Trig_Camera_Count, ushort StationNumber = 0);
//107.4 获取OK,NG触发计数
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Get_Trig_Blow_NG_Count_Net")]
public static extern short MCF_Sorting_Get_Trig_Blow_NG_Count_Net(ref uint Trig_Blow_NG_Count, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Get_Trig_Blow_OK_Count_Net")]
public static extern short MCF_Sorting_Get_Trig_Blow_OK_Count_Net(ref uint Trig_Blow_OK_Count, ushort StationNumber = 0);
//107.5 获取OK,NG漏触发计数
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Get_Lose_Blow_NG_Count_Net")]
public static extern short MCF_Sorting_Get_Lose_Blow_NG_Count_Net(ref uint Lose_Blow_NG_Count, ushort StationNumber = 0);
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Get_Lose_Blow_OK_Count_Net")]
public static extern short MCF_Sorting_Get_Lose_Blow_OK_Count_Net(ref uint Lose_Blow_OK_Count, ushort StationNumber = 0);
//107.6 获取气阀吹气计数
[DllImport("MCDLL_NET.DLL", EntryPoint = "MCF_Sorting_Get_Trig_Blow_Count_Net")]
public static extern short MCF_Sorting_Get_Trig_Blow_Count_Net(ushort Blow_Number, ref uint Trig_Blow_Count, ushort StationNumber = 0);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,277 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DH.Devices.Motion
{
/// <summary>
/// 回零状态
/// </summary>
public enum SearchHomeState
{
/// <summary>
/// 回零成功
/// </summary>
[Description("回零成功")]
HomeSucess = 0,
/// <summary>
/// 回零错误
/// </summary>
[Description("回零错误")]
HomeError = 31,
/// <summary>
/// 正在回零点
/// </summary>
[Description("正在回零点")]
Homing = 32,
}
/// <summary>
/// 0.3 坐标模式
/// </summary>
public enum PositionMode
{
/// <summary>
/// 绝对位置模式
/// </summary>
[Description("绝对位置模式")]
Position_Absolute = 0,
/// <summary>
/// 相对位置模式
/// </summary>
[Description("相对位置模式")]
Position_Opposite = 1,
}
/// <summary>
/// 0.4 单轴点动曲线类型
/// </summary>
public enum Profile
{
/// <summary>
/// T型曲线
/// </summary>
[Description("T型曲线")]
Profile_T = 0,
/// <summary>
/// S型曲线
/// </summary>
[Description("S型曲线")]
Profile_S = 1,
}
/// <summary>
/// 3.1 伺服使能设置
/// </summary>
public enum ServoLogic
{
/// <summary>
/// 触点闭合
/// </summary>
[Description("触点闭合")]
Servo_Close = 0,
/// <summary>
/// 触点打开
/// </summary>
[Description("触点打开")]
Servo_Open = 1,
}
/// <summary>
/// 3.2 报警复位电平设置
/// </summary>
public enum AlarmLogic
{
/// <summary>
/// 触点闭合
/// </summary>
[Description("触点闭合")]
Alarm_Close = 0,
/// <summary>
/// 触点打开
/// </summary>
[Description("触点打开")]
Alarm_Open = 1,
}
/// <summary>
/// 3.6
/// </summary>
public enum HomeState
{
/// <summary>
/// 触点闭合,硬件灯亮
/// </summary>
[Description("触点闭合,硬件灯亮")]
Home_Close = 0,
/// <summary>
/// 触点打开,硬件灯灭
/// </summary>
[Description("触点打开,硬件灯灭")]
Home_Open = 1,
}
/// <summary>
/// 4.1 脉冲模式
/// </summary>
public enum PulseMode
{
/// <summary>
/// 脉冲方向(默认)
/// </summary>
[Description("模式0")]
Pulse_Dir_H = 0,
/// <summary>
/// 脉冲方向
/// </summary>
[Description("模式1")]
Pulse_Dir_L = 1,
/// <summary>
/// 双脉冲
/// </summary>
[Description("模式2")]
Pulse_CW_CCW = 2,
/// <summary>
/// 双脉冲
/// </summary>
[Description("模式3")]
Pulse_CCW_CW = 3,
/// <summary>
/// AB相位
/// </summary>
[Description("模式4")]
Pulse_AB = 4,
/// <summary>
/// AB相位
/// </summary>
[Description("模式5")]
Pulse_BA = 5,
}
/****************************************************************************************************************
5
*****************************************************************************************************************/
//5.1 EMG_Mode
public enum EMG_Mode
{
[Description("不使用紧急停止功能")]
EMG_Trigger_Close = 0, //不使用紧急停止功能
[Description("低电平触发紧急停止")]
EMG_Trigger_Low_IMD = 1, //低电平触发紧急停止
[Description("低电平触发减速停止")]
EMG_Trigger_Low_DEC = 2,//低电平触发减速停止
[Description("高电平触发紧急停止")]
EMG_Trigger_High_IMD = 3, //高电平触发紧急停止
}
/// <summary>
/// 6.1.1 正负限位触发电平
/// </summary>
public enum LimitLogic
{
/// <summary>
/// 低电平触发
/// </summary>
[Description("低电平触发")]
Low_Logic = 0,
/// <summary>
/// 高电平触发
/// </summary>
[Description("高电平触发")]
High_Logic = 1,
}
/// <summary>
/// 6.1.2 回零限位触发电平
/// </summary>
public enum HomeLogic
{
/// <summary>
/// 低电平触发
/// </summary>
[Description("低电平触发")]
Low_Logic = 0,
/// <summary>
/// 高电平触发
/// </summary>
[Description("高电平触发")]
High_Logic = 1,
}
/// <summary>
/// 6.1.3 Index触发电平
/// </summary>
public enum IndexLogic
{
/// <summary>
/// 低电平触发
/// </summary>
[Description("低电平触发")]
Low_Logic = 0,
/// <summary>
/// 高电平触发
/// </summary>
[Description("高电平触发")]
High_Logic = 1,
}
}

View File

@ -22,7 +22,7 @@
<ItemGroup>
<Reference Include="HslCommunication">
<HintPath>..\X64\Debug\HslCommunication.dll</HintPath>
<HintPath>..\x64\Debug\HslCommunication.dll</HintPath>
</Reference>
</ItemGroup>

View File

@ -49,7 +49,7 @@ namespace DH.Devices.PLC
{
connected = true;
MonitorPieces();
TurntableOpen(18000,true);
TurntableOpen(12000,true);
return true;
}

View File

@ -11,6 +11,10 @@
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="OpenCvSharp4" Version="4.10.0.20241108" />

View File

@ -0,0 +1,689 @@
using OpenCvSharp;
using System.ComponentModel;
using System.Drawing;
using static OpenCvSharp.AgastFeatureDetector;
using System.Text.RegularExpressions;
using System.Text;
using System.Drawing.Design;
namespace DH.Devices.Vision
{
public enum MLModelType
{
[Description("图像分类")]
ImageClassification = 1,
[Description("目标检测")]
ObjectDetection = 2,
//[Description("图像分割")]
//ImageSegmentation = 3
[Description("语义分割")]
SemanticSegmentation = 3,
[Description("实例分割")]
InstanceSegmentation = 4,
[Description("目标检测GPU")]
ObjectGPUDetection = 5
}
public class ModelLabel
{
public string LabelId { get; set; }
[Category("模型标签")]
[DisplayName("模型标签索引")]
[Description("模型识别的标签索引")]
public int LabelIndex { get; set; }
[Category("模型标签")]
[DisplayName("模型标签")]
[Description("模型识别的标签名称")]
public string LabelName { get; set; }
//[Category("模型配置")]
//[DisplayName("模型参数配置")]
//[Description("模型参数配置集合")]
//public ModelParamSetting ModelParamSetting { get; set; } = new ModelParamSetting();
public string GetDisplayText()
{
return $"{LabelId}-{LabelName}";
}
}
public class MLRequest
{
public int ImageChannels = 3;
public Mat mImage;
public int ResizeWidth;
public int ResizeHeight;
public float confThreshold;
public float iouThreshold;
//public int ImageResizeCount;
public bool IsCLDetection;
public int ProCount;
public string in_node_name;
public string out_node_name;
public string in_lable_path;
public int ResizeImageSize;
public int segmentWidth;
public int ImageWidth;
// public List<labelStringBase> OkClassTxtList;
public List<ModelLabel> LabelNames;
}
public enum ResultState
{
[Description("检测NG")]
DetectNG = -3,
//[Description("检测不足TBD")]
// ShortageTBD = -2,
[Description("检测结果TBD")]
ResultTBD = -1,
[Description("OK")]
OK = 1,
// [Description("NG")]
// NG = 2,
//统计结果
[Description("A类NG")]
A_NG = 25,
[Description("B类NG")]
B_NG = 26,
[Description("C类NG")]
C_NG = 27,
}
/// <summary>
/// 深度学习 识别结果明细 面向业务detect 面向深度学习Recongnition、Inference
/// </summary>
public class DetectionResultDetail
{
public string LabelBGR { get; set; }//识别到对象的标签BGR
public int LabelNo { get; set; } // 识别到对象的标签索引
public string LabelName { get; set; }//识别到对象的标签名称
public double Score { get; set; }//识别目标结果的可能性、得分
public string LabelDisplay { get; set; }//识别到对象的 显示信息
public double Area { get; set; }//识别目标的区域面积
public Rectangle Rect { get; set; }//识别目标的外接矩形
public RotatedRect MinRect { get; set; }//识别目标的最小外接矩形(带角度)
public ResultState InferenceResult { get; set; }//只是模型推理 label的结果
public double DistanceToImageCenter { get; set; } //计算矩形框到图像中心的距离
public ResultState FinalResult { get; set; }//模型推理+其他视觉、逻辑判断后 label结果
}
public class MLResult
{
public bool IsSuccess = false;
public string ResultMessage;
public Bitmap ResultMap;
public List<DetectionResultDetail> ResultDetails = new List<DetectionResultDetail>();
}
public class MLInit
{
public string ModelFile;
public string InferenceDevice;
public int InferenceWidth;
public int InferenceHeight;
public string InputNodeName;
public int SizeModel;
public bool bReverse;//尺寸测量正反面
//目标检测Gpu
public bool IsGPU;
public int GPUId;
public float Score_thre;
public MLInit(string modelFile, bool isGPU, int gpuId, float score_thre)
{
ModelFile = modelFile;
IsGPU = isGPU;
GPUId = gpuId;
Score_thre = score_thre;
}
public MLInit(string modelFile, string inputNodeName, string inferenceDevice, int inferenceWidth, int inferenceHeight)
{
ModelFile = modelFile;
InferenceDevice = inferenceDevice;
InferenceWidth = inferenceWidth;
InferenceHeight = inferenceHeight;
InputNodeName = inputNodeName;
}
}
public class DetectStationResult
{
public string Pid { get; set; }
public string TempPid { get; set; }
/// <summary>
/// 检测工位名称
/// </summary>
public string DetectName { get; set; }
/// <summary>
/// 深度学习 检测结果
/// </summary>
public List<DetectionResultDetail> DetectDetails = new List<DetectionResultDetail>();
/// <summary>
/// 工位检测结果
/// </summary>
public ResultState ResultState { get; set; } = ResultState.ResultTBD;
public double FinalResultfScore { get; set; } = 0.0;
public string ResultLabel { get; set; } = "";// 多个ng时根据label优先级设定当前检测项的label
public string ResultLabelCategoryId { get; set; } = "";// 多个ng时根据label优先级设定当前检测项的label
public int PreTreatState { get; set; }
public bool IsPreTreatDone { get; set; } = true;
public bool IsAfterTreatDone { get; set; } = true;
public bool IsMLDetectDone { get; set; } = true;
/// <summary>
/// 预处理阶段已经NG
/// </summary>
public bool IsPreTreatNG { get; set; } = false;
/// <summary>
/// 目标检测NG
/// </summary>
public bool IsObjectDetectNG { get; set; } = false;
public DateTime EndTime { get; set; }
public int StationDetectElapsed { get; set; }
public static string NormalizeAndClean(string input)
{
if (input == null) return null;
// Step 1: 标准化字符编码为 Form C (规范组合)
string normalizedString = input.Normalize(NormalizationForm.FormC);
// Step 2: 移除所有空白字符,包括制表符和换行符
string withoutWhitespace = Regex.Replace(normalizedString, @"\s+", "");
// Step 3: 移除控制字符 (Unicode 控制字符,范围 \u0000 - \u001F 和 \u007F)
string withoutControlChars = Regex.Replace(withoutWhitespace, @"[\u0000-\u001F\u007F]+", "");
// Step 4: 移除特殊的不可见字符(如零宽度空格等)
string cleanedString = Regex.Replace(withoutControlChars, @"[\u200B\u200C\u200D\uFEFF]+", "");
return cleanedString;
}
}
public class RelatedCamera
{
[Category("关联相机")]
[DisplayName("关联相机")]
[Description("关联相机描述")]
//[TypeConverter(typeof(CollectionCountConvert))]
public string CameraSourceId { get; set; } = "";
public RelatedCamera()
{
}
public RelatedCamera(string cameraSourceId)
{
CameraSourceId = cameraSourceId;
}
}
public class DetectionConfig
{
[ReadOnly(true)]
public string Id { get; set; } = Guid.NewGuid().ToString();
[Category("检测配置")]
[DisplayName("检测配置名称")]
[Description("检测配置名称")]
public string Name { get; set; }
[Category("关联相机")]
[DisplayName("关联相机")]
[Description("关联相机描述")]
public string CameraSourceId { get; set; } = "";
[Category("关联相机集合")]
[DisplayName("关联相机集合")]
[Description("关联相机描述")]
//[TypeConverter(typeof(DeviceIdSelectorConverter<CameraBase>))]
public List<RelatedCamera> CameraCollects { get; set; } = new List<RelatedCamera>();
[Category("启用配置")]
[DisplayName("是否启用GPU检测")]
[Description("是否启用GPU检测")]
public bool IsEnableGPU { get; set; } = false;
[Category("启用配置")]
[DisplayName("是否混料模型")]
[Description("是否混料模型")]
public bool IsMixModel { get; set; } = false;
[Category("启用配置")]
[DisplayName("是否启用该检测")]
[Description("是否启用该检测")]
public bool IsEnabled { get; set; }
[Category("启用配置")]
[DisplayName("是否加入检测工位")]
[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-图像分割")]
//[TypeConverter(typeof(EnumDescriptionConverter<MLModelType>))]
public MLModelType ModelType { get; set; } = MLModelType.ObjectDetection;
//[Category("2.中检测(深度学习)")]
//[DisplayName("中检测-GPU索引")]
//[Description("GPU索引")]
//public int GPUIndex { get; set; } = 0;
[Category("2.中检测(深度学习)")]
[DisplayName("中检测-模型文件路径")]
[Description("中处理 深度学习模型文件路径,路径中不可含有中文字符,一般情况可以只配置中检测模型,当需要先用预检测过滤一次时,请先配置好与预检测相关配置")]
public string ModelPath { get; set; }
[Category("2.中检测(深度学习)")]
[DisplayName("中检测-模型宽度")]
[Description("中处理-模型宽度")]
public int ModelWidth { get; set; } = 640;
[Category("2.中检测(深度学习)")]
[DisplayName("中检测-模型高度")]
[Description("中处理-模型高度")]
public int ModelHeight { get; set; } = 640;
[Category("2.中检测(深度学习)")]
[DisplayName("中检测-模型节点名称")]
[Description("中处理-模型节点名称")]
public string ModeloutNodeName { get; set; } = "output0";
[Category("2.中检测(深度学习)")]
[DisplayName("中检测-模型置信度")]
[Description("中处理-模型置信度")]
public float ModelconfThreshold { get; set; } = 0.5f;
[Category("2.中检测(深度学习)")]
[DisplayName("中检测-模型标签路径")]
[Description("中处理-模型标签路径")]
public string in_lable_path { get; set; }
[Category("4.最终过滤(逻辑过滤)")]
[DisplayName("过滤器集合")]
[Description("最后的逻辑过滤:可根据 识别出对象的 宽度、高度、面积、得分来设置最终检测结果,同一识别目标同一判定,多项过滤器之间为“或”关系")]
public List<DetectionFilter> DetectionFilterList { get; set; } = new List<DetectionFilter>();
//[Category("深度学习配置")]
//[DisplayName("检测配置标签")]
//[Description("检测配置标签关联")]
//public List<DetectConfigLabel> DetectConfigLabelList { get; set; } = new List<DetectConfigLabel>();
public DetectionConfig()
{
}
public DetectionConfig(string name, MLModelType modelType, string modelPath, bool isEnableGPU,string sCameraSourceId)
{
ModelPath = modelPath ?? string.Empty;
Name = name;
ModelType = modelType;
IsEnableGPU = isEnableGPU;
Id = Guid.NewGuid().ToString();
CameraSourceId = sCameraSourceId;
}
}
/// <summary>
/// 识别目标定义 class分类信息 Detection Segmentation要识别的对象
/// </summary>
public class RecongnitionLabel //: IComplexDisplay
{
[Category("检测标签定义")]
[Description("检测标签编码")]
[ReadOnly(true)]
public string Id { get; set; } = Guid.NewGuid().ToString();
[Category("检测标签定义")]
[DisplayName("检测标签名称")]
[Description("检测标签名称")]
public string LabelName { get; set; } = "";
[Category("检测标签定义")]
[DisplayName("检测标签描述")]
[Description("检测标签描述,中文描述")]
public string LabelDescription { get; set; } = "";
[Category("检测标签定义")]
[DisplayName("检测标签分类")]
[Description("检测标签分类id")]
//[TypeConverter(typeof(LabelCategoryConverter))]
public string LabelCategory { get; set; } = "";
}
/// <summary>
/// 检测项识别对象
/// </summary>
public class DetectConfigLabel //: IComplexDisplay
{
[Category("检测项标签")]
[DisplayName("检测项标签")]
[Description("检测标签Id")]
//[TypeConverter(typeof(DetectionLabelConverter))]
public string LabelId { get; set; }
[Browsable(false)]
//public string LabelName { get => GetLabelName(); }
[Category("检测项标签")]
[DisplayName("检测标签优先级")]
[Description("检测标签优先级,值越小,优先级越高")]
public int LabelPriority { get; set; } = 0;
//[Category("检测项标签")]
//[DisplayName("标签BGR值")]
//[Description("检测标签BGR值例如0,128,0")]
//public string LabelBGR { get; set; }
//[Category("模型配置")]
//[DisplayName("模型参数配置")]
//[Description("模型参数配置集合")]
//[TypeConverter(typeof(ComplexObjectConvert))]
//[Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))]
//public ModelParamSetting ModelParamSetting { get; set; } = new ModelParamSetting();
//public string GetDisplayText()
//{
// string dName = "";
// if (!string.IsNullOrWhiteSpace(LabelId))
// {
// using (var scope = GlobalVar.Container.BeginLifetimeScope())
// {
// IProcessConfig config = scope.Resolve<IProcessConfig>();
// var mlBase = config.DeviceConfigs.FirstOrDefault(c => c is VisionEngineInitialConfigBase) as VisionEngineInitialConfigBase;
// if (mlBase != null)
// {
// var targetLabel = mlBase.RecongnitionLabelList.FirstOrDefault(u => u.Id == LabelId);
// if (targetLabel != null)
// {
// dName = targetLabel.GetDisplayText();
// }
// }
// }
// }
// return dName;
//}
//public string GetLabelName()
//{
// var name = "";
// var mlBase = iConfig.DeviceConfigs.FirstOrDefault(c => c is VisionEngineInitialConfigBase) as VisionEngineInitialConfigBase;
// if (mlBase != null)
// {
// var label = mlBase.RecongnitionLabelList.FirstOrDefault(u => u.Id == LabelId);
// if (label != null)
// {
// name = label.LabelName;
// }
// }
// return name;
//}
}
/// <summary>
/// 识别对象定义分类信息 A类B类
/// </summary>
public class RecongnitionLabelCategory //: IComplexDisplay
{
[Category("检测标签分类")]
[Description("检测标签分类")]
[ReadOnly(true)]
public string Id { get; set; } = Guid.NewGuid().ToString();
[Category("检测标签分类")]
[DisplayName("检测标签分类名称")]
[Description("检测标签分类名称")]
public string CategoryName { get; set; } = "A-NG";
[Category("检测标签分类")]
[DisplayName("检测标签分类优先级")]
[Description("检测标签分类优先级,值越小,优先级越高")]
public int CategoryPriority { get; set; } = 0;
public string GetDisplayText()
{
return CategoryPriority + ":" + CategoryName;
}
}
/// <summary>
/// 检测过滤
/// </summary>
public class DetectionFilter ///: IComplexDisplay
{
[Category("过滤器基础信息")]
[DisplayName("检测标签")]
[Description("检测标签信息")]
//[TypeConverter(typeof(DetectionLabelConverter))]
public string LabelId { get; set; }
// [Browsable(false)]
public string LabelName { get; set; }
[Category("过滤器基础信息")]
[DisplayName("是否启用过滤器")]
[Description("是否启用过滤器")]
public bool IsEnabled { get; set; }
[Category("过滤器判定信息")]
[DisplayName("判定结果")]
[Description("过滤器默认判定结果")]
public ResultState ResultState { get; set; } = ResultState.ResultTBD;
[Category("过滤条件")]
[DisplayName("过滤条件集合")]
[Description("过滤条件集合,集合之间为“且”关系")]
//[TypeConverter(typeof(CollectionCountConvert))]
// [Editor(typeof(ComplexCollectionEditor<FilterConditions>), typeof(UITypeEditor))]
public List<FilterConditions> FilterConditionsCollection { get; set; } = new List<FilterConditions>();
public bool FilterOperation(DetectionResultDetail recongnitionResult)
{
return FilterConditionsCollection.All(u =>
{
return u.FilterConditionCollection.Any(c =>
{
double compareValue = 0;
switch (c.FilterPropperty)
{
case DetectionFilterProperty.Width:
compareValue = recongnitionResult.Rect.Width;
break;
case DetectionFilterProperty.Height:
compareValue = recongnitionResult.Rect.Height;
break;
case DetectionFilterProperty.Area:
compareValue = recongnitionResult.Area;
break;
case DetectionFilterProperty.Score:
compareValue = recongnitionResult.Score;
break;
//case RecongnitionTargetFilterProperty.Uncertainty:
// compareValue = 0;
// //defect.Uncertainty;
// break;
}
return compareValue >= c.MinValue && compareValue <= c.MaxValue;
});
});
}
}
public class FilterConditions //: IComplexDisplay
{
[Category("过滤条件")]
[DisplayName("过滤条件集合")]
[Description("过滤条件集合,集合之间为“或”关系")]
//[TypeConverter(typeof(CollectionCountConvert))]
//[Editor(typeof(ComplexCollectionEditor<FilterCondition>), typeof(UITypeEditor))]
public List<FilterCondition> FilterConditionCollection { get; set; } = new List<FilterCondition>();
//public string GetDisplayText()
//{
// if (FilterConditionCollection.Count == 0)
// {
// return "空";
// }
// else
// {
// var desc = string.Join(" OR ", FilterConditionCollection.Select(u => u.GetDisplayText()));
// if (FilterConditionCollection.Count > 1)
// {
// desc = $"({desc})";
// }
// return desc;
// }
//}
}
public class FilterCondition //: IComplexDisplay
{
[Category("识别目标属性")]
[DisplayName("过滤属性")]
[Description("识别目标过滤针对的属性")]
//[TypeConverter(typeof(EnumDescriptionConverter<DetectionFilterProperty>))]
public DetectionFilterProperty FilterPropperty { get; set; } = DetectionFilterProperty.Width;
[Category("过滤值")]
[DisplayName("最小值")]
[Description("最小值")]
public double MinValue { get; set; } = 1;
[Category("过滤值")]
[DisplayName("最大值")]
[Description("最大值")]
public double MaxValue { get; set; } = 99999999;
//public string GetDisplayText()
//{
// return $"{FilterPropperty.GetEnumDescription()}:{MinValue}-{MaxValue}";
//}
}
public enum DetectionFilterProperty
{
[Description("宽度")]
Width = 1,
[Description("高度")]
Height = 2,
[Description("面积")]
Area = 3,
[Description("得分")]
Score = 4,
//[Description("不确定性")]
//Uncertainty = 5,
}
}

View File

@ -0,0 +1,244 @@
#define USE_MULTI_THREAD
using OpenCvSharp;
using OpenCvSharp.Extensions;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Threading;
using System.Threading.Tasks;
using System.Security.Cryptography.Xml;
using System.Runtime.InteropServices;
using Newtonsoft.Json;
namespace DH.Devices.Vision
{
/// <summary>
/// 目标检测 GPU
/// </summary>
public class SimboDetection : SimboVisionMLBase
{
public override bool Load(MLInit mLInit)
{
bool res = false;
try
{
Model = MLGPUEngine.InitModel(mLInit.ModelFile, 1, mLInit.Score_thre, mLInit.GPUId, 3, 8);
//Model = MLEngine.InitModel(mLInit.ModelFile, 1, 0.45f, 0, 3);
res = true;
#if USE_MULTI_THREAD
IsCreated = true;
if (IsCreated)
{
_runHandleBefore ??= new AutoResetEvent(false);
_runHandleAfter ??= new ManualResetEvent(false);
_runTask ??= Task.Factory.StartNew(() =>
{
while (IsCreated)
{
_runHandleBefore.WaitOne();
if (IsCreated)
{
_result = RunInferenceFixed(_req);
_runHandleAfter.Set();
}
}
}, TaskCreationOptions.LongRunning);
}
#endif
}
catch (Exception ex)
{
throw ex;
}
return res;
}
#if USE_MULTI_THREAD
MLRequest _req = null;
MLResult _result = null;
public bool IsCreated { get; set; } = false;
Task _runTask = null;
AutoResetEvent _runHandleBefore = new AutoResetEvent(false);
ManualResetEvent _runHandleAfter = new ManualResetEvent(false);
object _runLock = new object();
#endif
[HandleProcessCorruptedStateExceptions]
public override MLResult RunInference(MLRequest req)
{
#if USE_MULTI_THREAD
MLResult mlResult = null;
lock (_runLock)
{
_result = new MLResult();
_req = req;
_runHandleAfter.Reset();
_runHandleBefore.Set();
_runHandleAfter.WaitOne();
mlResult = _result;
}
return mlResult;
#else
return RunInferenceFixed(req);
#endif
}
private void ConvertJsonResult(string json, ref MLResult result)
{
// json = "{\"FastDetResult\":[{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654843,\"rect\":[175,99,110,594]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654589,\"rect\":[2608,19,104,661]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654285,\"rect\":[1275,19,104,662]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.620762,\"rect\":[1510,95,107,600]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.617812,\"rect\":[2844,93,106,602]}]}";
//
Console.WriteLine("检测结果JSON" + json);
HYoloResult detResult = JsonConvert.DeserializeObject<HYoloResult>(json);
if (detResult == null)
{
return;
}
int iNum = detResult.HYolo.Count;
int IokNum = 0;
for (int ix = 0; ix < iNum; ix++)
{
var det = detResult.HYolo[ix];
var rect = det.rect;
DetectionResultDetail detectionResultDetail = new DetectionResultDetail();
// detectionResultDetail.LabelNo = det.classId;
//todo: 标签名相对应
detectionResultDetail.LabelDisplay = det.classname;
detectionResultDetail.Rect = new Rectangle(rect[0], rect[1], rect[2], rect[3]);
detectionResultDetail.Score = det.fScore;
detectionResultDetail.LabelName = det.classname;
detectionResultDetail.Area = rect[2] * rect[3];
detectionResultDetail.InferenceResult = ResultState.DetectNG;
result.ResultDetails.Add(detectionResultDetail);
}
}
[HandleProcessCorruptedStateExceptions]
public MLResult RunInferenceFixed(MLRequest req)
{
MLResult mlResult = new MLResult();
Mat originMat = new Mat();
Mat detectMat = new Mat();
try
{
if (req.mImage == null)
{
mlResult.IsSuccess = false;
mlResult.ResultMessage = "异常mat为null无法执行推理";
return mlResult;
}
// resize
detectMat = req.mImage;//1ms
int iWidth = detectMat.Cols;
int iHeight = detectMat.Rows;
// 如果是单通道图像,转换为三通道 RGB 格式
if (detectMat.Channels() == 1)
{
// 将灰度图像转换为RGB格式三通道
Cv2.CvtColor(detectMat, originMat, ColorConversionCodes.GRAY2BGR);
}
else if (detectMat.Channels() == 3)
{
// 如果已经是三通道BGR则直接转换为RGB
Cv2.CvtColor(detectMat, originMat, ColorConversionCodes.BGR2RGB);
}
//输入数据转化为字节
var inputByte = new byte[originMat.Total() * 3];//这里必须乘以通道数不然数组越界也可以用w*h*c差不多
Marshal.Copy(originMat.Data, inputByte, 0, inputByte.Length);
byte[] labellist = new byte[40960]; //新建字节数组label1_str label2_str
byte[] outputByte = new byte[originMat.Total() * 3];
Stopwatch sw = new Stopwatch();
sw.Start();
//mlResult.IsSuccess = true;
unsafe
{
//mlResult.IsSuccess = MLGPUEngine.Inference(Model, inputByte, iWidth, iHeight, 3, req.in_lable_path, ref outputByte[0], ref labellist[0]);
mlResult.IsSuccess = MLGPUEngine.Inference2(Model, inputByte, iWidth, iHeight, 3, req.in_lable_path, ref labellist[0]);
}
sw.Stop();
if (mlResult.IsSuccess)
{
mlResult.ResultMessage = $"深度学习推理成功,耗时:{sw.ElapsedMilliseconds} ms";
//将字节数组转换为字符串
mlResult.ResultMap = originMat.ToBitmap();//4ms
string strGet = System.Text.Encoding.Default.GetString(labellist, 0, labellist.Length);
if (strGet == null)
{
mlResult.ResultMessage = $"异常:深度学习执行推理失败!";
return mlResult;
}
ConvertJsonResult(strGet, ref mlResult);
return mlResult;
}
else
{
mlResult.ResultMessage = $"异常:深度学习执行推理失败!";
return mlResult;
}
}
catch (Exception ex)
{
mlResult.ResultMessage = $"深度学习执行推理异常";
return mlResult;
}
finally
{
originMat?.Dispose();
originMat = null;
//maskMat?.Dispose();
// maskMat = null;
detectMat?.Dispose();
detectMat = null;
// maskWeighted?.Dispose();
// maskWeighted = null;
// GC.Collect();
}
}
}
}

View File

@ -0,0 +1,264 @@
//#define USE_MULTI_THREAD
using OpenCvSharp;
using OpenCvSharp.Extensions;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using Newtonsoft.Json;
namespace DH.Devices.Vision
{
/// <summary>
/// 实例分割 maskrcnn
/// </summary>
public class SimboInstanceSegmentation : SimboVisionMLBase
{
public override bool Load(MLInit mLInit)
{
bool res = false;
try
{
Model = MLEngine.InitModel(mLInit.ModelFile,
mLInit.InferenceDevice,
mLInit.InputNodeName,
1, 3,
mLInit.InferenceWidth,
mLInit.InferenceHeight,5);
res = true;
#if USE_MULTI_THREAD
IsCreated = true;
if (IsCreated)
{
if (_runHandleBefore == null)
{
_runHandleBefore = new AutoResetEvent(false);
}
if (_runHandleAfter == null)
{
_runHandleAfter = new ManualResetEvent(false);
}
if (_runTask == null)
{
_runTask = Task.Factory.StartNew(() =>
{
while (IsCreated)
{
_runHandleBefore.WaitOne();
if (IsCreated)
{
_result = RunInferenceFixed(_req);
_runHandleAfter.Set();
}
}
}, TaskCreationOptions.LongRunning);
}
}
#endif
}
catch (Exception ex)
{
throw ex;
}
return res;
}
#if USE_MULTI_THREAD
MLRequest _req = null;
MLResult _result = null;
public bool IsCreated { get; set; } = false;
Task _runTask = null;
AutoResetEvent _runHandleBefore = new AutoResetEvent(false);
ManualResetEvent _runHandleAfter = new ManualResetEvent(false);
object _runLock = new object();
#endif
[HandleProcessCorruptedStateExceptions]
public override MLResult RunInference(MLRequest req)
{
#if USE_MULTI_THREAD
MLResult mlResult = null;
lock (_runLock)
{
_result = new MLResult();
_req = req;
_runHandleAfter.Reset();
_runHandleBefore.Set();
_runHandleAfter.WaitOne();
mlResult = _result;
}
return mlResult;
#else
return RunInferenceFixed(req);
#endif
}
private void ConvertJsonResult(string json, ref MLResult result)
{
// json = "{\"FastDetResult\":[{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654843,\"rect\":[175,99,110,594]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654589,\"rect\":[2608,19,104,661]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.654285,\"rect\":[1275,19,104,662]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.620762,\"rect\":[1510,95,107,600]},{\"cls_id\":0,\"cls\":\"liewen\",\"fScore\":0.617812,\"rect\":[2844,93,106,602]}]}";
//
Console.WriteLine("检测结果JSON" + json);
SegResult detResult = JsonConvert.DeserializeObject<SegResult>(json);
if (detResult == null)
{
return;
}
int iNum = detResult.SegmentResult.Count;
int IokNum = 0;
for (int ix = 0; ix < iNum; ix++)
{
var det = detResult.SegmentResult[ix];
var rect = det.rect;
DetectionResultDetail detectionResultDetail = new DetectionResultDetail();
detectionResultDetail.LabelNo = det.classId;
//todo: 标签名相对应
detectionResultDetail.LabelDisplay = det.classname;
detectionResultDetail.Rect = new Rectangle(rect[0], rect[1], rect[2], rect[3]);
detectionResultDetail.Score = det.fScore;
detectionResultDetail.LabelName = det.classname;
detectionResultDetail.Area = det.area;
detectionResultDetail.InferenceResult = ResultState.DetectNG;
result.ResultDetails.Add(detectionResultDetail);
}
}
[HandleProcessCorruptedStateExceptions]
public MLResult RunInferenceFixed(MLRequest req)
{
MLResult mlResult = new MLResult();
Mat originMat = new Mat();
Mat detectMat = new Mat();
try
{
if (req.mImage == null)
{
mlResult.IsSuccess = false;
mlResult.ResultMessage = "异常mat为null无法执行推理";
return mlResult;
}
// resize
detectMat = req.mImage;//1ms
int iWidth = detectMat.Cols;
int iHeight = detectMat.Rows;
// 如果是单通道图像,转换为三通道 RGB 格式
if (detectMat.Channels() == 1)
{
// 将灰度图像转换为RGB格式三通道
Cv2.CvtColor(detectMat, originMat, ColorConversionCodes.GRAY2BGR);
}
else if (detectMat.Channels() == 3)
{
// 如果已经是三通道BGR则直接转换为RGB
Cv2.CvtColor(detectMat, originMat, ColorConversionCodes.BGR2RGB);
}
//输入数据转化为字节
var inputByte = new byte[originMat.Total() * 3];//这里必须乘以通道数不然数组越界也可以用w*h*c差不多
Marshal.Copy(originMat.Data, inputByte, 0, inputByte.Length);
byte[] labellist = new byte[40960]; //新建字节数组label1_str label2_str
byte[] outputByte = new byte[originMat.Total() * 3];
Stopwatch sw = new Stopwatch();
sw.Start();
unsafe
{
mlResult.IsSuccess = MLEngine.seg_ModelPredict(Model, inputByte, iWidth, iHeight, 3,
req.in_lable_path, req.confThreshold, req.iouThreshold, req.confThreshold, req.segmentWidth, ref outputByte[0], ref labellist[0]);
//mlResult.IsSuccess = true;
}
sw.Stop();
if (mlResult.IsSuccess)
{
mlResult.ResultMessage = $"深度学习推理成功,耗时:{sw.ElapsedMilliseconds} ms";
//将字节数组转换为字符串
mlResult.ResultMap = originMat.ToBitmap();//4ms
string strGet = System.Text.Encoding.Default.GetString(labellist, 0, labellist.Length);
Console.WriteLine("strGet:", strGet);
ConvertJsonResult(strGet, ref mlResult);
//解析json字符串
return mlResult;
}
else
{
mlResult.ResultMessage = $"异常:深度学习执行推理失败!";
return mlResult;
}
}
catch (Exception ex)
{
mlResult.ResultMessage = $"深度学习执行推理异常";
return mlResult;
}
finally
{
originMat?.Dispose();
originMat = null;
// GC.Collect();
}
}
}
}

View File

@ -12,28 +12,13 @@ using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using Newtonsoft.Json;
using System.Xml;
namespace DH.Devices.Vision
{
//public class SegResult
//{
// public List<Result> SegmentResult;
// public class Result
// {
// public double fScore;
// public int classId;
// public string classname;
// public double area;
// public List<int> rect;
// }
//}
@ -157,7 +142,6 @@ namespace DH.Devices.Vision
}
int iNum = detResult.SegmentResult.Count;
int IokNum = 0;
for (int ix = 0; ix < iNum; ix++)
{
var det = detResult.SegmentResult[ix];
@ -188,7 +172,7 @@ namespace DH.Devices.Vision
{
MLResult mlResult = new MLResult();
Mat originMat=new Mat() ;
Mat tempMat;
Mat detectMat= new Mat();
try
{
if (req.mImage == null)
@ -199,27 +183,28 @@ namespace DH.Devices.Vision
}
// resize
tempMat = req.mImage;//1ms
detectMat = req.mImage.Clone();//1ms
int iWidth = tempMat.Cols;
int iHeight = tempMat.Rows;
int iWidth = detectMat.Cols;
int iHeight = detectMat.Rows;
// 如果是单通道图像,转换为三通道 RGB 格式
if (tempMat.Channels() == 1)
if (detectMat.Channels() == 1)
{
// 将灰度图像转换为RGB格式三通道
Cv2.CvtColor( tempMat,originMat, ColorConversionCodes.GRAY2BGR);
Cv2.CvtColor( detectMat,originMat, ColorConversionCodes.GRAY2BGR);
}
else if (tempMat.Channels() == 3)
else if (detectMat.Channels() == 3)
{
// 如果已经是三通道BGR则直接转换为RGB
Cv2.CvtColor( tempMat,originMat, ColorConversionCodes.BGR2RGB);
// Cv2.CvtColor( detectMat,originMat, ColorConversionCodes.BGR2RGB);
// 直接使用原始图像
originMat = detectMat.Clone();
}
//输入数据转化为字节
@ -242,7 +227,7 @@ namespace DH.Devices.Vision
req.confThreshold, req.iouThreshold,
ref outputByte[0],
ref labellist[0]);
//mlResult.IsSuccess = true;
// mlResult.IsSuccess = true;
}
sw.Stop();
@ -250,9 +235,6 @@ namespace DH.Devices.Vision
{
mlResult.ResultMessage = $"深度学习推理成功,耗时:{sw.ElapsedMilliseconds} ms";
//Mat maskWeighted = new Mat(iHeight, iWidth, MatType.CV_8UC3, outputByte);
//mlResult.ResultMap = BitmapConverter.ToBitmap(maskWeighted);//4ms
//将字节数组转换为字符串
mlResult.ResultMap = originMat.ToBitmap();//4ms
string strGet = System.Text.Encoding.Default.GetString(labellist, 0, labellist.Length);
@ -261,9 +243,6 @@ namespace DH.Devices.Vision
ConvertJsonResult(strGet, ref mlResult);
//maskWeighted?.Dispose();
//maskWeighted = null;
// 解析json字符串
return mlResult;
}
@ -280,10 +259,19 @@ namespace DH.Devices.Vision
}
finally
{
req.mImage?.Dispose();
req.mImage = null;
originMat = null;
// 释放 Mat 资源
if (detectMat != null)
{
detectMat.Dispose();
detectMat = null;
}
if (originMat != null)
{
originMat.Dispose();
originMat = null;
}
// GC.Collect();

View File

@ -0,0 +1,18 @@
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace DH.Devices.Vision
{
public class SimboVisionDriver
{
}
}

View File

@ -2,6 +2,7 @@
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
@ -44,6 +45,31 @@ namespace DH.Devices.Vision
// ColorLut = new Mat(1, 256, MatType.CV_8UC3, ColorMap);
}
}
public class HYoloResult
{
//{
// "HYolo": [{
// "fScore": "0.687012",
// "classId": 0,
// "classname": "quejiao",
// "rect": [421, 823, 6, 8]
// }]
//}
public List<Result> HYolo;
public class Result
{
public double fScore;
public int classId;
public string classname;
//public double area;
public List<int> rect;
}
}
public class SegResult
{
public List<Result> SegmentResult;
@ -60,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

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

View File

@ -17,60 +17,72 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Commons", "Commons", "{0AB4
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DH.Commons", "DH.Commons\DH.Commons.csproj", "{027373EC-C5CB-4161-8D43-AB6009371FDE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DH.Devices.Vision", "DH.Devices.Vision\DH.Devices.Vision.csproj", "{97B55FCF-54A3-449E-8437-735E65C35291}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DH.Devices.Vision", "DH.Devices.Vision\DH.Devices.Vision.csproj", "{97B55FCF-54A3-449E-8437-735E65C35291}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DH.Devices.Camera", "DH.Devices.Camera\DH.Devices.Camera.csproj", "{1378A932-1C25-40EF-BA31-A3463B23F4E5}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DH.Devices.Camera", "DH.Devices.Camera\DH.Devices.Camera.csproj", "{1378A932-1C25-40EF-BA31-A3463B23F4E5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DH.Devices.PLC", "DH.Devices.PLC\DH.Devices.PLC.csproj", "{458B2CF6-6F1B-4B8B-BB85-C6FD7F453A5D}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DH.Devices.PLC", "DH.Devices.PLC\DH.Devices.PLC.csproj", "{458B2CF6-6F1B-4B8B-BB85-C6FD7F453A5D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Motion", "Motion", "{5C8472C6-EB6A-4D89-B519-7073BBF6A5D2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DH.Devices.Motion", "DH.Devices.Motion\DH.Devices.Motion.csproj", "{144E3775-0BD7-4528-9FB0-A0F4ADC74313}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|X64 = Debug|X64
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
Release|X64 = Release|X64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{17CC10DC-9132-4A03-AADA-2D1070418C9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{17CC10DC-9132-4A03-AADA-2D1070418C9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{17CC10DC-9132-4A03-AADA-2D1070418C9B}.Debug|X64.ActiveCfg = Debug|X64
{17CC10DC-9132-4A03-AADA-2D1070418C9B}.Debug|X64.Build.0 = Debug|X64
{17CC10DC-9132-4A03-AADA-2D1070418C9B}.Debug|x64.ActiveCfg = Debug|x64
{17CC10DC-9132-4A03-AADA-2D1070418C9B}.Debug|x64.Build.0 = Debug|x64
{17CC10DC-9132-4A03-AADA-2D1070418C9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{17CC10DC-9132-4A03-AADA-2D1070418C9B}.Release|Any CPU.Build.0 = Release|Any CPU
{17CC10DC-9132-4A03-AADA-2D1070418C9B}.Release|X64.ActiveCfg = Release|X64
{17CC10DC-9132-4A03-AADA-2D1070418C9B}.Release|X64.Build.0 = Release|X64
{17CC10DC-9132-4A03-AADA-2D1070418C9B}.Release|x64.ActiveCfg = Release|x64
{17CC10DC-9132-4A03-AADA-2D1070418C9B}.Release|x64.Build.0 = Release|x64
{027373EC-C5CB-4161-8D43-AB6009371FDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{027373EC-C5CB-4161-8D43-AB6009371FDE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{027373EC-C5CB-4161-8D43-AB6009371FDE}.Debug|X64.ActiveCfg = Debug|X64
{027373EC-C5CB-4161-8D43-AB6009371FDE}.Debug|X64.Build.0 = Debug|X64
{027373EC-C5CB-4161-8D43-AB6009371FDE}.Debug|x64.ActiveCfg = Debug|x64
{027373EC-C5CB-4161-8D43-AB6009371FDE}.Debug|x64.Build.0 = Debug|x64
{027373EC-C5CB-4161-8D43-AB6009371FDE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{027373EC-C5CB-4161-8D43-AB6009371FDE}.Release|Any CPU.Build.0 = Release|Any CPU
{027373EC-C5CB-4161-8D43-AB6009371FDE}.Release|X64.ActiveCfg = Release|X64
{027373EC-C5CB-4161-8D43-AB6009371FDE}.Release|X64.Build.0 = Release|X64
{027373EC-C5CB-4161-8D43-AB6009371FDE}.Release|x64.ActiveCfg = Release|x64
{027373EC-C5CB-4161-8D43-AB6009371FDE}.Release|x64.Build.0 = Release|x64
{97B55FCF-54A3-449E-8437-735E65C35291}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{97B55FCF-54A3-449E-8437-735E65C35291}.Debug|Any CPU.Build.0 = Debug|Any CPU
{97B55FCF-54A3-449E-8437-735E65C35291}.Debug|X64.ActiveCfg = Debug|X64
{97B55FCF-54A3-449E-8437-735E65C35291}.Debug|X64.Build.0 = Debug|X64
{97B55FCF-54A3-449E-8437-735E65C35291}.Debug|x64.ActiveCfg = Debug|x64
{97B55FCF-54A3-449E-8437-735E65C35291}.Debug|x64.Build.0 = Debug|x64
{97B55FCF-54A3-449E-8437-735E65C35291}.Release|Any CPU.ActiveCfg = Release|Any CPU
{97B55FCF-54A3-449E-8437-735E65C35291}.Release|Any CPU.Build.0 = Release|Any CPU
{97B55FCF-54A3-449E-8437-735E65C35291}.Release|X64.ActiveCfg = Release|X64
{97B55FCF-54A3-449E-8437-735E65C35291}.Release|X64.Build.0 = Release|X64
{97B55FCF-54A3-449E-8437-735E65C35291}.Release|x64.ActiveCfg = Release|x64
{97B55FCF-54A3-449E-8437-735E65C35291}.Release|x64.Build.0 = Release|x64
{1378A932-1C25-40EF-BA31-A3463B23F4E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1378A932-1C25-40EF-BA31-A3463B23F4E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1378A932-1C25-40EF-BA31-A3463B23F4E5}.Debug|X64.ActiveCfg = Debug|x64
{1378A932-1C25-40EF-BA31-A3463B23F4E5}.Debug|X64.Build.0 = Debug|x64
{1378A932-1C25-40EF-BA31-A3463B23F4E5}.Debug|x64.ActiveCfg = Debug|x64
{1378A932-1C25-40EF-BA31-A3463B23F4E5}.Debug|x64.Build.0 = Debug|x64
{1378A932-1C25-40EF-BA31-A3463B23F4E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1378A932-1C25-40EF-BA31-A3463B23F4E5}.Release|Any CPU.Build.0 = Release|Any CPU
{1378A932-1C25-40EF-BA31-A3463B23F4E5}.Release|X64.ActiveCfg = Release|x64
{1378A932-1C25-40EF-BA31-A3463B23F4E5}.Release|X64.Build.0 = Release|x64
{1378A932-1C25-40EF-BA31-A3463B23F4E5}.Release|x64.ActiveCfg = Release|x64
{1378A932-1C25-40EF-BA31-A3463B23F4E5}.Release|x64.Build.0 = Release|x64
{458B2CF6-6F1B-4B8B-BB85-C6FD7F453A5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{458B2CF6-6F1B-4B8B-BB85-C6FD7F453A5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{458B2CF6-6F1B-4B8B-BB85-C6FD7F453A5D}.Debug|X64.ActiveCfg = Debug|x64
{458B2CF6-6F1B-4B8B-BB85-C6FD7F453A5D}.Debug|X64.Build.0 = Debug|x64
{458B2CF6-6F1B-4B8B-BB85-C6FD7F453A5D}.Debug|x64.ActiveCfg = Debug|x64
{458B2CF6-6F1B-4B8B-BB85-C6FD7F453A5D}.Debug|x64.Build.0 = Debug|x64
{458B2CF6-6F1B-4B8B-BB85-C6FD7F453A5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{458B2CF6-6F1B-4B8B-BB85-C6FD7F453A5D}.Release|Any CPU.Build.0 = Release|Any CPU
{458B2CF6-6F1B-4B8B-BB85-C6FD7F453A5D}.Release|X64.ActiveCfg = Release|x64
{458B2CF6-6F1B-4B8B-BB85-C6FD7F453A5D}.Release|X64.Build.0 = Release|x64
{458B2CF6-6F1B-4B8B-BB85-C6FD7F453A5D}.Release|x64.ActiveCfg = Release|x64
{458B2CF6-6F1B-4B8B-BB85-C6FD7F453A5D}.Release|x64.Build.0 = Release|x64
{144E3775-0BD7-4528-9FB0-A0F4ADC74313}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{144E3775-0BD7-4528-9FB0-A0F4ADC74313}.Debug|Any CPU.Build.0 = Debug|Any CPU
{144E3775-0BD7-4528-9FB0-A0F4ADC74313}.Debug|x64.ActiveCfg = Debug|x64
{144E3775-0BD7-4528-9FB0-A0F4ADC74313}.Debug|x64.Build.0 = Debug|x64
{144E3775-0BD7-4528-9FB0-A0F4ADC74313}.Release|Any CPU.ActiveCfg = Release|Any CPU
{144E3775-0BD7-4528-9FB0-A0F4ADC74313}.Release|Any CPU.Build.0 = Release|Any CPU
{144E3775-0BD7-4528-9FB0-A0F4ADC74313}.Release|x64.ActiveCfg = Release|x64
{144E3775-0BD7-4528-9FB0-A0F4ADC74313}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -83,6 +95,8 @@ Global
{97B55FCF-54A3-449E-8437-735E65C35291} = {F77AF94C-280D-44C5-B7C0-FC86AA9EC504}
{1378A932-1C25-40EF-BA31-A3463B23F4E5} = {1591B03B-0015-42FC-B784-0D9F740E2A23}
{458B2CF6-6F1B-4B8B-BB85-C6FD7F453A5D} = {2560C5A5-0CA2-48AD-B606-6C55BEFD8109}
{5C8472C6-EB6A-4D89-B519-7073BBF6A5D2} = {8EC33C16-65CE-4C12-9C8D-DB2425F9F7C0}
{144E3775-0BD7-4528-9FB0-A0F4ADC74313} = {5C8472C6-EB6A-4D89-B519-7073BBF6A5D2}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6FC1A8DF-636E-434C-981E-10F20FAD723B}

View File

@ -12,6 +12,18 @@
<OutputType>WinExe</OutputType>
</PropertyGroup>
<ItemGroup>
<Compile Include="Views\CamConfigFrm.cs" />
<Compile Include="Views\CamConfigFrm.Designer.cs" />
<Compile Include="Views\UserConfigFrm.cs" />
<Compile Include="Views\UserConfigFrm.Designer.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Views\CamConfigFrm.resx" />
<EmbeddedResource Include="Views\UserConfigFrm.resx" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AntdUI" Version="1.8.9" />
<PackageReference Include="System.IO.Ports" Version="9.0.2" />
@ -19,13 +31,20 @@
<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>
<ItemGroup>
<Reference Include="DVPCameraCS64">
<HintPath>..\X64\Debug\DVPCameraCS64.dll</HintPath>
<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>

View File

@ -41,6 +41,7 @@
button_color = new AntdUI.Button();
buttonSZ = new AntdUI.Button();
pageHeader1 = new AntdUI.PageHeader();
label1 = new Label();
divider2 = new AntdUI.Divider();
panelmain = new AntdUI.Panel();
panel2 = new AntdUI.Panel();
@ -56,11 +57,9 @@
panel3 = new AntdUI.Panel();
tabs2 = new AntdUI.Tabs();
tabPage2 = new AntdUI.TabPage();
pictureBox1 = new PictureBox();
divider1 = new AntdUI.Divider();
panel1 = new AntdUI.Panel();
segmented1 = new AntdUI.Segmented();
label1 = new Label();
titlebar.SuspendLayout();
pageHeader1.SuspendLayout();
panelmain.SuspendLayout();
@ -73,8 +72,6 @@
tabPage3.SuspendLayout();
panel3.SuspendLayout();
tabs2.SuspendLayout();
tabPage2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit();
panel1.SuspendLayout();
SuspendLayout();
//
@ -139,6 +136,15 @@
pageHeader1.TabIndex = 7;
pageHeader1.Text = "UPH";
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(61, 10);
label1.Name = "label1";
label1.Size = new Size(64, 21);
label1.TabIndex = 1;
label1.Text = "100000";
//
// divider2
//
divider2.Dock = DockStyle.Top;
@ -285,22 +291,11 @@
//
// tabPage2
//
tabPage2.Controls.Add(pictureBox1);
tabPage2.Location = new Point(3, 28);
tabPage2.Name = "tabPage2";
tabPage2.Size = new Size(347, 469);
tabPage2.TabIndex = 0;
tabPage2.Text = "统计";
//
// pictureBox1
//
pictureBox1.Dock = DockStyle.Fill;
pictureBox1.Location = new Point(0, 0);
pictureBox1.Name = "pictureBox1";
pictureBox1.Size = new Size(347, 469);
pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
pictureBox1.TabIndex = 0;
pictureBox1.TabStop = false;
tabPage2.Text = "配置";
//
// divider1
//
@ -401,15 +396,6 @@
segmented1.Text = "segmented1";
segmented1.SelectIndexChanged += segmented1_SelectIndexChanged;
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(61, 10);
label1.Name = "label1";
label1.Size = new Size(64, 21);
label1.TabIndex = 1;
label1.Text = "100000";
//
// MainWindow
//
ClientSize = new Size(1024, 648);
@ -438,8 +424,6 @@
tabPage3.ResumeLayout(false);
panel3.ResumeLayout(false);
tabs2.ResumeLayout(false);
tabPage2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit();
panel1.ResumeLayout(false);
ResumeLayout(false);
}
@ -468,7 +452,6 @@
private AntdUI.TabPage tabPage2;
private AntdUI.Divider divider1;
private RichTextBox richTextBox1;
private PictureBox pictureBox1;
private Label label1;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Microsoft ResX Schema
Version 2.0
@ -48,7 +48,7 @@
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter

View File

@ -0,0 +1,44 @@
namespace DHSoftware.Views
{
partial class CamConfigFrm
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
SuspendLayout();
//
// CamConfigFrm
//
AutoScaleDimensions = new SizeF(7F, 17F);
AutoScaleMode = AutoScaleMode.Font;
Name = "CamConfigFrm";
Size = new Size(869, 521);
ResumeLayout(false);
}
#endregion
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DHSoftware.Views
{
public partial class CamConfigFrm : UserControl
{
public CamConfigFrm()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,44 @@
namespace DHSoftware.Views
{
partial class UserConfigFrm
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
SuspendLayout();
//
// UserConfigFrm
//
AutoScaleDimensions = new SizeF(7F, 17F);
AutoScaleMode = AutoScaleMode.Font;
Name = "UserConfigFrm";
Size = new Size(749, 536);
ResumeLayout(false);
}
#endregion
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DHSoftware.Views
{
public partial class UserConfigFrm : UserControl
{
public UserConfigFrm()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -78,16 +78,16 @@ namespace DHSoftware
}
public void InferenceOne(Action preAction = null, Action postAction = null)
public void InferenceOne()
{
//lock (_inferenceLock)
//{
// Interlocked.Decrement(ref InferenceLeft);
//}
preAction?.Invoke();
_countdownEvent.Signal();
postAction?.Invoke();
}
public bool InferenceFinished()