using System; using System.Collections.Generic; using System.Threading; using HalconDotNet; using TeamAAS.FlowEditor.Models; using TeamAAS.FlowEditor.Plugins; using Plugins.Halcon.Models; using Plugins.Halcon; namespace Plugins.Halcon { // ───────────────────────────────────────────────────────────────────── // HALCON 图像处理分类算子(从主程序集迁入分类 DLL)。 // 显示名/类型全名保持不变 —— 工具箱、流程文件、公式绑定全部兼容。 // ───────────────────────────────────────────────────────────────────── /// H阈值分割:提取灰度落在 [最小,最大] 区间的像素为区域。 [Serializable] [Plugin("H阈值分割", PluginCategory.Halocn模块, typeof(HalconThresholdModel), "FilterOutline", NodeShape = NodeCategory.Normal, IsSubFlowNode = true, VisionCategory = VisionPlugin.图像处理, Description = "灰度阈值分割:把灰度∈[最小,最大]的像素提取为区域")] public class HalconThresholdPlugin : BasePlugin { public override List DeclareOutputs() => new List { new OutputField("区域", typeof(object)), new OutputField("结果", typeof(bool)), }; public override NodeRunStatus PluginRun(CancellationToken token, out Dictionary results) { var res = new Dictionary(); results = res; NodeRunStatus Fail(string m) { res["Error"] = m; res["结果"] = false; Log(1, $"阈值分割失败: {m}", TeamAAS.LogLevel.Error); return NodeRunStatus.Failed; } bool owned = false; HObject image = null; try { var src = GetResolve(Model.ImageSource); if (src == null) return Fail("未获取到输入图像(请绑定「输入图像」,例如 &{输入.图像})"); owned = !(src is HObject); image = HalconRuntime.ToHObject(src); Log(3, $"阈值分割:灰度区间[{Model.MinGray}, {Model.MaxGray}]"); var region = HalconRuntime.Threshold(image, Model.MinGray, Model.MaxGray); res["区域"] = region; res["结果"] = true; HalconEditorPreview.Show(Model, src, region, "red"); // 图层发布 + 编辑器预览:底图 + 阈值区域叠加 Log(2, $"阈值分割完成,区域对象数={HalconRuntime.CountObj(region)}"); return NodeRunStatus.Success; } catch (Exception ex) { return Fail(ex.Message); } finally { if (owned) HalconRuntime.Dispose(image); } } } /// H连通域:把一个区域拆成互不相连的多个独立区域。 [Serializable] [Plugin("H连通域", PluginCategory.Halocn模块, typeof(HalconConnectionModel), "VectorSquare", NodeShape = NodeCategory.Normal, IsSubFlowNode = true, VisionCategory = VisionPlugin.图像处理, Description = "连通域拆分:把一个区域拆成多个独立区域,输出区域集与数量")] public class HalconConnectionPlugin : BasePlugin { public override List DeclareOutputs() => new List { new OutputField("区域集", typeof(object)), new OutputField("数量", typeof(int)), new OutputField("结果", typeof(bool)), }; public override NodeRunStatus PluginRun(CancellationToken token, out Dictionary results) { var res = new Dictionary(); results = res; NodeRunStatus Fail(string m) { res["Error"] = m; res["结果"] = false; Log(1, $"连通域失败: {m}", TeamAAS.LogLevel.Error); return NodeRunStatus.Failed; } try { var src = GetResolve(Model.RegionSource); if (!(src is HObject region)) return Fail("未获取到输入区域(请绑定上游「区域」输出)"); var connected = HalconRuntime.Connection(region); int n = HalconRuntime.CountObj(connected); res["区域集"] = connected; res["数量"] = n; res["结果"] = true; HalconEditorPreview.Show(Model, null, connected, "yellow"); // 只更新叠加区域,保留底图 Log(2, $"连通域拆分完成,得到 {n} 个独立区域"); return NodeRunStatus.Success; } catch (Exception ex) { return Fail(ex.Message); } } } /// H图像预处理:滤波 / 灰度线性变换 / 转灰度。 [Serializable] [Plugin("H图像预处理", PluginCategory.Halocn模块, typeof(HalconPreprocessModel), "Blur", NodeShape = NodeCategory.Normal, IsSubFlowNode = true, VisionCategory = VisionPlugin.图像处理, Description = "图像预处理:均值/中值/高斯滤波、灰度线性变换、转灰度")] public class HalconPreprocessPlugin : BasePlugin { public override List DeclareOutputs() => new List { new OutputField("图像", typeof(object)), new OutputField("结果", typeof(bool)), }; public override NodeRunStatus PluginRun(CancellationToken token, out Dictionary results) { var res = new Dictionary(); results = res; NodeRunStatus Fail(string m) { res["Error"] = m; res["结果"] = false; Log(1, $"图像预处理失败: {m}", TeamAAS.LogLevel.Error); return NodeRunStatus.Failed; } bool owned = false; HObject image = null; try { var src = GetResolve(Model.ImageSource); if (src == null) return Fail("未获取到输入图像(请绑定「输入图像」)"); owned = !(src is HObject); image = HalconRuntime.ToHObject(src); HObject outImg; switch (Model.ProcessType) { case HalconPreprocessType.均值滤波: outImg = HalconRuntime.MeanImage(image, Model.Param1, Model.Param2 > 0 ? Model.Param2 : Model.Param1); break; case HalconPreprocessType.中值滤波: outImg = HalconRuntime.MedianImage(image, "circle", Model.Param1, "mirrored"); break; case HalconPreprocessType.高斯滤波: outImg = HalconRuntime.GaussFilter(image, Model.Param1); break; case HalconPreprocessType.灰度线性变换: outImg = HalconRuntime.ScaleImage(image, Model.Param1, Model.Param2); break; case HalconPreprocessType.转灰度: outImg = HalconRuntime.RgbToGray(image); break; default: return Fail($"未知处理方式:{Model.ProcessType}"); } res["图像"] = outImg; res["结果"] = true; HalconEditorPreview.Show(Model, outImg, null); // 图层发布:处理后的图像作底图 Log(2, $"图像预处理完成:{Model.ProcessType}"); return NodeRunStatus.Success; } catch (Exception ex) { return Fail(ex.Message); } finally { if (owned) HalconRuntime.Dispose(image); } } } /// H形态学:对区域做膨胀/腐蚀/开/闭运算。 [Serializable] [Plugin("H形态学", PluginCategory.Halocn模块, typeof(HalconMorphologyModel), "ArrowExpandAll", NodeShape = NodeCategory.Normal, IsSubFlowNode = true, VisionCategory = VisionPlugin.图像处理, Description = "形态学:膨胀/腐蚀/开运算/闭运算(圆形结构元)")] public class HalconMorphologyPlugin : BasePlugin { public override List DeclareOutputs() => new List { new OutputField("区域", typeof(object)), new OutputField("结果", typeof(bool)), }; public override NodeRunStatus PluginRun(CancellationToken token, out Dictionary results) { var res = new Dictionary(); results = res; NodeRunStatus Fail(string m) { res["Error"] = m; res["结果"] = false; Log(1, $"形态学失败: {m}", TeamAAS.LogLevel.Error); return NodeRunStatus.Failed; } try { var src = GetResolve(Model.RegionSource); if (!(src is HObject region)) return Fail("未获取到输入区域(请绑定上游「区域」输出)"); HObject outRegion; switch (Model.Operation) { case HalconMorphOperation.膨胀: outRegion = HalconRuntime.DilationCircle(region, Model.Radius); break; case HalconMorphOperation.腐蚀: outRegion = HalconRuntime.ErosionCircle(region, Model.Radius); break; case HalconMorphOperation.开运算: outRegion = HalconRuntime.OpeningCircle(region, Model.Radius); break; case HalconMorphOperation.闭运算: outRegion = HalconRuntime.ClosingCircle(region, Model.Radius); break; default: return Fail($"未知形态学操作:{Model.Operation}"); } res["区域"] = outRegion; res["结果"] = true; HalconEditorPreview.Show(Model, null, outRegion, "orange"); // 只更新叠加区域,保留底图 Log(2, $"形态学完成:{Model.Operation},半径={Model.Radius}"); return NodeRunStatus.Success; } catch (Exception ex) { return Fail(ex.Message); } } } }