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<UserRecord> dicRecords = new ConcurrentBag<UserRecord>();
|
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<int, UserRecord> GetRecords()
|
{
|
ConcurrentDictionary<int, UserRecord> dicRecords = new ConcurrentDictionary<int, UserRecord>();
|
|
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<ProcessParams>(strJson);
|
if (Params == null)
|
return false;
|
|
Params.FixDeserializedData();
|
|
return LoadRecords(directoryPath + $"\\{strProcessName}\\{strProcessName}.rds");
|
}
|
catch { return false; }
|
}
|
|
/// <summary>
|
/// 加载绘制流(带.json,实际路径)
|
/// </summary>
|
/// <param name="fullPath">完整路径带.json</param>
|
/// <returns></returns>
|
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<int, UserRecord> dicRecords = JsonConvert.DeserializeObject<ConcurrentDictionary<int, UserRecord>>(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; }
|
}
|
|
/// <summary>
|
/// 保存绘制流(不带.json,实际路径)
|
/// </summary>
|
/// <param name="filePath"></param>
|
/// <returns></returns>
|
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; }
|
}
|
|
/// <summary>
|
/// 获取脚本输入
|
/// </summary>
|
/// <returns></returns>
|
public Dictionary<string, object> GetInputs()
|
{
|
try
|
{
|
Dictionary<string, object> dicInputs = new Dictionary<string, object>();
|
|
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<string, object>(); }
|
}
|
|
/// <summary>
|
/// 设置脚本输入
|
/// </summary>
|
/// <param name="dicInputs"></param>
|
/// <returns></returns>
|
public bool SetInputs(Dictionary<string, object> 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<int, object> _dictionary = new();
|
private readonly ConcurrentQueue<int> _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;
|
}
|
}
|
}
|