using System; using System.Collections.Generic; using System.Linq; using System.Threading; using HalconDotNet; using TeamAAS.FlowEditor.Models; using TeamAAS.FlowEditor.Plugins; using Plugins.Halcon.Models; namespace Plugins.Halcon { // ───────────────────────────────────────────────────────────────────── // HALCON 几何测量分类算子(从主程序集迁入分类 DLL)。 // 显示名/类型全名保持不变 —— 工具箱、流程文件、公式绑定全部兼容。 // ───────────────────────────────────────────────────────────────────── /// H区域特征:面积、重心、区域数量。 [Serializable] [Plugin("H区域特征", PluginCategory.Halocn模块, typeof(HalconAreaCenterModel), "Ruler", NodeShape = NodeCategory.Normal, IsSubFlowNode = true, VisionCategory = VisionPlugin.几何测量, Description = "区域特征:面积、重心、数量(区域集时给出总面积与首个区域重心)")] public class HalconAreaCenterPlugin : BasePlugin { public override List DeclareOutputs() => new List { new OutputField("数量", typeof(int)), new OutputField("总面积", typeof(double)), new OutputField("重心行", typeof(double)), new OutputField("重心列", typeof(double)), 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("未获取到输入区域(请绑定上游「区域」输出)"); HalconRuntime.AreaCenter(region, out double[] areas, out double[] rows, out double[] cols); int count = areas.Length; double total = areas.Length > 0 ? areas.Sum() : 0d; double row = rows.Length > 0 ? rows[0] : 0d; double col = cols.Length > 0 ? cols[0] : 0d; res["数量"] = count; res["总面积"] = total; res["重心行"] = row; res["重心列"] = col; res["结果"] = true; Log(2, $"区域特征:数量={count},总面积={total:F1},首区域重心=({row:F1},{col:F1})"); return NodeRunStatus.Success; } catch (Exception ex) { return Fail(ex.Message); } } } /// H外接矩形:区域的最小外接正矩形边界与宽高。 [Serializable] [Plugin("H外接矩形", PluginCategory.Halocn模块, typeof(HalconRectangleModel), "CropFree", NodeShape = NodeCategory.Normal, IsSubFlowNode = true, VisionCategory = VisionPlugin.几何测量, Description = "最小外接正矩形:行1/列1/行2/列2 与 宽/高(取第一个区域)")] public class HalconRectanglePlugin : BasePlugin { public override List DeclareOutputs() => new List { new OutputField("行1", typeof(double)), new OutputField("列1", typeof(double)), new OutputField("行2", typeof(double)), new OutputField("列2", typeof(double)), new OutputField("宽", typeof(double)), new OutputField("高", typeof(double)), 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("未获取到输入区域(请绑定上游「区域」输出)"); HalconRuntime.SmallestRectangle1(region, out double r1, out double c1, out double r2, out double c2); res["行1"] = r1; res["列1"] = c1; res["行2"] = r2; res["列2"] = c2; res["宽"] = c2 - c1; res["高"] = r2 - r1; res["结果"] = true; Log(2, $"外接矩形:({r1:F1},{c1:F1})-({r2:F1},{c2:F1}),宽={c2 - c1:F1},高={r2 - r1:F1}"); return NodeRunStatus.Success; } catch (Exception ex) { return Fail(ex.Message); } } } } namespace Plugins.Halcon.Models { using PropertyGridLib.Attributes; using PropertyGridLib.Controls; using System.ComponentModel; using TeamAAS.FlowEditor.Plugins; using TeamAAS.FlowEngine.FormulaData; /// 区域特征:面积、重心、区域数量。 [Serializable] public class HalconAreaCenterModel : HalconOperatorModelBase { [Category("I.输入")] [DisplayName("1.输入区域")] [Description("上游区域(单个或区域集;区域集时给出总面积与首个区域重心)")] [FormulaEditor(typeof(PluginDataProvider))] public FormulaBound RegionSource { get; set; } = new FormulaBound(); } /// 最小外接矩形:区域的外接正矩形边界与宽高。 [Serializable] public class HalconRectangleModel : HalconOperatorModelBase { [Category("I.输入")] [DisplayName("1.输入区域")] [Description("上游区域(取第一个区域计算外接矩形)")] [FormulaEditor(typeof(PluginDataProvider))] public FormulaBound RegionSource { get; set; } = new FormulaBound(); } }