提交
This commit is contained in:
300
DH.Commons/Base/CameraBase.cs
Normal file
300
DH.Commons/Base/CameraBase.cs
Normal file
@ -0,0 +1,300 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing.Imaging;
|
||||
using AntdUI;
|
||||
using OpenCvSharp;
|
||||
|
||||
namespace DH.Commons.Base
|
||||
{
|
||||
public class CameraBase : NotifyProperty
|
||||
{
|
||||
// 私有字段 + 带通知的属性(与DetectionLabel风格一致)
|
||||
private bool _isEnabled = false;
|
||||
private bool _isContinueMode = false;
|
||||
private bool _isSavePicEnabled = false;
|
||||
private string _imageSaveDirectory;
|
||||
private ImageFormat _imageFormat = ImageFormat.Jpeg;
|
||||
private bool _isHardwareTrigger = false;
|
||||
private string _serialNumber = string.Empty;
|
||||
private string _cameraName = string.Empty;
|
||||
private string _cameraIP = string.Empty;
|
||||
private string _computerIP = string.Empty;
|
||||
private bool _isDirectHardwareTrigger = false;
|
||||
private float _gain = -1;
|
||||
private float _rotateImage = 0;
|
||||
private float _exposure = 200;
|
||||
private float _triggerDelay = 0;
|
||||
private decimal _roiX = 0;
|
||||
private decimal _roiY = 0;
|
||||
private decimal _roiW = 0;
|
||||
private decimal _roiH = 0;
|
||||
private int _lineDebouncerTime = 0;
|
||||
|
||||
public volatile int SnapshotCount = 0;
|
||||
|
||||
[Category("采图模式")]
|
||||
[DisplayName("连续模式")]
|
||||
[Description("是否连续模式。true:连续模式采图;false:触发模式采图")]
|
||||
public bool IsContinueMode
|
||||
{
|
||||
get => _isContinueMode;
|
||||
set
|
||||
{
|
||||
if (_isContinueMode == value) return;
|
||||
_isContinueMode = value;
|
||||
OnPropertyChanged(nameof(IsContinueMode));
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsEnabled
|
||||
{
|
||||
get => _isEnabled;
|
||||
set
|
||||
{
|
||||
if (_isEnabled == value) return;
|
||||
_isEnabled = value;
|
||||
OnPropertyChanged(nameof(IsEnabled));
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsSavePicEnabled
|
||||
{
|
||||
get => _isSavePicEnabled;
|
||||
set
|
||||
{
|
||||
if (_isSavePicEnabled == value) return;
|
||||
_isSavePicEnabled = value;
|
||||
OnPropertyChanged(nameof(IsSavePicEnabled));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("图片保存")]
|
||||
[DisplayName("图片保存文件夹")]
|
||||
[Description("图片保存文件夹")]
|
||||
public virtual string ImageSaveDirectory
|
||||
{
|
||||
get => _imageSaveDirectory;
|
||||
set
|
||||
{
|
||||
if (_imageSaveDirectory == value) return;
|
||||
_imageSaveDirectory = value;
|
||||
OnPropertyChanged(nameof(ImageSaveDirectory));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("图片保存")]
|
||||
[DisplayName("图片保存格式")]
|
||||
[Description("图片保存格式")]
|
||||
public ImageFormat ImageFormat
|
||||
{
|
||||
get => _imageFormat;
|
||||
set
|
||||
{
|
||||
if (_imageFormat == value) return;
|
||||
_imageFormat = value;
|
||||
OnPropertyChanged(nameof(ImageFormat));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("采图模式")]
|
||||
[DisplayName("硬触发")]
|
||||
[Description("是否硬触发模式。true:硬触发;false:软触发")]
|
||||
public bool IsHardwareTrigger
|
||||
{
|
||||
get => _isHardwareTrigger;
|
||||
set
|
||||
{
|
||||
if (_isHardwareTrigger == value) return;
|
||||
_isHardwareTrigger = value;
|
||||
OnPropertyChanged(nameof(IsHardwareTrigger));
|
||||
}
|
||||
}
|
||||
|
||||
public string SerialNumber
|
||||
{
|
||||
get => _serialNumber;
|
||||
set
|
||||
{
|
||||
if (_serialNumber == value) return;
|
||||
_serialNumber = value;
|
||||
OnPropertyChanged(nameof(SerialNumber));
|
||||
}
|
||||
}
|
||||
|
||||
public string CameraName
|
||||
{
|
||||
get => _cameraName;
|
||||
set
|
||||
{
|
||||
if (_cameraName == value) return;
|
||||
_cameraName = value;
|
||||
OnPropertyChanged(nameof(CameraName));
|
||||
}
|
||||
}
|
||||
|
||||
public string CameraIP
|
||||
{
|
||||
get => _cameraIP;
|
||||
set
|
||||
{
|
||||
if (_cameraIP == value) return;
|
||||
_cameraIP = value;
|
||||
OnPropertyChanged(nameof(CameraIP));
|
||||
}
|
||||
}
|
||||
|
||||
public string ComputerIP
|
||||
{
|
||||
get => _computerIP;
|
||||
set
|
||||
{
|
||||
if (_computerIP == value) return;
|
||||
_computerIP = value;
|
||||
OnPropertyChanged(nameof(ComputerIP));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("采图模式")]
|
||||
[DisplayName("是否传感器直接硬触发")]
|
||||
[Description("是否传感器直接硬触发。true:传感器硬触发,不通过软件触发;false:通过软件触发IO 的硬触发模式")]
|
||||
public bool IsDirectHardwareTrigger
|
||||
{
|
||||
get => _isDirectHardwareTrigger;
|
||||
set
|
||||
{
|
||||
if (_isDirectHardwareTrigger == value) return;
|
||||
_isDirectHardwareTrigger = value;
|
||||
OnPropertyChanged(nameof(IsDirectHardwareTrigger));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("相机设置")]
|
||||
[DisplayName("增益")]
|
||||
[Description("Gain:增益,-1:不设置,不同型号相机的增益,请参考mvs")]
|
||||
public float Gain
|
||||
{
|
||||
get => _gain;
|
||||
set
|
||||
{
|
||||
if (_gain.Equals(value)) return;
|
||||
_gain = value;
|
||||
OnPropertyChanged(nameof(Gain));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("图像旋转")]
|
||||
[DisplayName("默认旋转")]
|
||||
[Description("默认旋转,相机开启后默认不旋转")]
|
||||
public virtual float RotateImage
|
||||
{
|
||||
get => _rotateImage;
|
||||
set
|
||||
{
|
||||
if (_rotateImage.Equals(value)) return;
|
||||
_rotateImage = value;
|
||||
OnPropertyChanged(nameof(RotateImage));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("取像配置")]
|
||||
[DisplayName("曝光")]
|
||||
[Description("曝光")]
|
||||
public virtual float Exposure
|
||||
{
|
||||
get => _exposure;
|
||||
set
|
||||
{
|
||||
if (_exposure.Equals(value)) return;
|
||||
_exposure = value;
|
||||
OnPropertyChanged(nameof(Exposure));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("相机设置")]
|
||||
[DisplayName("硬触发后的延迟")]
|
||||
[Description("TriggerDelay:硬触发后的延迟,单位:us 微秒")]
|
||||
public float TriggerDelay
|
||||
{
|
||||
get => _triggerDelay;
|
||||
set
|
||||
{
|
||||
if (_triggerDelay.Equals(value)) return;
|
||||
_triggerDelay = value;
|
||||
OnPropertyChanged(nameof(TriggerDelay));
|
||||
}
|
||||
}
|
||||
|
||||
public decimal ROIX
|
||||
{
|
||||
get => _roiX;
|
||||
set
|
||||
{
|
||||
if (_roiX == value) return;
|
||||
_roiX = value;
|
||||
OnPropertyChanged(nameof(ROIX));
|
||||
}
|
||||
}
|
||||
|
||||
public decimal ROIY
|
||||
{
|
||||
get => _roiY;
|
||||
set
|
||||
{
|
||||
if (_roiY == value) return;
|
||||
_roiY = value;
|
||||
OnPropertyChanged(nameof(ROIY));
|
||||
}
|
||||
}
|
||||
|
||||
public decimal ROIW
|
||||
{
|
||||
get => _roiW;
|
||||
set
|
||||
{
|
||||
if (_roiW == value) return;
|
||||
_roiW = value;
|
||||
OnPropertyChanged(nameof(ROIW));
|
||||
}
|
||||
}
|
||||
|
||||
public decimal ROIH
|
||||
{
|
||||
get => _roiH;
|
||||
set
|
||||
{
|
||||
if (_roiH == value) return;
|
||||
_roiH = value;
|
||||
OnPropertyChanged(nameof(ROIH));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("相机设置")]
|
||||
[DisplayName("滤波时间")]
|
||||
[Description("LineDebouncerTime:I/O去抖时间 单位:us")]
|
||||
public int LineDebouncerTime
|
||||
{
|
||||
get => _lineDebouncerTime;
|
||||
set
|
||||
{
|
||||
if (_lineDebouncerTime == value) return;
|
||||
_lineDebouncerTime = value;
|
||||
OnPropertyChanged(nameof(LineDebouncerTime));
|
||||
}
|
||||
}
|
||||
|
||||
// 其他方法保持原有逻辑
|
||||
public Action<DateTime, CameraBase, Mat> OnHImageOutput { get; set; }
|
||||
|
||||
public virtual bool CameraConnect() { return false; }
|
||||
|
||||
public virtual bool CameraDisConnect() { return false; }
|
||||
|
||||
public virtual void SetExposure(int exposureTime, string cameraName) { }
|
||||
|
||||
public virtual void SetGain(int gain, string cameraName) { }
|
||||
|
||||
internal virtual void SetAcquisitionMode(int mode) { }
|
||||
|
||||
internal virtual void SetAcqRegion(int offsetV, int offsetH, int imageH, int imageW, string cameraName) { }
|
||||
}
|
||||
}
|
@ -7,26 +7,13 @@ using System.Text;
|
||||
using System.Drawing.Design;
|
||||
using AntdUI;
|
||||
using static DH.Commons.Enums.EnumHelper;
|
||||
using System.Text.Json.Serialization;
|
||||
using DH.Commons.Enums;
|
||||
|
||||
|
||||
namespace DH.Commons.Enums
|
||||
namespace DH.Commons.Base
|
||||
{
|
||||
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 class ModelLabel
|
||||
{
|
||||
public string LabelId { get; set; }
|
||||
|
||||
@ -42,7 +29,7 @@ namespace DH.Commons.Enums
|
||||
[Description("模型识别的标签名称")]
|
||||
public string LabelName { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//[Category("模型配置")]
|
||||
@ -71,28 +58,28 @@ namespace DH.Commons.Enums
|
||||
//public int ImageResizeCount;
|
||||
public bool IsCLDetection;
|
||||
public int ProCount;
|
||||
public string in_node_name;
|
||||
public string in_node_name;
|
||||
|
||||
public string out_node_name;
|
||||
public string out_node_name;
|
||||
|
||||
public string in_lable_path;
|
||||
public string in_lable_path;
|
||||
|
||||
public int ResizeImageSize;
|
||||
public int segmentWidth;
|
||||
public int ImageWidth;
|
||||
|
||||
// public List<labelStringBase> OkClassTxtList;
|
||||
// public List<labelStringBase> OkClassTxtList;
|
||||
|
||||
|
||||
public List<ModelLabel> LabelNames;
|
||||
public List<ModelLabel> LabelNames;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
public enum ResultState
|
||||
{
|
||||
|
||||
|
||||
[Description("检测NG")]
|
||||
DetectNG = -3,
|
||||
|
||||
@ -202,7 +189,7 @@ namespace DH.Commons.Enums
|
||||
|
||||
}
|
||||
}
|
||||
public class DetectStationResult
|
||||
public class DetectStationResult
|
||||
{
|
||||
#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||||
public string Pid { get; set; }
|
||||
@ -219,7 +206,7 @@ namespace DH.Commons.Enums
|
||||
public string DetectName { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 深度学习 检测结果
|
||||
/// </summary>
|
||||
@ -280,7 +267,7 @@ namespace DH.Commons.Enums
|
||||
|
||||
return cleanedString;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
public class RelatedCamera : NotifyProperty
|
||||
{
|
||||
@ -402,7 +389,7 @@ namespace DH.Commons.Enums
|
||||
|
||||
public static double GetDistance(CustomizedPoint p1, CustomizedPoint p2)
|
||||
{
|
||||
return Math.Sqrt(Math.Pow((p1.X - p2.X), 2) + Math.Pow((p1.Y - p2.Y), 2));
|
||||
return Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2));
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@ -443,13 +430,13 @@ namespace DH.Commons.Enums
|
||||
|
||||
public int CompareTo(CustomizedPoint other)
|
||||
{
|
||||
return (X == other.X && Y == other.Y) ? 0 : 1;
|
||||
return X == other.X && Y == other.Y ? 0 : 1;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
//return (int)(X * 10 + Y);
|
||||
return (new Tuple<double, double>(X, Y)).GetHashCode();
|
||||
return new Tuple<double, double>(X, Y).GetHashCode();
|
||||
}
|
||||
|
||||
public static CustomizedPoint operator -(CustomizedPoint p1, CustomizedPoint p2)
|
||||
@ -462,193 +449,421 @@ namespace DH.Commons.Enums
|
||||
return new CustomizedPoint(p1.X + p2.X, p1.Y + p2.Y);
|
||||
}
|
||||
}
|
||||
// public class PreTreatParam
|
||||
// {
|
||||
// public class PreTreatParam
|
||||
// {
|
||||
|
||||
// /// <summary>
|
||||
// /// 参数名称
|
||||
// /// </summary>
|
||||
// ///
|
||||
// [Category("预处理参数")]
|
||||
// [DisplayName("参数名称")]
|
||||
// [Description("参数名称")]
|
||||
//#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||||
// public string Name { get; set; }
|
||||
// /// <summary>
|
||||
// /// 参数名称
|
||||
// /// </summary>
|
||||
// ///
|
||||
// [Category("预处理参数")]
|
||||
// [DisplayName("参数名称")]
|
||||
// [Description("参数名称")]
|
||||
//#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||||
// public string Name { get; set; }
|
||||
|
||||
|
||||
|
||||
// /// <summary>
|
||||
// /// 参数值
|
||||
// /// </summary>
|
||||
// ///
|
||||
// [Category("预处理参数")]
|
||||
// [DisplayName("参数值")]
|
||||
// [Description("参数值")]
|
||||
//#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||||
// public string Value { get; set; }
|
||||
// /// <summary>
|
||||
// /// 参数值
|
||||
// /// </summary>
|
||||
// ///
|
||||
// [Category("预处理参数")]
|
||||
// [DisplayName("参数值")]
|
||||
// [Description("参数值")]
|
||||
//#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||||
// public string Value { get; set; }
|
||||
|
||||
|
||||
|
||||
// }
|
||||
public class DetectionConfig
|
||||
// }
|
||||
public class DetectionConfig : NotifyProperty
|
||||
{
|
||||
[ReadOnly(true)]
|
||||
public string Id { get; set; } = Guid.NewGuid().ToString();
|
||||
#region 属性字段
|
||||
private string _id = Guid.NewGuid().ToString();
|
||||
private string _name;
|
||||
private string _cameraSourceId = "";
|
||||
private List<RelatedCamera> _cameraCollects = new List<RelatedCamera>();
|
||||
private bool _isEnableGPU;
|
||||
private bool _isMixModel;
|
||||
private bool _isPreEnabled;
|
||||
private bool _isEnabled;
|
||||
private bool _isAddStation = true;
|
||||
private string _halconAlgorithemPath_Pre;
|
||||
private AntList<PreTreatParam> _preTreatParams = new AntList<PreTreatParam>();
|
||||
private AntList<PreTreatParam> _outPreTreatParams = new AntList<PreTreatParam>();
|
||||
private ModelType _modelType = ModelType.目标检测;
|
||||
private string _modelPath;
|
||||
private int _modelWidth = 640;
|
||||
private int _modelHeight = 640;
|
||||
private string _modeloutNodeName = "output0";
|
||||
private float _modelconfThreshold = 0.5f;
|
||||
private string _in_lable_path;
|
||||
private AntList<DetectionLable> _detectionLableList = new AntList<DetectionLable>();
|
||||
private AntList<SizeTreatParam> _sizeTreatParamList = new AntList<SizeTreatParam>();
|
||||
|
||||
private CustomizedPoint _showLocation = new CustomizedPoint();
|
||||
|
||||
private bool _saveOKOriginal = false;
|
||||
private bool _saveNGOriginal = false;
|
||||
private bool _saveOKDetect = false;
|
||||
private bool _saveNGDetect = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 属性声明
|
||||
[ReadOnly(true)]
|
||||
public string Id
|
||||
{
|
||||
get => _id;
|
||||
set
|
||||
{
|
||||
if (_id == value) return;
|
||||
_id = value;
|
||||
OnPropertyChanged(nameof(Id));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("检测配置")]
|
||||
[DisplayName("检测配置名称")]
|
||||
[Description("检测配置名称")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Category("关联相机")]
|
||||
[DisplayName("关联相机")]
|
||||
[Description("关联相机描述")]
|
||||
|
||||
|
||||
public string CameraSourceId { get; set; } = "";
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set
|
||||
{
|
||||
if (_name == value) return;
|
||||
_name = value;
|
||||
OnPropertyChanged(nameof(Name));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("关联相机集合")]
|
||||
[DisplayName("关联相机集合")]
|
||||
[Description("关联相机描述")]
|
||||
//[TypeConverter(typeof(DeviceIdSelectorConverter<CameraBase>))]
|
||||
|
||||
|
||||
|
||||
public List<RelatedCamera> CameraCollects { get; set; } = new List<RelatedCamera>();
|
||||
|
||||
public List<RelatedCamera> CameraCollects
|
||||
{
|
||||
get => _cameraCollects;
|
||||
set
|
||||
{
|
||||
if (_cameraCollects == value) return;
|
||||
_cameraCollects = value;
|
||||
OnPropertyChanged(nameof(CameraCollects));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("启用配置")]
|
||||
[DisplayName("是否启用GPU检测")]
|
||||
[Description("是否启用GPU检测")]
|
||||
public bool IsEnableGPU { get; set; } = false;
|
||||
public bool IsEnableGPU
|
||||
{
|
||||
get => _isEnableGPU;
|
||||
set
|
||||
{
|
||||
if (_isEnableGPU == value) return;
|
||||
_isEnableGPU = value;
|
||||
OnPropertyChanged(nameof(IsEnableGPU));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("启用配置")]
|
||||
[DisplayName("是否混料模型")]
|
||||
[Description("是否混料模型")]
|
||||
public bool IsMixModel { get; set; } = false;
|
||||
public bool IsMixModel
|
||||
{
|
||||
get => _isMixModel;
|
||||
set
|
||||
{
|
||||
if (_isMixModel == value) return;
|
||||
_isMixModel = value;
|
||||
OnPropertyChanged(nameof(IsMixModel));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Category("启用配置")]
|
||||
[DisplayName("是否启用预处理")]
|
||||
[Description("是否启用预处理")]
|
||||
public bool IsPreEnabled
|
||||
{
|
||||
get => _isPreEnabled;
|
||||
set
|
||||
{
|
||||
if (_isPreEnabled == value) return;
|
||||
_isPreEnabled = value;
|
||||
OnPropertyChanged(nameof(IsPreEnabled));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("启用配置")]
|
||||
[DisplayName("是否启用该检测")]
|
||||
[Description("是否启用该检测")]
|
||||
public bool IsEnabled { get; set; }
|
||||
public bool IsEnabled
|
||||
{
|
||||
get => _isEnabled;
|
||||
set
|
||||
{
|
||||
if (_isEnabled == value) return;
|
||||
_isEnabled = value;
|
||||
OnPropertyChanged(nameof(IsEnabled));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("启用配置")]
|
||||
[DisplayName("是否加入检测工位")]
|
||||
[Description("是否加入检测工位")]
|
||||
public bool IsAddStation { get; set; } = true;
|
||||
public bool IsAddStation
|
||||
{
|
||||
get => _isAddStation;
|
||||
set
|
||||
{
|
||||
if (_isAddStation == value) return;
|
||||
_isAddStation = value;
|
||||
OnPropertyChanged(nameof(IsAddStation));
|
||||
}
|
||||
}
|
||||
|
||||
[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>();
|
||||
public string HalconAlgorithemPath_Pre
|
||||
{
|
||||
get => _halconAlgorithemPath_Pre;
|
||||
set
|
||||
{
|
||||
if (_halconAlgorithemPath_Pre == value) return;
|
||||
_halconAlgorithemPath_Pre = value;
|
||||
OnPropertyChanged(nameof(HalconAlgorithemPath_Pre));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("1.预处理(视觉算子)")]
|
||||
[DisplayName("预处理-参数列表")]
|
||||
[Description("预处理-参数列表")]
|
||||
|
||||
public List<PreTreatParam> PreTreatParams { get; set; } = new List<PreTreatParam>();
|
||||
public AntList<PreTreatParam> PreTreatParams
|
||||
{
|
||||
get => _preTreatParams;
|
||||
set
|
||||
{
|
||||
if (_preTreatParams == value) return;
|
||||
_preTreatParams = value;
|
||||
OnPropertyChanged(nameof(PreTreatParams));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("1.预处理(视觉算子)")]
|
||||
[DisplayName("预处理-输出参数列表")]
|
||||
[Description("预处理-输出参数列表")]
|
||||
|
||||
public List<PreTreatParam> OUTPreTreatParams { get; set; } = new List<PreTreatParam>();
|
||||
public AntList<PreTreatParam> OUTPreTreatParams
|
||||
{
|
||||
get => _outPreTreatParams;
|
||||
set
|
||||
{
|
||||
if (_outPreTreatParams == value) return;
|
||||
_outPreTreatParams = value;
|
||||
OnPropertyChanged(nameof(OUTPreTreatParams));
|
||||
}
|
||||
}
|
||||
|
||||
[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;
|
||||
public ModelType ModelType
|
||||
{
|
||||
get => _modelType;
|
||||
set
|
||||
{
|
||||
if (_modelType == value) return;
|
||||
_modelType = value;
|
||||
OnPropertyChanged(nameof(ModelType));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("2.中检测(深度学习)")]
|
||||
[DisplayName("中检测-模型文件路径")]
|
||||
[Description("中处理 深度学习模型文件路径,路径中不可含有中文字符,一般情况可以只配置中检测模型,当需要先用预检测过滤一次时,请先配置好与预检测相关配置")]
|
||||
|
||||
public string ModelPath { get; set; }
|
||||
[Description("中处理 深度学习模型文件路径")]
|
||||
public string ModelPath
|
||||
{
|
||||
get => _modelPath;
|
||||
set
|
||||
{
|
||||
if (_modelPath == value) return;
|
||||
_modelPath = value;
|
||||
OnPropertyChanged(nameof(ModelPath));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("2.中检测(深度学习)")]
|
||||
[DisplayName("中检测-模型宽度")]
|
||||
[Description("中处理-模型宽度")]
|
||||
|
||||
public int ModelWidth { get; set; } = 640;
|
||||
public int ModelWidth
|
||||
{
|
||||
get => _modelWidth;
|
||||
set
|
||||
{
|
||||
if (_modelWidth == value) return;
|
||||
_modelWidth = value;
|
||||
OnPropertyChanged(nameof(ModelWidth));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("2.中检测(深度学习)")]
|
||||
[DisplayName("中检测-模型高度")]
|
||||
[Description("中处理-模型高度")]
|
||||
|
||||
public int ModelHeight { get; set; } = 640;
|
||||
public int ModelHeight
|
||||
{
|
||||
get => _modelHeight;
|
||||
set
|
||||
{
|
||||
if (_modelHeight == value) return;
|
||||
_modelHeight = value;
|
||||
OnPropertyChanged(nameof(ModelHeight));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("2.中检测(深度学习)")]
|
||||
[DisplayName("中检测-模型节点名称")]
|
||||
[Description("中处理-模型节点名称")]
|
||||
|
||||
public string ModeloutNodeName { get; set; } = "output0";
|
||||
public string ModeloutNodeName
|
||||
{
|
||||
get => _modeloutNodeName;
|
||||
set
|
||||
{
|
||||
if (_modeloutNodeName == value) return;
|
||||
_modeloutNodeName = value;
|
||||
OnPropertyChanged(nameof(ModeloutNodeName));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("2.中检测(深度学习)")]
|
||||
[DisplayName("中检测-模型置信度")]
|
||||
[Description("中处理-模型置信度")]
|
||||
|
||||
public float ModelconfThreshold { get; set; } = 0.5f;
|
||||
public float ModelconfThreshold
|
||||
{
|
||||
get => _modelconfThreshold;
|
||||
set
|
||||
{
|
||||
if (_modelconfThreshold == value) return;
|
||||
_modelconfThreshold = value;
|
||||
OnPropertyChanged(nameof(ModelconfThreshold));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("2.中检测(深度学习)")]
|
||||
[DisplayName("中检测-模型标签路径")]
|
||||
[Description("中处理-模型标签路径")]
|
||||
|
||||
public string in_lable_path { get; set; }
|
||||
|
||||
[Category("4.最终过滤(逻辑过滤)")]
|
||||
[DisplayName("过滤器集合")]
|
||||
[Description("最后的逻辑过滤:可根据 识别出对象的 宽度、高度、面积、得分来设置最终检测结果,同一识别目标同一判定,多项过滤器之间为“或”关系")]
|
||||
|
||||
public List<DetectionFilter> DetectionFilterList { get; set; } = new List<DetectionFilter>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 标签集合
|
||||
/// </summary>
|
||||
public List<DetectionLable> DetectionLableList { get; set; } = new List<DetectionLable>();
|
||||
//[Category("深度学习配置")]
|
||||
//[DisplayName("检测配置标签")]
|
||||
//[Description("检测配置标签关联")]
|
||||
|
||||
//public List<DetectConfigLabel> DetectConfigLabelList { get; set; } = new List<DetectConfigLabel>();
|
||||
[Category("显示配置")]
|
||||
[DisplayName("显示位置")]
|
||||
[Description("检测信息显示位置。左上角为(1,1),向右向下为正方向")]
|
||||
// [TypeConverter(typeof(ComplexObjectConvert))]
|
||||
// [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))]
|
||||
public CustomizedPoint ShowLocation { get; set; } = new CustomizedPoint();
|
||||
|
||||
public DetectionConfig()
|
||||
public string In_lable_path
|
||||
{
|
||||
|
||||
get => _in_lable_path;
|
||||
set
|
||||
{
|
||||
if (_in_lable_path == value) return;
|
||||
_in_lable_path = value;
|
||||
OnPropertyChanged(nameof(In_lable_path));
|
||||
}
|
||||
}
|
||||
|
||||
public DetectionConfig(string name, MLModelType modelType, string modelPath, bool isEnableGPU,string sCameraSourceId)
|
||||
{
|
||||
|
||||
|
||||
[Category("显示配置")]
|
||||
[DisplayName("显示位置")]
|
||||
[Description("检测信息显示位置")]
|
||||
public CustomizedPoint ShowLocation
|
||||
{
|
||||
get => _showLocation;
|
||||
set
|
||||
{
|
||||
if (_showLocation == value) return;
|
||||
_showLocation = value;
|
||||
OnPropertyChanged(nameof(ShowLocation));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 标签集合(需确保DetectionLable也实现INotifyPropertyChanged)
|
||||
/// </summary>
|
||||
public AntList<DetectionLable> DetectionLableList
|
||||
{
|
||||
get => _detectionLableList;
|
||||
set
|
||||
{
|
||||
if (_detectionLableList == value) return;
|
||||
_detectionLableList = value;
|
||||
OnPropertyChanged(nameof(DetectionLableList));
|
||||
}
|
||||
}
|
||||
|
||||
public AntList<SizeTreatParam> SizeTreatParamList
|
||||
{
|
||||
get => _sizeTreatParamList;
|
||||
set
|
||||
{
|
||||
if (_sizeTreatParamList == value) return;
|
||||
_sizeTreatParamList = value;
|
||||
OnPropertyChanged(nameof(SizeTreatParamList));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool SaveOKOriginal
|
||||
{
|
||||
get => _saveOKOriginal;
|
||||
set
|
||||
{
|
||||
if (_saveOKOriginal == value) return;
|
||||
_saveOKOriginal = value;
|
||||
OnPropertyChanged(nameof(SaveOKOriginal));
|
||||
}
|
||||
}
|
||||
|
||||
public bool SaveNGOriginal
|
||||
{
|
||||
get => _saveNGOriginal;
|
||||
set
|
||||
{
|
||||
if (_saveNGOriginal == value) return;
|
||||
_saveNGOriginal = value;
|
||||
OnPropertyChanged(nameof(SaveNGOriginal));
|
||||
}
|
||||
}
|
||||
public bool SaveOKDetect
|
||||
{
|
||||
get => _saveOKDetect;
|
||||
set
|
||||
{
|
||||
if (_saveOKDetect == value) return;
|
||||
_saveOKDetect = value;
|
||||
OnPropertyChanged(nameof(SaveOKDetect));
|
||||
}
|
||||
}
|
||||
public bool SaveNGDetect
|
||||
{
|
||||
get => _saveNGDetect;
|
||||
set
|
||||
{
|
||||
if (_saveNGDetect == value) return;
|
||||
_saveNGDetect = value;
|
||||
OnPropertyChanged(nameof(SaveNGDetect));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 构造函数
|
||||
public DetectionConfig() { }
|
||||
|
||||
public DetectionConfig(
|
||||
string name,
|
||||
ModelType modelType,
|
||||
string modelPath,
|
||||
bool isEnableGPU,
|
||||
string sCameraSourceId)
|
||||
{
|
||||
// 通过属性赋值触发通知
|
||||
ModelPath = modelPath ?? string.Empty;
|
||||
Name = name;
|
||||
ModelType = modelType;
|
||||
IsEnableGPU = isEnableGPU;
|
||||
Id = Guid.NewGuid().ToString();
|
||||
CameraSourceId = sCameraSourceId;
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
//大改预处理类
|
||||
@ -696,6 +911,7 @@ namespace DH.Commons.Enums
|
||||
}
|
||||
|
||||
private CellLink[] cellLinks;
|
||||
[JsonIgnore]
|
||||
public CellLink[] CellLinks
|
||||
{
|
||||
get { return cellLinks; }
|
||||
@ -724,7 +940,7 @@ namespace DH.Commons.Enums
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public bool Selected
|
||||
{
|
||||
get { return _selected; }
|
||||
@ -816,6 +1032,7 @@ namespace DH.Commons.Enums
|
||||
}
|
||||
|
||||
private CellLink[] cellLinks;
|
||||
[JsonIgnore]
|
||||
public CellLink[] CellLinks
|
||||
{
|
||||
get { return cellLinks; }
|
||||
@ -909,7 +1126,7 @@ namespace DH.Commons.Enums
|
||||
_resultShow = value;
|
||||
OnPropertyChanged(nameof(ResultShow));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public string OutResultShow
|
||||
@ -933,9 +1150,10 @@ namespace DH.Commons.Enums
|
||||
OnPropertyChanged(nameof(PrePath));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private CellLink[] cellLinks;
|
||||
[JsonIgnore]
|
||||
public CellLink[] CellLinks
|
||||
{
|
||||
get { return cellLinks; }
|
||||
@ -973,9 +1191,9 @@ namespace DH.Commons.Enums
|
||||
//[TypeConverter(typeof(LabelCategoryConverter))]
|
||||
public string LabelCategory { get; set; } = "";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1036,8 +1254,8 @@ namespace DH.Commons.Enums
|
||||
//public string GetLabelName()
|
||||
//{
|
||||
// var name = "";
|
||||
|
||||
|
||||
|
||||
|
||||
// var mlBase = iConfig.DeviceConfigs.FirstOrDefault(c => c is VisionEngineInitialConfigBase) as VisionEngineInitialConfigBase;
|
||||
// if (mlBase != null)
|
||||
// {
|
||||
@ -1048,7 +1266,7 @@ namespace DH.Commons.Enums
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// return name;
|
||||
//}
|
||||
}
|
||||
@ -1109,11 +1327,11 @@ namespace DH.Commons.Enums
|
||||
[DisplayName("过滤条件集合")]
|
||||
[Description("过滤条件集合,集合之间为“且”关系")]
|
||||
//[TypeConverter(typeof(CollectionCountConvert))]
|
||||
// [Editor(typeof(ComplexCollectionEditor<FilterConditions>), typeof(UITypeEditor))]
|
||||
// [Editor(typeof(ComplexCollectionEditor<FilterConditions>), typeof(UITypeEditor))]
|
||||
public List<FilterConditions> FilterConditionsCollection { get; set; } = new List<FilterConditions>();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public bool FilterOperation(DetectionResultDetail recongnitionResult)
|
||||
{
|
||||
return FilterConditionsCollection.All(u =>
|
408
DH.Commons/Base/PLCBase.cs
Normal file
408
DH.Commons/Base/PLCBase.cs
Normal file
@ -0,0 +1,408 @@
|
||||
using System.ComponentModel;
|
||||
using System.IO.Ports;
|
||||
using System.Text.Json.Serialization;
|
||||
using AntdUI;
|
||||
using DH.Commons.Enums; // 请确保此命名空间包含EnumPLCType
|
||||
|
||||
namespace DH.Commons.Base
|
||||
{
|
||||
public class PLCBase : NotifyProperty
|
||||
{
|
||||
// 私有字段
|
||||
private bool _enable;
|
||||
private bool _connected;
|
||||
private string _plcName;
|
||||
private EnumPLCType _plcType;
|
||||
private string _com = "COM1";
|
||||
private int _baudRate = 9600;
|
||||
private int _dataBit = 8;
|
||||
private StopBits _stopBit = StopBits.One;
|
||||
private Parity _parity = Parity.None;
|
||||
private string _ip = "192.168.6.6";
|
||||
private int _port = 502;
|
||||
private AntList<PLCItem> _PLCItemList = new AntList<PLCItem>();
|
||||
[Category("设备配置")]
|
||||
[DisplayName("是否启用")]
|
||||
[Description("是否启用")]
|
||||
public bool Enable
|
||||
{
|
||||
get => _enable;
|
||||
set
|
||||
{
|
||||
if (_enable == value) return;
|
||||
_enable = value;
|
||||
OnPropertyChanged(nameof(Enable));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Category("状态监控")]
|
||||
[DisplayName("连接状态")]
|
||||
[Description("PLC连接状态")]
|
||||
public bool Connected
|
||||
{
|
||||
get => _connected;
|
||||
set
|
||||
{
|
||||
if (_connected == value) return;
|
||||
_connected = value;
|
||||
OnPropertyChanged(nameof(Connected));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("设备配置")]
|
||||
[DisplayName("PLC名称")]
|
||||
[Description("PLC设备名称")]
|
||||
public string PLCName
|
||||
{
|
||||
get => _plcName;
|
||||
set
|
||||
{
|
||||
if (_plcName == value) return;
|
||||
_plcName = value;
|
||||
OnPropertyChanged(nameof(PLCName));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("设备配置")]
|
||||
[DisplayName("PLC类型")]
|
||||
[Description("PLC通信协议类型")]
|
||||
public EnumPLCType PLCType
|
||||
{
|
||||
get => _plcType;
|
||||
set
|
||||
{
|
||||
if (_plcType == value) return;
|
||||
_plcType = value;
|
||||
OnPropertyChanged(nameof(PLCType));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("串口配置")]
|
||||
[DisplayName("COM端口")]
|
||||
[Description("串口号,如COM1")]
|
||||
public string COM
|
||||
{
|
||||
get => _com;
|
||||
set
|
||||
{
|
||||
if (_com == value) return;
|
||||
_com = value;
|
||||
OnPropertyChanged(nameof(COM));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("串口配置")]
|
||||
[DisplayName("波特率")]
|
||||
[Description("串口通信波特率")]
|
||||
public int BaudRate
|
||||
{
|
||||
get => _baudRate;
|
||||
set
|
||||
{
|
||||
if (_baudRate == value) return;
|
||||
_baudRate = value;
|
||||
OnPropertyChanged(nameof(BaudRate));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("串口配置")]
|
||||
[DisplayName("数据位")]
|
||||
[Description("数据位长度(5/6/7/8)")]
|
||||
public int DataBit
|
||||
{
|
||||
get => _dataBit;
|
||||
set
|
||||
{
|
||||
if (_dataBit == value) return;
|
||||
_dataBit = value;
|
||||
OnPropertyChanged(nameof(DataBit));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("串口配置")]
|
||||
[DisplayName("停止位")]
|
||||
[Description("停止位设置")]
|
||||
public StopBits StopBit
|
||||
{
|
||||
get => _stopBit;
|
||||
set
|
||||
{
|
||||
if (_stopBit == value) return;
|
||||
_stopBit = value;
|
||||
OnPropertyChanged(nameof(StopBit));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("串口配置")]
|
||||
[DisplayName("校验位")]
|
||||
[Description("奇偶校验方式")]
|
||||
public Parity Parity
|
||||
{
|
||||
get => _parity;
|
||||
set
|
||||
{
|
||||
if (_parity == value) return;
|
||||
_parity = value;
|
||||
OnPropertyChanged(nameof(Parity));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("网络配置")]
|
||||
[DisplayName("IP地址")]
|
||||
[Description("PLC网络地址")]
|
||||
public string IP
|
||||
{
|
||||
get => _ip;
|
||||
set
|
||||
{
|
||||
if (_ip == value) return;
|
||||
_ip = value;
|
||||
OnPropertyChanged(nameof(IP));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("网络配置")]
|
||||
[DisplayName("端口号")]
|
||||
[Description("网络通信端口")]
|
||||
public int Port
|
||||
{
|
||||
get => _port;
|
||||
set
|
||||
{
|
||||
if (_port == value) return;
|
||||
_port = value;
|
||||
OnPropertyChanged(nameof(Port));
|
||||
}
|
||||
}
|
||||
|
||||
[Category("点位配置")]
|
||||
[DisplayName("点位配置")]
|
||||
[Description("点位配置")]
|
||||
public AntList<PLCItem> PLCItemList
|
||||
{
|
||||
get => _PLCItemList;
|
||||
set
|
||||
{
|
||||
if (_PLCItemList == value) return;
|
||||
_PLCItemList = value;
|
||||
OnPropertyChanged(nameof(PLCItemList));
|
||||
}
|
||||
}
|
||||
public virtual bool PLCConnect()
|
||||
{
|
||||
Connected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual bool PLCDisConnect()
|
||||
{
|
||||
Connected = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public virtual ushort ReadShort(string address) { return 0; }
|
||||
public virtual int ReadInt(string address) { return 0; }
|
||||
public virtual float ReadFloat(string address) { return 0; }
|
||||
public virtual bool ReadBool(string address) { return false; }
|
||||
public virtual bool WriteShort(string address, short value, bool waitForReply = true) { return false; }
|
||||
public virtual bool WriteInt(string address, int value, bool waitForReply = true) { return false; }
|
||||
public virtual bool WriteDInt(string address, int value, bool waitForReply = true) { return false; }
|
||||
public virtual bool WriteFloat(string address, float value, bool waitForReply = true) { return false; }
|
||||
public virtual bool WriteBool(string address, bool value, bool waitForReply = true) { return false; }
|
||||
}
|
||||
|
||||
|
||||
public class PLCItem : NotifyProperty
|
||||
{
|
||||
private bool _selected;
|
||||
private string _name = string.Empty;
|
||||
private string _type = string.Empty;
|
||||
private string _value = string.Empty;
|
||||
private bool _startexecute;
|
||||
private bool _endexecute;
|
||||
private int _startindex;
|
||||
private int _endindex;
|
||||
private string _numtype;
|
||||
private string _address;
|
||||
/// <summary>
|
||||
/// 是否选中
|
||||
/// </summary>
|
||||
public bool Selected
|
||||
{
|
||||
get => _selected;
|
||||
set
|
||||
{
|
||||
if (_selected != value)
|
||||
{
|
||||
_selected = value;
|
||||
OnPropertyChanged(nameof(Selected));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 参数名称
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set
|
||||
{
|
||||
if (_name != value)
|
||||
{
|
||||
_name = value;
|
||||
OnPropertyChanged(nameof(Name));
|
||||
}
|
||||
}
|
||||
}
|
||||
public string Type
|
||||
{
|
||||
get => _type;
|
||||
set
|
||||
{
|
||||
if (_type != value)
|
||||
{
|
||||
_type = value;
|
||||
OnPropertyChanged(nameof(Type));
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 参数类型
|
||||
/// </summary>
|
||||
public string Address
|
||||
{
|
||||
get => _address;
|
||||
set
|
||||
{
|
||||
if (_address != value)
|
||||
{
|
||||
_address = value;
|
||||
OnPropertyChanged(nameof(Address));
|
||||
}
|
||||
}
|
||||
}
|
||||
public string NumTpye
|
||||
{
|
||||
get => _numtype;
|
||||
set
|
||||
{
|
||||
if (_numtype != value)
|
||||
{
|
||||
_numtype = value;
|
||||
OnPropertyChanged(nameof(NumTpye));
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 参数值
|
||||
/// </summary>
|
||||
public string Value
|
||||
{
|
||||
get => _value;
|
||||
set
|
||||
{
|
||||
if (_value != value)
|
||||
{
|
||||
_value = value;
|
||||
OnPropertyChanged(nameof(Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 流程开启执行状态
|
||||
/// </summary>
|
||||
public bool StartExecute
|
||||
{
|
||||
get => _startexecute;
|
||||
set
|
||||
{
|
||||
if (_startexecute != value)
|
||||
{
|
||||
_startexecute = value;
|
||||
OnPropertyChanged(nameof(StartExecute));
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 流程结束执行状态
|
||||
/// </summary>
|
||||
public bool EndExecute
|
||||
{
|
||||
get => _endexecute;
|
||||
set
|
||||
{
|
||||
if (_endexecute != value)
|
||||
{
|
||||
_endexecute = value;
|
||||
OnPropertyChanged(nameof(EndExecute));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 流程开启顺序
|
||||
/// </summary>
|
||||
public int StartIndex
|
||||
{
|
||||
get => _startindex;
|
||||
set
|
||||
{
|
||||
if (_startindex != value)
|
||||
{
|
||||
_startindex = value;
|
||||
OnPropertyChanged(nameof(StartIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 流程结束顺序
|
||||
/// </summary>
|
||||
public int EndIndex
|
||||
{
|
||||
get => _endindex;
|
||||
set
|
||||
{
|
||||
if (_endindex != value)
|
||||
{
|
||||
_endindex = value;
|
||||
OnPropertyChanged(nameof(EndIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CellLink[] cellLinks;
|
||||
[JsonIgnore]
|
||||
public CellLink[] CellLinks
|
||||
{
|
||||
get { return cellLinks; }
|
||||
set
|
||||
{
|
||||
if (cellLinks == value) return;
|
||||
cellLinks = value;
|
||||
OnPropertyChanged(nameof(CellLinks));
|
||||
}
|
||||
}
|
||||
|
||||
private CellTag[] cellTags;
|
||||
[JsonIgnore]
|
||||
public CellTag[] CellTags
|
||||
{
|
||||
get { return cellTags; }
|
||||
set
|
||||
{
|
||||
if (cellTags == value) return;
|
||||
cellTags = value;
|
||||
OnPropertyChanged(nameof(CellTags));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
186
DH.Commons/Base/VisionEngineBase.cs
Normal file
186
DH.Commons/Base/VisionEngineBase.cs
Normal file
@ -0,0 +1,186 @@
|
||||
using System.Collections;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using DH.Commons.Enums;
|
||||
using HalconDotNet;
|
||||
using OpenCvSharp;
|
||||
|
||||
|
||||
|
||||
namespace DH.Commons.Base
|
||||
{
|
||||
/// <summary>
|
||||
/// 视觉处理引擎:1.传统视觉 2.深度学习
|
||||
/// CV深度学习 四大领域
|
||||
/// Image Classification 图像分类:判别图中物体是什么,比如是猫还是狗;
|
||||
/// Semantic Segmentation 语义分割:对图像进行像素级分类,预测每个像素属于的类别,不区分个体;
|
||||
/// Object Detection 目标检测:寻找图像中的物体并进行定位;
|
||||
/// Instance Segmentation 实例分割:定位图中每个物体,并进行像素级标注,区分不同个体;
|
||||
/// </summary>
|
||||
public abstract class VisionEngineBase
|
||||
{
|
||||
public List<DetectionConfig> DetectionConfigs = new List<DetectionConfig>();
|
||||
#region event
|
||||
public event Action<string, List<double>> OnCropParamsOutput;
|
||||
public event Action<string, Bitmap, List<IShapeElement>> OnDetectionDone;
|
||||
public event Action<string> OnDetectionWarningStop;//有无检测 需要报警停机
|
||||
#endregion
|
||||
//public VisionEngineInitialConfigBase IConfig
|
||||
//{
|
||||
// get => InitialConfig as VisionEngineInitialConfigBase;
|
||||
//}
|
||||
// public ImageSaveHelper ImageSaveHelper { get; set; } = new ImageSaveHelper();
|
||||
public string BatchNO { get; set; }
|
||||
|
||||
public HTuple hv_ModelID;
|
||||
|
||||
public abstract DetectStationResult RunInference(Mat originImgSet, string detectionId = null);
|
||||
|
||||
//public abstract void SaveDetectResultAsync(DetectStationResult detectResult);
|
||||
|
||||
|
||||
|
||||
public virtual void DetectionDone(string detectionId, Bitmap image, List<IShapeElement> detectionResults)
|
||||
{
|
||||
OnDetectionDone?.Invoke(detectionId, image, detectionResults);
|
||||
}
|
||||
|
||||
public virtual void DetectionWarningStop(string detectionDes)
|
||||
{
|
||||
OnDetectionWarningStop?.Invoke(detectionDes);
|
||||
}
|
||||
|
||||
public virtual void SaveImageAsync(string fullname, Bitmap saveMap, ImageFormat imageFormat)
|
||||
{
|
||||
if (saveMap != null)
|
||||
{
|
||||
//ImageSaveSet imageSaveSet = new ImageSaveSet()
|
||||
//{
|
||||
// FullName = fullname,
|
||||
// SaveImage = saveMap.CopyBitmap(),
|
||||
// ImageFormat = imageFormat.DeepSerializeClone()
|
||||
//};
|
||||
|
||||
//ImageSaveHelper.ImageSaveAsync(imageSaveSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
public class CamModuleXY
|
||||
{
|
||||
[Category("图片行")]
|
||||
[DisplayName("行")]
|
||||
[Description("行")]
|
||||
// [TypeConverter(typeof(DeviceIdSelectorConverter<CameraBase>))]
|
||||
//[TypeConverter(typeof(CollectionCountConvert))]
|
||||
public int PicRows { get; set; } = 1;
|
||||
|
||||
[Category("图片列")]
|
||||
[DisplayName("列")]
|
||||
[Description("列")]
|
||||
// [TypeConverter(typeof(DeviceIdSelectorConverter<CameraBase>))]
|
||||
//[TypeConverter(typeof(CollectionCountConvert))]
|
||||
public int PicCols { get; set; } = 1;
|
||||
|
||||
public string GetDisplayText()
|
||||
{
|
||||
return "行:" + PicRows.ToString() + "列:" + PicCols.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
//public class RelatedCamera
|
||||
//{
|
||||
|
||||
// [Category("关联相机")]
|
||||
// [DisplayName("关联相机")]
|
||||
// [Description("关联相机描述")]
|
||||
// //[TypeConverter(typeof(DeviceIdSelectorConverter<CameraBase>))]
|
||||
// //[TypeConverter(typeof(CollectionCountConvert))]
|
||||
// public string CameraSourceId { get; set; } = "";
|
||||
|
||||
|
||||
// //public string GetDisplayText()
|
||||
// //{
|
||||
// // using (var scope = GlobalVar.Container.BeginLifetimeScope())
|
||||
// // {
|
||||
// // List<IDevice> deviceList = scope.Resolve<List<IDevice>>();
|
||||
// // IDevice CameraDevice = deviceList.FirstOrDefault(dev => dev.Id.Equals(CameraSourceId));
|
||||
|
||||
// // if (CameraDevice != null && CameraDevice is CameraBase)
|
||||
// // {
|
||||
// // return CameraDevice.Name;
|
||||
// // }
|
||||
|
||||
// // }
|
||||
// // return CameraSourceId;
|
||||
// //}
|
||||
//}
|
||||
public class VisionEngineInitialConfigBase //: InitialConfigBase
|
||||
{
|
||||
[Category("深度学习检测配置")]
|
||||
[DisplayName("检测配置集合")]
|
||||
[Description("检测配置集合")]
|
||||
//[TypeConverter(typeof(CollectionCountConvert))]
|
||||
//[Editor(typeof(ComplexCollectionEditor<DetectionConfig>), typeof(UITypeEditor))]
|
||||
public List<DetectionConfig> DetectionConfigs { get; set; } = new List<DetectionConfig>();
|
||||
|
||||
[Category("深度学习检测配置")]
|
||||
[DisplayName("标签分类")]
|
||||
[Description("标签分类,A_NG,B_TBD...")]
|
||||
// [TypeConverter(typeof(CollectionCountConvert))]
|
||||
// [Editor(typeof(ComplexCollectionEditor<RecongnitionLabelCategory>), typeof(UITypeEditor))]
|
||||
public List<RecongnitionLabelCategory> RecongnitionLabelCategoryList { get; set; } = new List<RecongnitionLabelCategory>();
|
||||
|
||||
[Category("深度学习检测配置")]
|
||||
[DisplayName("检测标签定义集合")]
|
||||
[Description("定义检测标签的集合,例如:Seg/Detection模式:断裂、油污、划伤...;Class模式:ok、ng、上面、下面、套环、正常...")]
|
||||
// [TypeConverter(typeof(CollectionCountConvert))]
|
||||
// [Editor(typeof(ComplexCollectionEditor<RecongnitionLabel>), typeof(UITypeEditor))]
|
||||
public List<RecongnitionLabel> RecongnitionLabelList { get; set; } = new List<RecongnitionLabel>();
|
||||
|
||||
[Category("深度学习检测配置")]
|
||||
[DisplayName("标签置信度")]
|
||||
[Description("标签置信度,过滤小于改置信度的标签,大于该设置的标签才能识别")]
|
||||
public float Score { get; set; } = 0.5f;
|
||||
|
||||
[Category("深度学习检测配置")]
|
||||
[DisplayName("CPU线程数量")]
|
||||
[Description("用于深度学习的CPU线程数量,不要设置太大,会单独占用线程,影响其他程序运行")]
|
||||
public int CPUNums { get; set; } = 1;
|
||||
|
||||
//[Category("深度学习检测配置")]
|
||||
//[DisplayName("检测项GPU指定")]
|
||||
//[Description("将检测项指定到GPU")]
|
||||
// [TypeConverter(typeof(CollectionCountConvert))]
|
||||
// [Editor(typeof(ComplexCollectionEditor<DetectionGPUConfig>), typeof(UITypeEditor))]
|
||||
// public List<DetectionGPUConfig> DetectionGPUList { get; set; } = new List<DetectionGPUConfig>();
|
||||
|
||||
// [Category("数据保存配置")]
|
||||
//[DisplayName("是否保存检测明细CSV")]
|
||||
//[Description("是否保存 检测明细CSV")]
|
||||
//public override bool IsEnableCSV { get; set; } = true;
|
||||
|
||||
//[Category("数据保存配置")]
|
||||
//[DisplayName("是否保存检测图片")]
|
||||
//[Description("是否保存 检测图片,总开关")]
|
||||
//public bool IsSaveImage { get; set; } = true;
|
||||
|
||||
//[Category("数据保存配置")]
|
||||
//[Description("检测图片 保存文件夹")]
|
||||
//[DisplayName("检测图片保存文件夹")]
|
||||
//[Editor(typeof(FoldDialogEditor), typeof(UITypeEditor))]
|
||||
//public string ImageSaveDirectory { get; set; } = "D:\\PROJECTS\\X017\\Images";
|
||||
|
||||
//[Category("数据保存配置")]
|
||||
//[Description("检测明细CSV文件夹")]
|
||||
//[DisplayName("检测明细CSV文件夹")]
|
||||
//[Editor(typeof(FoldDialogEditor), typeof(UITypeEditor))]
|
||||
//public string CSVDataPath { get; set; } = "D:\\PROJECTS\\X017\\Images";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -13,12 +13,19 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AntdUI" Version="1.8.9" />
|
||||
<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" />
|
||||
<PackageReference Include="System.IO.Ports" Version="9.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -1,16 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DH.Commons.Enums
|
||||
{
|
||||
public class CameraInfo
|
||||
{
|
||||
public string CamName { get; set; }
|
||||
public string Serinum { get; set; }
|
||||
public string IP { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -7,12 +7,48 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace DH.Commons.Enums
|
||||
{
|
||||
|
||||
public enum ModelType
|
||||
{
|
||||
图像分类 = 1,
|
||||
目标检测 = 2,
|
||||
语义分割 = 3,
|
||||
实例分割 = 4,
|
||||
目标检测GPU = 5
|
||||
}
|
||||
public enum SelectPicType
|
||||
{
|
||||
[Description("训练图片")]
|
||||
train = 0,
|
||||
[Description("测试图片")]
|
||||
test
|
||||
|
||||
}
|
||||
public enum NetModel
|
||||
{
|
||||
[Description("目标检测")]
|
||||
training = 0,
|
||||
[Description("语义分割")]
|
||||
train_seg,
|
||||
[Description("模型导出")]
|
||||
emport,
|
||||
[Description("推理预测")]
|
||||
infernce
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public enum EnumPLCType
|
||||
{
|
||||
信捷XC_串口,
|
||||
信捷XC_网口,
|
||||
信捷XD_串口,
|
||||
信捷XD_网口
|
||||
[Description("信捷XC串口")]
|
||||
信捷XC串口 = 0,
|
||||
[Description("信捷XC网口")]
|
||||
信捷XC网口 = 1,
|
||||
[Description("信捷XD串口")]
|
||||
信捷XD串口 = 2,
|
||||
[Description("信捷XD网口")]
|
||||
信捷XD网口 = 3
|
||||
}
|
||||
|
||||
|
||||
@ -43,20 +79,39 @@ namespace DH.Commons.Enums
|
||||
工位3=13,
|
||||
工位4=14,
|
||||
工位5=15,
|
||||
OK料盒=16,
|
||||
NG料盒=17,
|
||||
OK吹气时间=18,
|
||||
NG吹气时间=19,
|
||||
产品计数=20,
|
||||
计数清零=21,
|
||||
工件最小值=22,
|
||||
工具最大值=23,
|
||||
启用心跳=24,
|
||||
心跳=25
|
||||
工位6 = 16,
|
||||
工位7 = 17,
|
||||
工位8 = 18,
|
||||
工位9 = 19,
|
||||
工位10 = 20,
|
||||
OK料盒 =21,
|
||||
NG料盒=22,
|
||||
OK吹气时间=23,
|
||||
NG吹气时间=24,
|
||||
产品计数=25,
|
||||
计数清零=26,
|
||||
工件最小值=27,
|
||||
工具最大值=28,
|
||||
启用心跳=29,
|
||||
心跳地址=30
|
||||
|
||||
}
|
||||
|
||||
|
||||
public enum EnumPLCDataType
|
||||
{
|
||||
HD,
|
||||
D,
|
||||
M
|
||||
}
|
||||
public enum EnumPLCINTType
|
||||
{
|
||||
单字16位,
|
||||
单字32位,
|
||||
双字16位,
|
||||
双字32位
|
||||
}
|
||||
|
||||
public enum StreamFormat
|
||||
{
|
||||
[Description("8位图像")]
|
||||
|
227
DH.Commons/Helper/ConfigHelper.cs
Normal file
227
DH.Commons/Helper/ConfigHelper.cs
Normal file
@ -0,0 +1,227 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using DH.Commons.Base;
|
||||
using DH.Commons.Models;
|
||||
|
||||
namespace DH.Commons.Helper
|
||||
{
|
||||
public static class ConfigHelper
|
||||
{
|
||||
private static readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
IgnoreNullValues = true
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 配置存储根目录
|
||||
/// </summary>
|
||||
private static string ConfigsRoot => Path.Combine(
|
||||
AppDomain.CurrentDomain.BaseDirectory,
|
||||
"configs");
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前方案的主配置文件路径
|
||||
/// </summary>
|
||||
private static string CurrentConfigPath
|
||||
{
|
||||
get
|
||||
{
|
||||
ValidateCurrentScheme();
|
||||
return Path.Combine(
|
||||
ConfigsRoot,
|
||||
$"config_{SystemModel.CurrentScheme}.json");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前方案的备份目录路径
|
||||
/// </summary>
|
||||
private static string CurrentBackupDir
|
||||
{
|
||||
get
|
||||
{
|
||||
ValidateCurrentScheme();
|
||||
return Path.Combine(
|
||||
ConfigsRoot,
|
||||
$"bak_{SystemModel.CurrentScheme}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化新方案(创建空文件)
|
||||
/// </summary>
|
||||
public static void InitializeScheme(string scheme)
|
||||
{
|
||||
SystemModel.CurrentScheme = scheme;
|
||||
|
||||
// 创建空配置文件
|
||||
if (!File.Exists(CurrentConfigPath))
|
||||
{
|
||||
Directory.CreateDirectory(ConfigsRoot);
|
||||
File.WriteAllText(CurrentConfigPath, "{}");
|
||||
}
|
||||
|
||||
// 创建备份目录
|
||||
Directory.CreateDirectory(CurrentBackupDir);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存当前配置(自动备份)
|
||||
/// </summary>
|
||||
public static void SaveConfig()
|
||||
{
|
||||
ValidateCurrentScheme();
|
||||
|
||||
// 确保配置目录存在
|
||||
Directory.CreateDirectory(ConfigsRoot);
|
||||
|
||||
// 备份现有配置
|
||||
if (File.Exists(CurrentConfigPath))
|
||||
{
|
||||
var backupName = $"config_{SystemModel.CurrentScheme}_{DateTime.Now:yyyyMMddHHmmss}.json";
|
||||
var backupPath = Path.Combine(CurrentBackupDir, backupName);
|
||||
|
||||
Directory.CreateDirectory(CurrentBackupDir);
|
||||
File.Copy(CurrentConfigPath, backupPath);
|
||||
}
|
||||
|
||||
// 序列化当前配置
|
||||
var json = JsonSerializer.Serialize(new
|
||||
{
|
||||
ConfigModel.CameraBaseList,
|
||||
ConfigModel.PLCBaseList,
|
||||
ConfigModel.DetectionList
|
||||
}, _jsonOptions);
|
||||
|
||||
// 写入新配置
|
||||
File.WriteAllText(CurrentConfigPath, json);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载当前方案配置
|
||||
/// </summary>
|
||||
public static void LoadConfig()
|
||||
{
|
||||
ValidateCurrentScheme();
|
||||
|
||||
if (!File.Exists(CurrentConfigPath))
|
||||
{
|
||||
InitializeScheme(SystemModel.CurrentScheme);
|
||||
return;
|
||||
}
|
||||
|
||||
var json = File.ReadAllText(CurrentConfigPath);
|
||||
var data = JsonSerializer.Deserialize<ConfigData>(json, _jsonOptions);
|
||||
|
||||
ConfigModel.CameraBaseList = data?.Cameras ?? new List<CameraBase>();
|
||||
ConfigModel.PLCBaseList = data?.PLCs ?? new List<PLCBase>();
|
||||
ConfigModel.DetectionList = data?.Detections ?? new List<DetectionConfig>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证当前方案有效性
|
||||
/// </summary>
|
||||
private static void ValidateCurrentScheme()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(SystemModel.CurrentScheme))
|
||||
throw new InvalidOperationException("当前方案未设置");
|
||||
}
|
||||
/// <summary>
|
||||
/// 派生新方案(基于当前方案创建副本)
|
||||
/// </summary>
|
||||
/// <param name="newSchemeName">新方案名称</param>
|
||||
public static void DeriveScheme(string newSchemeName)
|
||||
{
|
||||
// 验证输入
|
||||
if (string.IsNullOrWhiteSpace(newSchemeName))
|
||||
{
|
||||
throw new ArgumentException("新方案名称不能为空");
|
||||
}
|
||||
|
||||
// 验证当前方案是否有效
|
||||
ValidateCurrentScheme();
|
||||
|
||||
// 检查新方案是否已存在
|
||||
var newConfigPath = Path.Combine(ConfigsRoot, $"config_{newSchemeName}.json");
|
||||
if (File.Exists(newConfigPath))
|
||||
{
|
||||
throw new InvalidOperationException($"方案 {newSchemeName} 已存在");
|
||||
}
|
||||
|
||||
// 保存当前配置确保最新
|
||||
SaveConfig();
|
||||
|
||||
try
|
||||
{
|
||||
// 复制配置文件
|
||||
File.Copy(CurrentConfigPath, newConfigPath);
|
||||
|
||||
// 创建备份目录
|
||||
var newBackupDir = Path.Combine(ConfigsRoot, $"bak_{newSchemeName}");
|
||||
Directory.CreateDirectory(newBackupDir);
|
||||
|
||||
// 可选:自动切换新方案
|
||||
// SystemModel.CurrentScheme = newSchemeName;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw new InvalidOperationException($"方案派生失败: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除指定方案的配置文件及备份目录
|
||||
/// </summary>
|
||||
/// <param name="schemeName">要删除的方案名称</param>
|
||||
/// <exception cref="ArgumentException">当方案名称为空时抛出</exception>
|
||||
/// <exception cref="IOException">文件操作失败时抛出</exception>
|
||||
public static void DeleteSchemeConfig(string schemeName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(schemeName))
|
||||
throw new ArgumentException("方案名称无效");
|
||||
|
||||
// 构造路径
|
||||
var configPath = Path.Combine(ConfigsRoot, $"config_{schemeName}.json");
|
||||
var backupDir = Path.Combine(ConfigsRoot, $"bak_{schemeName}");
|
||||
|
||||
try
|
||||
{
|
||||
// 删除配置文件
|
||||
if (File.Exists(configPath))
|
||||
{
|
||||
File.Delete(configPath);
|
||||
}
|
||||
|
||||
// 删除备份目录(递归删除)
|
||||
if (Directory.Exists(backupDir))
|
||||
{
|
||||
Directory.Delete(backupDir, true);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException)
|
||||
{
|
||||
throw new IOException($"删除方案 {schemeName} 的配置文件失败: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 配置数据模型(内部类)
|
||||
/// </summary>
|
||||
private class ConfigData
|
||||
{
|
||||
[JsonPropertyName("cameraBaseList")]
|
||||
public List<CameraBase> Cameras { get; set; } = new List<CameraBase>();
|
||||
|
||||
[JsonPropertyName("plcBaseList")]
|
||||
public List<PLCBase> PLCs { get; set; } = new List<PLCBase>();
|
||||
|
||||
[JsonPropertyName("detectionList")]
|
||||
public List<DetectionConfig> Detections { get; set; } = new List<DetectionConfig>();
|
||||
}
|
||||
}
|
||||
}
|
@ -76,160 +76,50 @@ namespace DH.Commons.Enums
|
||||
}
|
||||
}
|
||||
|
||||
//public static System.Windows.Media.Color GetEnumSelectedMediaColor(this Enum enumObj)
|
||||
//{
|
||||
// Type t = enumObj.GetType();
|
||||
// FieldInfo f = t.GetField(enumObj.ToString());
|
||||
|
||||
// ColorSelectAttribute attr = f.GetCustomAttribute<ColorSelectAttribute>();
|
||||
// if (attr != null)
|
||||
// {
|
||||
// var prop = typeof(System.Windows.Media.Colors).GetProperties().FirstOrDefault(p => p.Name == attr.SelectedColor);
|
||||
// if (prop != null)
|
||||
// {
|
||||
// return (System.Windows.Media.Color)prop.GetValue(null);
|
||||
// }
|
||||
// }
|
||||
// return System.Windows.Media.Colors.Transparent;
|
||||
//}
|
||||
|
||||
//public static System.Drawing.Color GetEnumSelectedColor(this Enum enumObj)
|
||||
//{
|
||||
// Type t = enumObj.GetType();
|
||||
// FieldInfo f = t.GetField(enumObj.ToString());
|
||||
|
||||
// ColorSelectAttribute attr = f.GetCustomAttribute<ColorSelectAttribute>();
|
||||
// if (attr != null)
|
||||
// {
|
||||
// return System.Drawing.Color.FromName(attr.SelectedColor);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return System.Drawing.Color.Transparent;
|
||||
// }
|
||||
//}
|
||||
|
||||
//public static System.Drawing.Color GetEnumSelectedFontColor(this Enum enumObj)
|
||||
//{
|
||||
// Type t = enumObj.GetType();
|
||||
// FieldInfo f = t.GetField(enumObj.ToString());
|
||||
|
||||
// var attr = f.GetCustomAttribute<FontColorSelectAttribute>();
|
||||
// if (attr != null)
|
||||
// {
|
||||
// return System.Drawing.Color.FromName(attr.SelectedColor);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return System.Drawing.Color.Transparent;
|
||||
// }
|
||||
//}
|
||||
|
||||
//public static string GetEnumSelectedColorString(this Enum enumObj)
|
||||
//{
|
||||
// Type t = enumObj.GetType();
|
||||
// FieldInfo f = t.GetField(enumObj.ToString());
|
||||
|
||||
// ColorSelectAttribute attr = f.GetCustomAttribute<ColorSelectAttribute>();
|
||||
// if (attr != null)
|
||||
// {
|
||||
// return attr.SelectedColor;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return "Transparent";
|
||||
// }
|
||||
//}
|
||||
|
||||
// 根据描述获取枚举值(泛型方法)
|
||||
public static T GetEnumFromDescription<T>(string description) where T : Enum
|
||||
{
|
||||
Type enumType = typeof(T);
|
||||
foreach (T value in Enum.GetValues(enumType))
|
||||
{
|
||||
string desc = GetEnumDescription(value);
|
||||
if (desc == description)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
throw new ArgumentException($"在枚举 {enumType.Name} 中未找到描述为 '{description}' 的值");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当枚举牵涉到状态变换,检查现状态是否满足待转换的状态的前置状态要求
|
||||
/// 获取枚举类型的所有描述文本
|
||||
/// </summary>
|
||||
/// <param name="stateToBe"></param>
|
||||
/// <param name="currentState"></param>
|
||||
/// <returns></returns>
|
||||
//public static bool CheckPreStateValid(this Enum stateToBe, int currentState)
|
||||
//{
|
||||
// Type t = stateToBe.GetType();
|
||||
// FieldInfo f = t.GetField(stateToBe.ToString());
|
||||
/// <param name="enumType">枚举类型</param>
|
||||
/// <returns>描述文本列表</returns>
|
||||
public static List<string> GetEnumDescriptions(Type enumType)
|
||||
{
|
||||
// 验证类型是否为枚举
|
||||
if (!enumType.IsEnum)
|
||||
throw new ArgumentException("传入的类型必须是枚举类型", nameof(enumType));
|
||||
|
||||
// PreStateAttribute attr = f.GetCustomAttribute<PreStateAttribute>();
|
||||
// if (attr == null)
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return attr.CheckPreStateValid(currentState);
|
||||
// }
|
||||
//}
|
||||
var descriptions = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 设备状态定义
|
||||
/// 未初始化和异常状态无前置状态要求
|
||||
/// 初始化操作前置状态必须是未初始化、关闭状态和异常状态
|
||||
/// 打开前置必须是初始化和暂停
|
||||
/// 关闭前置必须是打开和暂停和异常
|
||||
/// 暂停前置必须是打开
|
||||
/// </summary>
|
||||
//public enum DeviceState
|
||||
//{
|
||||
// TBD = -1,
|
||||
|
||||
// [ColorSelect("Gray")]
|
||||
// [FontColorSelect("Black")]
|
||||
// [Description("未初始化")]
|
||||
// DSUninit = 1,
|
||||
|
||||
// [ColorSelect("Gold")]
|
||||
// [FontColorSelect("White")]
|
||||
// [PreState(1 + 2 + 4 + 8 + 32)]
|
||||
// [Description("初始化")]
|
||||
// DSInit = 2,
|
||||
|
||||
// [ColorSelect("Lime")]
|
||||
// [FontColorSelect("Black")]
|
||||
// [PreState(2 + 4 + 16)]
|
||||
// [Description("运行中")]
|
||||
// DSOpen = 4,
|
||||
|
||||
// [ColorSelect("Gray")]
|
||||
// [FontColorSelect("White")]
|
||||
// [PreState(1 + 4 + 8 + 16 + 32)]
|
||||
// [Description("关闭")]
|
||||
// DSClose = 8,
|
||||
|
||||
// [ColorSelect("Gold")]
|
||||
// [FontColorSelect("White")]
|
||||
// [PreState(4 + 16)]
|
||||
// [Description("暂停")]
|
||||
// DSPause = 16,
|
||||
|
||||
// [ColorSelect("Red")]
|
||||
// [FontColorSelect("White")]
|
||||
// [Description("异常")]
|
||||
// DSExcept = 32
|
||||
//}
|
||||
|
||||
///// <summary>
|
||||
///// 工序状态
|
||||
///// </summary>
|
||||
//public enum RunState
|
||||
//{
|
||||
// [ColorSelect("Gold")]
|
||||
// [Description("空闲")]
|
||||
// Idle = 1,
|
||||
// [ColorSelect("Lime")]
|
||||
// [Description("运行中")]
|
||||
// Running = 2,
|
||||
// [ColorSelect("Gray")]
|
||||
// [Description("停止")]
|
||||
// Stop = 3,
|
||||
// [ColorSelect("Red")]
|
||||
// [Description("宕机")]
|
||||
// Down = 99,
|
||||
//}
|
||||
foreach (var value in Enum.GetValues(enumType))
|
||||
{
|
||||
var fieldInfo = enumType.GetField(value.ToString());
|
||||
var attribute = fieldInfo.GetCustomAttribute<DescriptionAttribute>();
|
||||
descriptions.Add(attribute?.Description ?? value.ToString());
|
||||
}
|
||||
|
||||
return descriptions;
|
||||
}
|
||||
public static string GetEnumDescription1(Enum value)
|
||||
{
|
||||
var field = value.GetType().GetField(value.ToString());
|
||||
var attribute = field.GetCustomAttributes(typeof(DescriptionAttribute), false)
|
||||
.FirstOrDefault() as DescriptionAttribute;
|
||||
return attribute?.Description ?? value.ToString();
|
||||
}
|
||||
[Flags]
|
||||
public enum DeviceAttributeType
|
||||
{
|
||||
|
117
DH.Commons/Helper/SchemeHelper.cs
Normal file
117
DH.Commons/Helper/SchemeHelper.cs
Normal file
@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DH.Commons.Helper
|
||||
{
|
||||
public static class SchemeHelper
|
||||
{
|
||||
private const string SchemesKey = "Schemes";
|
||||
private const string CurrentSchemeKey = "CurrentScheme";
|
||||
private const char Separator = '|';
|
||||
|
||||
/// <summary>
|
||||
/// 初始化配置(首次运行时调用)
|
||||
/// </summary>
|
||||
public static void Initialize()
|
||||
{
|
||||
// 如果Schemes不存在,创建空键
|
||||
if (!SystemConfigHelper.KeyExists(SchemesKey))
|
||||
{
|
||||
SystemConfigHelper.SetValue(SchemesKey, "");
|
||||
}
|
||||
|
||||
// 如果CurrentScheme不存在,创建空键
|
||||
if (!SystemConfigHelper.KeyExists(CurrentSchemeKey))
|
||||
{
|
||||
SystemConfigHelper.SetValue(CurrentSchemeKey, "");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有方案(自动处理空值)
|
||||
/// </summary>
|
||||
public static List<string> GetAllSchemes()
|
||||
{
|
||||
var schemeString = SystemConfigHelper.GetValue(SchemesKey, "");
|
||||
return string.IsNullOrEmpty(schemeString)
|
||||
? new List<string>()
|
||||
: new List<string>(schemeString.Split(Separator));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加新方案(自动初始化处理)
|
||||
/// </summary>
|
||||
public static void AddScheme(string schemeName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(schemeName))
|
||||
throw new ArgumentException("方案名称无效");
|
||||
|
||||
var schemes = GetAllSchemes();
|
||||
|
||||
if (schemes.Contains(schemeName))
|
||||
throw new InvalidOperationException($"方案 {schemeName} 已存在");
|
||||
|
||||
schemes.Add(schemeName);
|
||||
SaveSchemes(schemes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置当前方案(空值安全处理)
|
||||
/// </summary>
|
||||
public static void SetCurrentScheme(string schemeName)
|
||||
{
|
||||
var schemes = GetAllSchemes();
|
||||
|
||||
if (!schemes.Contains(schemeName))
|
||||
throw new KeyNotFoundException($"方案 {schemeName} 不存在");
|
||||
|
||||
SystemConfigHelper.SetValue(CurrentSchemeKey, schemeName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前方案(默认值处理)
|
||||
/// </summary>
|
||||
public static string GetCurrentScheme()
|
||||
{
|
||||
var current = SystemConfigHelper.GetValue(CurrentSchemeKey, "");
|
||||
return !string.IsNullOrEmpty(current) ? current : "默认方案";
|
||||
}
|
||||
|
||||
private static void SaveSchemes(List<string> schemes)
|
||||
{
|
||||
var schemeString = schemes.Count > 0
|
||||
? string.Join(Separator.ToString(), schemes)
|
||||
: "";
|
||||
SystemConfigHelper.SetValue(SchemesKey, schemeString);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 删除指定方案(自动同步当前方案状态)
|
||||
/// </summary>
|
||||
/// <param name="schemeName">要删除的方案名称</param>
|
||||
/// <exception cref="ArgumentException">当方案名称为空时抛出</exception>
|
||||
/// <exception cref="KeyNotFoundException">当方案不存在时抛出</exception>
|
||||
public static void DeleteScheme(string schemeName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(schemeName))
|
||||
throw new ArgumentException("方案名称无效");
|
||||
|
||||
var schemes = GetAllSchemes();
|
||||
|
||||
if (!schemes.Contains(schemeName))
|
||||
throw new KeyNotFoundException($"方案 {schemeName} 不存在");
|
||||
|
||||
// 删除前检查是否是当前方案
|
||||
bool isCurrent = GetCurrentScheme() == schemeName;
|
||||
|
||||
// 执行删除操作
|
||||
schemes.Remove(schemeName);
|
||||
SaveSchemes(schemes);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
120
DH.Commons/Helper/SystemConfigHelper.cs
Normal file
120
DH.Commons/Helper/SystemConfigHelper.cs
Normal file
@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DH.Commons.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// 配置文件操作工具类(自动定位主程序配置)
|
||||
/// </summary>
|
||||
public static class SystemConfigHelper
|
||||
{
|
||||
private static Configuration _mainConfig;
|
||||
private static readonly object _lock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// 获取主程序配置对象
|
||||
/// </summary>
|
||||
private static Configuration MainConfiguration
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_mainConfig == null)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_mainConfig == null)
|
||||
{
|
||||
// 获取主程序路径
|
||||
string exePath = Assembly.GetEntryAssembly().Location;
|
||||
var configFile = exePath + ".config";
|
||||
|
||||
// 加载主程序配置
|
||||
var fileMap = new ExeConfigurationFileMap
|
||||
{
|
||||
ExeConfigFilename = configFile
|
||||
};
|
||||
_mainConfig = ConfigurationManager.OpenMappedExeConfiguration(
|
||||
fileMap,
|
||||
ConfigurationUserLevel.None
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _mainConfig;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查配置项是否存在
|
||||
/// </summary>
|
||||
public static bool KeyExists(string key)
|
||||
{
|
||||
return MainConfiguration.AppSettings.Settings[key] != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取配置项(带类型自动转换)
|
||||
/// </summary>
|
||||
public static T GetValue<T>(string key, T defaultValue = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var setting = MainConfiguration.AppSettings.Settings[key];
|
||||
if (setting == null) return defaultValue;
|
||||
|
||||
return (T)Convert.ChangeType(setting.Value, typeof(T));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入配置项(自动保存)
|
||||
/// </summary>
|
||||
public static void SetValue(string key, object value)
|
||||
{
|
||||
var settings = MainConfiguration.AppSettings.Settings;
|
||||
var stringValue = value?.ToString() ?? string.Empty;
|
||||
|
||||
if (settings[key] == null)
|
||||
{
|
||||
settings.Add(key, stringValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
settings[key].Value = stringValue;
|
||||
}
|
||||
|
||||
SaveChanges();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除指定配置项
|
||||
/// </summary>
|
||||
public static void RemoveKey(string key)
|
||||
{
|
||||
if (KeyExists(key))
|
||||
{
|
||||
MainConfiguration.AppSettings.Settings.Remove(key);
|
||||
SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存配置修改
|
||||
/// </summary>
|
||||
private static void SaveChanges()
|
||||
{
|
||||
MainConfiguration.Save(ConfigurationSaveMode.Modified);
|
||||
ConfigurationManager.RefreshSection("appSettings");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
29
DH.Commons/Models/SystemModel.cs
Normal file
29
DH.Commons/Models/SystemModel.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using DH.Commons.Base;
|
||||
|
||||
namespace DH.Commons.Models
|
||||
{
|
||||
public static class SystemModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前方案
|
||||
/// </summary>
|
||||
public static string CurrentScheme=string.Empty;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 配置集合
|
||||
/// </summary>
|
||||
public static class ConfigModel
|
||||
{
|
||||
public static List<CameraBase> CameraBaseList = new List<CameraBase>();
|
||||
public static List<PLCBase> PLCBaseList = new List<PLCBase>();
|
||||
public static List<DetectionConfig> DetectionList = new List<DetectionConfig>();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user