using HalconDotNet; using LB_VisionControls; using LB_VisionProcesses.Alogrithms; using LB_VisionProcesses.Alogrithms.Halcon; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using SharpCompress.Common; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace LB_VisionProcesses.Processes { public class RecordTool : BaseProcess { public RecordTool() { strProcessClass = "LB_VisionProcesses.Processes.RecordTool"; strProcessName = "创建绘制工具"; } ConcurrentBag dicRecords = new ConcurrentBag(); public override bool Run() { #region 初始化变量 DateTime StartTime = DateTime.Now; InitRunParams(); HOperatorSet.GenEmptyObj(out HObject EmptyObj); OutputImage = EmptyObj; #endregion try { //if (InputImage == null) //{ // Msg = "输入图片为空"; // Result = false; // return Result; //} //if (!(InputImage is HObject)) //{ // Msg = "输入图片格式不为HObject"; // Result = false; // return Result; //} #region 裁剪区域 //object DomainImage = null; //if (!ReduceDomainImage(InputImage, ref DomainImage)) //{ // Msg = "裁剪区域失败"; // Result = false; // return Result; //} #endregion #region 算子逻辑 Record = new MsgRecord(); foreach (var recordObj in dicRecords) { if (recordObj is UserRecord record) { string Msg = ""; if (!record.MsgMap.Contains('{') || !record.MsgMap.Contains('}')) Msg = record.MsgMap; else { Msg = record.MsgMap; // 使用正则表达式匹配所有 {key} 格式的内容 Msg = Regex.Replace(Msg, @"\{([^}]+)\}", match => { string key = match.Groups[1].Value; // 获取花括号内的内容 if (Params.Inputs.ContainsKey(key)) { object value = Params.Inputs[key]; if (value == null) return ""; // 尝试解析为数值类型 if (double.TryParse(value.ToString(), out double num)) return num.ToString("F4"); return value?.ToString(); } return match.Value; // 如果找不到键,保留原文本 }); } bool Result = false; if (!record.ResultMap.StartsWith("{") || !record.ResultMap.EndsWith("}")) Result = Convert.ToBoolean(record.ResultMap); else { string Map = record.ResultMap; Map = Map.Replace("{", ""); Map = Map.Replace("}", ""); if (Params.Inputs.ContainsKey(Map) && Params.Inputs[Map] is bool res) Result = res; } ROI Obj = new ROI(); if (record.ShapeMap.StartsWith("{") && record.ShapeMap.EndsWith("}")) { string Map = record.ShapeMap; Map = Map.Replace("{", ""); Map = Map.Replace("}", ""); if (Params.Inputs.ContainsKey(Map) && Params.Inputs[Map] is ROI roi) Obj = roi; } double X = 0; if (!record.XMap.StartsWith("{") || !record.XMap.EndsWith("}")) X = Convert.ToDouble(record.XMap); else { string Map = record.ResultMap; Map = Map.Replace("{", ""); Map = Map.Replace("}", ""); if (Params.Inputs.ContainsKey(Map) && Params.Inputs[Map] is double val) X = val; } double Y = 0; if (!record.YMap.StartsWith("{") || !record.YMap.EndsWith("}")) Y = Convert.ToDouble(record.YMap); else { string Map = record.ResultMap; Map = Map.Replace("{", ""); Map = Map.Replace("}", ""); if (Params.Inputs.ContainsKey(Map) && Params.Inputs[Map] is double val) Y = val; } HPoint Pose = new HPoint(X, Y); ((MsgRecord)Record).AddXld(Msg, Pose.Row, Pose.Column, Obj.GetXld(), Result); } } #endregion #region 生成OutputImage给后续处理 try { //OutputImage = hoDomainImage; } catch (Exception ex) { Msg = "生成OutputImage失败,原因是:" + ex.ToString(); Result = false; return Result; } #endregion Msg = "运行成功"; Result = true; return Result; } catch (Exception ex) { Msg = "运行失败,原因是:" + ex.ToString().TrimEnd(); OutputImage = null; Result = false; return Result; } finally { RunTime = (DateTime.Now - StartTime).TotalMilliseconds; } } public ConcurrentDictionary GetRecords() { ConcurrentDictionary dicRecords = new ConcurrentDictionary(); int index = 1; foreach (var userRecord in this.dicRecords) { dicRecords.TryAdd(index, userRecord); index++; } return dicRecords; } public override bool Load(string fullPath) { try { // 获取不带文件名的目录路径 string directoryPath = Path.GetDirectoryName(fullPath); strProcessName = Path.GetFileNameWithoutExtension(fullPath); // 修正真实路径,工具其路径为一个文件夹,而不是一个文件 string FilePath = directoryPath + "\\" + strProcessName; fullPath = FilePath + "\\" + strProcessName + ".json"; if (!File.Exists(fullPath)) { Debug.WriteLine("文件不存在创建空文件"); Save(directoryPath); return true; } string strJson = string.Empty; using (StreamReader streamReader = new StreamReader(fullPath, Encoding.UTF8)) { strJson = streamReader.ReadToEnd(); streamReader.Close(); } Params = JsonConvert.DeserializeObject(strJson); if (Params == null) return false; Params.FixDeserializedData(); return LoadRecords(directoryPath + $"\\{strProcessName}\\{strProcessName}.rds"); } catch { return false; } } /// /// 加载绘制流(带.json,实际路径) /// /// 完整路径带.json /// public bool LoadRecords(string fullPath) { try { // 获取不带文件名的目录路径 string directoryPath = Path.GetDirectoryName(fullPath); if (!File.Exists(fullPath)) { Debug.WriteLine("文件不存在创建空文件"); SaveRecords(directoryPath); return true; } string strJson = string.Empty; using (StreamReader streamReader = new StreamReader(fullPath, Encoding.UTF8)) { strJson = streamReader.ReadToEnd(); streamReader.Close(); } ConcurrentDictionary dicRecords = JsonConvert.DeserializeObject>(strJson); if (dicRecords == null) return false; this.dicRecords.Clear(); for (int i = 1; i <= dicRecords.Count; i++) { if (dicRecords.ContainsKey(i)) this.dicRecords.Add(dicRecords[i]); } return true; } catch { return false; } } public override bool Save(string filePath) { try { if (string.IsNullOrEmpty(filePath) || filePath.Trim() == "") { Debug.WriteLine("文件路径不完整"); return false; } // 修正真实路径,工具其路径为一个文件夹,而不是一个文件 filePath += ("\\" + strProcessName); string strJson = string.Empty; var settings = new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.Indented, // 自定义缩进(4空格) ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() } }; strJson = JsonConvert.SerializeObject(Params, settings); //判断文件夹是否存在,防呆输入为文件名称 if (!Directory.Exists(filePath)) { try { Directory.CreateDirectory(filePath); } catch (Exception) { } } // filePath 已经含了Name File.WriteAllText(filePath + $"\\{strProcessName}.json", strJson, Encoding.UTF8); return SaveRecords(filePath); } catch { return false; } } /// /// 保存绘制流(不带.json,实际路径) /// /// /// public bool SaveRecords(string filePath) { try { if (string.IsNullOrEmpty(filePath) || filePath.Trim() == "") { Debug.WriteLine("文件路径不完整"); return false; } var dicRecords = GetRecords(); string strJson = string.Empty; var settings = new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.Indented, // 自定义缩进(4空格) ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() } }; strJson = JsonConvert.SerializeObject(dicRecords, settings); //判断文件夹是否存在,防呆输入为文件名称 if (!Directory.Exists(filePath)) { try { Directory.CreateDirectory(filePath); } catch (Exception) { } } // filePath 已经含了Name File.WriteAllText(filePath + $"\\{strProcessName}.rds", strJson, Encoding.UTF8); return true; } catch { return false; } } public bool ClearRecord() { try { dicRecords.Clear(); return true; } catch { return false; } } public bool AddRecord(UserRecord record) { try { dicRecords.Add(record); return true; } catch { return false; } } public bool RemoveLastRecord() { try { return dicRecords.TryTake(out _); } catch { return false; } } /// /// 获取脚本输入 /// /// public Dictionary GetInputs() { try { Dictionary dicInputs = new Dictionary(); for (int i = 0; i <= Params.Inputs.Count - 1; i++) { bool isFindKey = Params.Inputs.GetKey(i, out string key); //忽略不需要的参数 if (!isFindKey || key == "Scrip" || key == "OtherDllPaths") continue; dicInputs.TryAdd(key, Params.Inputs[i]); } return dicInputs; } catch { return new Dictionary(); } } /// /// 设置脚本输入 /// /// /// public bool SetInputs(Dictionary dicInputs) { try { //设置输入前将原先其他输入清除 if (!ClearInputs()) return false; foreach (var kvp in dicInputs) { string key = kvp.Key; //忽略不需要的参数 if (key == "Scrip" || key == "OtherDllPaths") continue; Params.Inputs.Add(key, kvp.Value); } return true; } catch { return false; } } public bool ClearInputs() { try { //设置输入前将原先其他输入清除 for (int i = 0; i <= Params.Inputs.Count - 1; i++) { bool isFindKey = Params.Inputs.GetKey(i, out string key); //忽略不需要的参数 if (!isFindKey || key == "Scrip" || key == "OtherDllPaths") continue; Params.Inputs.Remove(i); } return true; } catch { return false; } } } [Serializable] public class UserRecord { [JsonConstructor] public UserRecord() { } //public UserRecord(HPoint Pose, string Msg, bool Result = true) //{ // this.Pose = Pose; // this.Msg = Msg; // this.Result = Result; //} //public UserRecord(HPoint Pose, ROI Obj, bool Result = true, string Msg = "") //{ // this.Pose = Pose; // this.Obj = Obj; // this.Result = Result; // this.Msg = Msg; //} [JsonProperty] public string MsgMap = ""; [JsonProperty] public string ShapeMap = ""; [JsonProperty] public string ResultMap = "True"; [JsonProperty] public string XMap = "0"; [JsonProperty] public string YMap = "0"; //public bool Result = false; //public string Msg = ""; //public HPoint Pose = new HPoint(); //public ROI Obj = new ROI(); } public class OrderedConcurrentDictionary { private readonly ConcurrentDictionary _dictionary = new(); private readonly ConcurrentQueue _keyQueue = new(); private int _currentMaxKey = 0; private readonly object _reorderLock = new(); public int Count { get { return _dictionary.Count; } } public bool Add(object value) { lock (_reorderLock) { int newKey = GetNextKey(); if (_dictionary.TryAdd(newKey, value)) { _keyQueue.Enqueue(newKey); return true; } } return false; } public bool Remove(int key) { if (_dictionary.TryRemove(key, out _)) { lock (_reorderLock) { // 重新排序 ReorderDictionary(); } return true; } return false; } public bool Clear() { try { while (Count > 0) Remove(Count - 1); return true; } catch { return false; } } public bool TryGetValue(int key, out object value) { return _dictionary.TryGetValue(key, out value); } private int GetNextKey() { return Interlocked.Increment(ref _currentMaxKey); } private void ReorderDictionary() { // 获取当前所有值 var values = _dictionary.Values.ToArray(); // 清空字典和队列 _dictionary.Clear(); while (_keyQueue.TryDequeue(out _)) { } // 重新添加并更新键 for (int i = 0; i < values.Length; i++) { int newKey = i + 1; _dictionary.TryAdd(newKey, values[i]); _keyQueue.Enqueue(newKey); } // 更新最大键值 _currentMaxKey = values.Length; } } }