1437 lines
42 KiB
C#
1437 lines
42 KiB
C#
using OpenCvSharp;
|
||
using System.ComponentModel;
|
||
using System.Drawing;
|
||
using static OpenCvSharp.AgastFeatureDetector;
|
||
using System.Text.RegularExpressions;
|
||
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.Base
|
||
{
|
||
|
||
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
|
||
{
|
||
#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||
public string LabelBGR { get; set; }//识别到对象的标签BGR
|
||
|
||
|
||
|
||
public int LabelNo { get; set; } // 识别到对象的标签索引
|
||
|
||
#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||
public string LabelName { get; set; }//识别到对象的标签名称
|
||
|
||
|
||
public double Score { get; set; }//识别目标结果的可能性、得分
|
||
|
||
#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||
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;
|
||
#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||
public string ResultMessage;
|
||
|
||
#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||
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;
|
||
#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||
#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||
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
|
||
{
|
||
#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||
public string Pid { get; set; }
|
||
|
||
|
||
#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||
public string TempPid { get; set; }
|
||
|
||
|
||
/// <summary>
|
||
/// 检测工位名称
|
||
/// </summary>
|
||
#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||
public string DetectName { get; set; }
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 深度学习 检测结果
|
||
/// </summary>
|
||
public List<DetectionResultDetail> DetectDetails = new List<DetectionResultDetail>();
|
||
public List<IShapeElement> DetectionResultShapes = new List<IShapeElement>();
|
||
|
||
|
||
/// <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)
|
||
{
|
||
#pragma warning disable CS8603 // 可能返回 null 引用。
|
||
if (input == null) return null;
|
||
#pragma warning restore CS8603 // 可能返回 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 : NotifyProperty
|
||
{
|
||
|
||
private string _cameraSourceId = "";
|
||
[Category("关联相机")]
|
||
[DisplayName("相机源ID")]
|
||
[Description("关联相机的唯一标识符")]
|
||
//[TypeConverter(typeof(CollectionCountConvert))]
|
||
public string CameraSourceId
|
||
{
|
||
get { return _cameraSourceId; }
|
||
set
|
||
{
|
||
if (_cameraSourceId == value) return;
|
||
_cameraSourceId = value;
|
||
OnPropertyChanged(nameof(CameraSourceId));
|
||
}
|
||
}
|
||
|
||
public RelatedCamera()
|
||
{
|
||
}
|
||
|
||
// 可选:添加带 Selected 的构造函数
|
||
public RelatedCamera(string cameraSourceId)
|
||
{
|
||
CameraSourceId = cameraSourceId;
|
||
|
||
}
|
||
}
|
||
public class CustomizedPoint : INotifyPropertyChanged, IComparable<CustomizedPoint>
|
||
{
|
||
private double x = 0;
|
||
[Category("坐标设置")]
|
||
[Description("X坐标")]
|
||
public double X
|
||
{
|
||
get => x;
|
||
set
|
||
{
|
||
if (value != x)
|
||
{
|
||
x = value;
|
||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("X"));
|
||
}
|
||
}
|
||
}
|
||
|
||
private double y = 0;
|
||
[Category("坐标设置")]
|
||
[Description("Y坐标")]
|
||
public double Y
|
||
{
|
||
get => y;
|
||
set
|
||
{
|
||
if (value != y)
|
||
{
|
||
y = value;
|
||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Y"));
|
||
}
|
||
}
|
||
}
|
||
|
||
public CustomizedPoint() { }
|
||
|
||
public CustomizedPoint(double x, double y)
|
||
{
|
||
X = x;
|
||
Y = y;
|
||
}
|
||
|
||
//public CustomizedPoint(Point p)
|
||
//{
|
||
// X = p.X;
|
||
// Y = p.Y;
|
||
//}
|
||
|
||
public CustomizedPoint(PointF p)
|
||
{
|
||
X = p.X;
|
||
Y = p.Y;
|
||
}
|
||
|
||
public CustomizedPoint(CustomizedPoint p)
|
||
{
|
||
X = p.X;
|
||
Y = p.Y;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据PLC的读取数值获取点位坐标
|
||
/// </summary>
|
||
/// <param name="plcValues">0:X低位 1:X高位 2:Y低位 3:Y高位</param>
|
||
//public CustomizedPoint(List<int> plcValues)
|
||
//{
|
||
// if (plcValues == null || plcValues.Count != 4)
|
||
// return;
|
||
|
||
// var list = plcValues.ParseUnsignShortListToInt();
|
||
|
||
// X = list[0];
|
||
// Y = list[1];
|
||
//}
|
||
|
||
public event PropertyChangedEventHandler PropertyChanged;
|
||
|
||
public static List<CustomizedPoint> GetPoints(List<double> Xs, List<double> Ys)
|
||
{
|
||
List<CustomizedPoint> points = new List<CustomizedPoint>();
|
||
for (int i = 0; i < Xs.Count && i < Ys.Count; i++)
|
||
{
|
||
points.Add(new CustomizedPoint(Xs[i], Ys[i]));
|
||
}
|
||
|
||
return points;
|
||
}
|
||
|
||
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));
|
||
}
|
||
|
||
public override string ToString()
|
||
{
|
||
return GetDisplayText();
|
||
}
|
||
|
||
public virtual string GetDisplayText()
|
||
{
|
||
return string.Format("X:{0};Y:{1}", X, Y);
|
||
}
|
||
|
||
public virtual string GetCSVHead()
|
||
{
|
||
return "X,Y";
|
||
}
|
||
|
||
public virtual string GetCSVData()
|
||
{
|
||
return X.ToString("f3") + ";" + Y.ToString("f3");
|
||
}
|
||
|
||
//public static double GetCustomizedPointDistance(CustomizedPoint startPoint, CustomizedPoint endPoint)
|
||
//{
|
||
// return Math.Sqrt(Math.Pow(endPoint.X - startPoint.X, 2) + Math.Pow(endPoint.Y - startPoint.Y, 2));
|
||
//}
|
||
|
||
public CustomizedPoint OffsetClone(CustomizedPoint point)
|
||
{
|
||
return new CustomizedPoint(X + point.X, Y + point.Y);
|
||
}
|
||
|
||
public void Offset(CustomizedPoint point)
|
||
{
|
||
X += point.X;
|
||
Y += point.Y;
|
||
}
|
||
|
||
public int CompareTo(CustomizedPoint other)
|
||
{
|
||
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();
|
||
}
|
||
|
||
public static CustomizedPoint operator -(CustomizedPoint p1, CustomizedPoint p2)
|
||
{
|
||
return new CustomizedPoint(p1.X - p2.X, p1.Y - p2.Y);
|
||
}
|
||
|
||
public static CustomizedPoint operator +(CustomizedPoint p1, CustomizedPoint p2)
|
||
{
|
||
return new CustomizedPoint(p1.X + p2.X, p1.Y + p2.Y);
|
||
}
|
||
}
|
||
// 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 Value { get; set; }
|
||
|
||
|
||
|
||
// }
|
||
public class DetectionConfig : NotifyProperty
|
||
{
|
||
#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 => _name;
|
||
set
|
||
{
|
||
if (_name == value) return;
|
||
_name = value;
|
||
OnPropertyChanged(nameof(Name));
|
||
}
|
||
}
|
||
|
||
[Category("关联相机集合")]
|
||
[DisplayName("关联相机集合")]
|
||
[Description("关联相机描述")]
|
||
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 => _isEnableGPU;
|
||
set
|
||
{
|
||
if (_isEnableGPU == value) return;
|
||
_isEnableGPU = value;
|
||
OnPropertyChanged(nameof(IsEnableGPU));
|
||
}
|
||
}
|
||
|
||
[Category("启用配置")]
|
||
[DisplayName("是否混料模型")]
|
||
[Description("是否混料模型")]
|
||
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 => _isEnabled;
|
||
set
|
||
{
|
||
if (_isEnabled == value) return;
|
||
_isEnabled = value;
|
||
OnPropertyChanged(nameof(IsEnabled));
|
||
}
|
||
}
|
||
|
||
[Category("启用配置")]
|
||
[DisplayName("是否加入检测工位")]
|
||
[Description("是否加入检测工位")]
|
||
public bool IsAddStation
|
||
{
|
||
get => _isAddStation;
|
||
set
|
||
{
|
||
if (_isAddStation == value) return;
|
||
_isAddStation = value;
|
||
OnPropertyChanged(nameof(IsAddStation));
|
||
}
|
||
}
|
||
|
||
[Category("1.预处理(视觉算子)")]
|
||
[DisplayName("预处理-算法文件路径")]
|
||
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 AntList<PreTreatParam> PreTreatParams
|
||
{
|
||
get => _preTreatParams;
|
||
set
|
||
{
|
||
if (_preTreatParams == value) return;
|
||
_preTreatParams = value;
|
||
OnPropertyChanged(nameof(PreTreatParams));
|
||
}
|
||
}
|
||
|
||
[Category("1.预处理(视觉算子)")]
|
||
[DisplayName("预处理-输出参数列表")]
|
||
[Description("预处理-输出参数列表")]
|
||
public AntList<PreTreatParam> OUTPreTreatParams
|
||
{
|
||
get => _outPreTreatParams;
|
||
set
|
||
{
|
||
if (_outPreTreatParams == value) return;
|
||
_outPreTreatParams = value;
|
||
OnPropertyChanged(nameof(OUTPreTreatParams));
|
||
}
|
||
}
|
||
|
||
[Category("2.中检测(深度学习)")]
|
||
[DisplayName("中检测-模型类型")]
|
||
[Description("模型类型:ImageClassification-图片分类;ObjectDetection:目标检测;Segmentation-图像分割")]
|
||
public ModelType ModelType
|
||
{
|
||
get => _modelType;
|
||
set
|
||
{
|
||
if (_modelType == value) return;
|
||
_modelType = value;
|
||
OnPropertyChanged(nameof(ModelType));
|
||
}
|
||
}
|
||
|
||
[Category("2.中检测(深度学习)")]
|
||
[DisplayName("中检测-模型文件路径")]
|
||
[Description("中处理 深度学习模型文件路径")]
|
||
public string ModelPath
|
||
{
|
||
get => _modelPath;
|
||
set
|
||
{
|
||
if (_modelPath == value) return;
|
||
_modelPath = value;
|
||
OnPropertyChanged(nameof(ModelPath));
|
||
}
|
||
}
|
||
|
||
[Category("2.中检测(深度学习)")]
|
||
[DisplayName("中检测-模型宽度")]
|
||
[Description("中处理-模型宽度")]
|
||
public int ModelWidth
|
||
{
|
||
get => _modelWidth;
|
||
set
|
||
{
|
||
if (_modelWidth == value) return;
|
||
_modelWidth = value;
|
||
OnPropertyChanged(nameof(ModelWidth));
|
||
}
|
||
}
|
||
|
||
[Category("2.中检测(深度学习)")]
|
||
[DisplayName("中检测-模型高度")]
|
||
[Description("中处理-模型高度")]
|
||
public int ModelHeight
|
||
{
|
||
get => _modelHeight;
|
||
set
|
||
{
|
||
if (_modelHeight == value) return;
|
||
_modelHeight = value;
|
||
OnPropertyChanged(nameof(ModelHeight));
|
||
}
|
||
}
|
||
|
||
[Category("2.中检测(深度学习)")]
|
||
[DisplayName("中检测-模型节点名称")]
|
||
[Description("中处理-模型节点名称")]
|
||
public string ModeloutNodeName
|
||
{
|
||
get => _modeloutNodeName;
|
||
set
|
||
{
|
||
if (_modeloutNodeName == value) return;
|
||
_modeloutNodeName = value;
|
||
OnPropertyChanged(nameof(ModeloutNodeName));
|
||
}
|
||
}
|
||
|
||
[Category("2.中检测(深度学习)")]
|
||
[DisplayName("中检测-模型置信度")]
|
||
[Description("中处理-模型置信度")]
|
||
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 => _in_lable_path;
|
||
set
|
||
{
|
||
if (_in_lable_path == value) return;
|
||
_in_lable_path = value;
|
||
OnPropertyChanged(nameof(In_lable_path));
|
||
}
|
||
}
|
||
|
||
|
||
|
||
[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;
|
||
|
||
}
|
||
#endregion
|
||
}
|
||
|
||
//大改预处理类
|
||
/// <summary>
|
||
/// 预处理
|
||
/// </summary>
|
||
public class PreTreatParam : NotifyProperty
|
||
{
|
||
|
||
|
||
private bool _selected = false;
|
||
public bool Selected
|
||
{
|
||
get { return _selected; }
|
||
set
|
||
{
|
||
if (_selected == value) return;
|
||
_selected = value;
|
||
OnPropertyChanged(nameof(Selected));
|
||
}
|
||
}
|
||
private string _name;
|
||
public string Name
|
||
{
|
||
get { return _name; }
|
||
set
|
||
{
|
||
if (_name == value) return;
|
||
_name = value;
|
||
OnPropertyChanged(nameof(Name));
|
||
}
|
||
}
|
||
|
||
|
||
private string _value;
|
||
public string Value
|
||
{
|
||
get { return _value; }
|
||
set
|
||
{
|
||
if (_value == value) return;
|
||
_value = value;
|
||
OnPropertyChanged(nameof(Value));
|
||
}
|
||
}
|
||
|
||
private CellLink[] cellLinks;
|
||
[JsonIgnore]
|
||
public CellLink[] CellLinks
|
||
{
|
||
get { return cellLinks; }
|
||
set
|
||
{
|
||
if (cellLinks == value) return;
|
||
cellLinks = value;
|
||
OnPropertyChanged(nameof(CellLinks));
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|
||
|
||
public class DetectionLable : NotifyProperty
|
||
{
|
||
private bool _selected = false;
|
||
|
||
private string _labelId;
|
||
private string _labelName;
|
||
private double _maxScore;
|
||
private double _minScore;
|
||
private double _maxArea;
|
||
private double _minArea;
|
||
private ResultState _resultState = ResultState.ResultTBD;
|
||
|
||
|
||
|
||
|
||
public bool Selected
|
||
{
|
||
get { return _selected; }
|
||
set
|
||
{
|
||
if (_selected == value) return;
|
||
_selected = value;
|
||
OnPropertyChanged(nameof(Selected));
|
||
}
|
||
}
|
||
|
||
|
||
|
||
public string LabelId
|
||
{
|
||
get { return _labelId; }
|
||
set
|
||
{
|
||
if (_labelId == value) return;
|
||
_labelId = value;
|
||
OnPropertyChanged(nameof(LabelId));
|
||
}
|
||
}
|
||
|
||
public string LabelName
|
||
{
|
||
get { return _labelName; }
|
||
set
|
||
{
|
||
if (_labelName == value) return;
|
||
_labelName = value;
|
||
OnPropertyChanged(nameof(LabelName));
|
||
}
|
||
}
|
||
|
||
public double MaxScore
|
||
{
|
||
get { return _maxScore; }
|
||
set
|
||
{
|
||
if (_maxScore.Equals(value)) return;
|
||
_maxScore = value;
|
||
OnPropertyChanged(nameof(MaxScore));
|
||
}
|
||
}
|
||
|
||
public double MinScore
|
||
{
|
||
get { return _minScore; }
|
||
set
|
||
{
|
||
if (_minScore.Equals(value)) return;
|
||
_minScore = value;
|
||
OnPropertyChanged(nameof(MinScore));
|
||
}
|
||
}
|
||
|
||
public double MaxArea
|
||
{
|
||
get { return _maxArea; }
|
||
set
|
||
{
|
||
if (_maxArea.Equals(value)) return;
|
||
_maxArea = value;
|
||
OnPropertyChanged(nameof(MaxArea));
|
||
}
|
||
}
|
||
|
||
public double MinArea
|
||
{
|
||
get { return _minArea; }
|
||
set
|
||
{
|
||
if (_minArea.Equals(value)) return;
|
||
_minArea = value;
|
||
OnPropertyChanged(nameof(MinArea));
|
||
}
|
||
}
|
||
|
||
public ResultState ResultState
|
||
{
|
||
get { return _resultState; }
|
||
set
|
||
{
|
||
if (_resultState == value) return;
|
||
_resultState = value;
|
||
OnPropertyChanged(nameof(ResultState));
|
||
}
|
||
}
|
||
|
||
private CellLink[] cellLinks;
|
||
[JsonIgnore]
|
||
public CellLink[] CellLinks
|
||
{
|
||
get { return cellLinks; }
|
||
set
|
||
{
|
||
if (cellLinks == value) return;
|
||
cellLinks = value;
|
||
OnPropertyChanged(nameof(CellLinks));
|
||
}
|
||
}
|
||
}
|
||
|
||
public class SizeTreatParam : NotifyProperty
|
||
{
|
||
private bool _selected = false;
|
||
|
||
|
||
private bool _isEnable;
|
||
private string _preName;
|
||
private int _prePix;
|
||
|
||
private SizeEnum _preType;
|
||
private string _resultShow;
|
||
private string _outResultShow;
|
||
|
||
|
||
private string _prePath;
|
||
|
||
|
||
public bool Selected
|
||
{
|
||
get { return _selected; }
|
||
set
|
||
{
|
||
if (_selected == value) return;
|
||
_selected = value;
|
||
OnPropertyChanged(nameof(Selected));
|
||
}
|
||
}
|
||
|
||
public bool IsEnable
|
||
{
|
||
get { return _isEnable; }
|
||
set
|
||
{
|
||
if (_isEnable == value) return;
|
||
_isEnable = value;
|
||
OnPropertyChanged(nameof(IsEnable));
|
||
}
|
||
}
|
||
|
||
public string PreName
|
||
{
|
||
get { return _preName; }
|
||
set
|
||
{
|
||
if (_preName == value) return;
|
||
_preName = value;
|
||
OnPropertyChanged(nameof(PreName));
|
||
}
|
||
}
|
||
|
||
public SizeEnum PreType
|
||
{
|
||
get { return _preType; }
|
||
set
|
||
{
|
||
if (_preType == value) return;
|
||
_preType = value;
|
||
OnPropertyChanged(nameof(PreType));
|
||
}
|
||
}
|
||
|
||
public int PrePix
|
||
{
|
||
get { return _prePix; }
|
||
set
|
||
{
|
||
if (_prePix.Equals(value)) return;
|
||
_prePix = value;
|
||
OnPropertyChanged(nameof(PrePix));
|
||
}
|
||
}
|
||
|
||
public string ResultShow
|
||
{
|
||
get { return _resultShow; }
|
||
set
|
||
{
|
||
if (_resultShow == value) return;
|
||
_resultShow = value;
|
||
OnPropertyChanged(nameof(ResultShow));
|
||
}
|
||
|
||
}
|
||
|
||
public string OutResultShow
|
||
{
|
||
get { return _outResultShow; }
|
||
set
|
||
{
|
||
if (_outResultShow == value) return;
|
||
_outResultShow = value;
|
||
OnPropertyChanged(nameof(OutResultShow));
|
||
}
|
||
}
|
||
|
||
public string PrePath
|
||
{
|
||
get { return _prePath; }
|
||
set
|
||
{
|
||
if (_prePath.Equals(value)) return;
|
||
_prePath = value;
|
||
OnPropertyChanged(nameof(PrePath));
|
||
}
|
||
}
|
||
|
||
|
||
private CellLink[] cellLinks;
|
||
[JsonIgnore]
|
||
public CellLink[] CellLinks
|
||
{
|
||
get { return cellLinks; }
|
||
set
|
||
{
|
||
if (cellLinks == value) return;
|
||
cellLinks = value;
|
||
OnPropertyChanged(nameof(CellLinks));
|
||
}
|
||
}
|
||
}
|
||
/// <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))]
|
||
#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||
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; }
|
||
|
||
|
||
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,
|
||
}
|
||
}
|