HalconImageProcessingNodes.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading;
  4. using HalconDotNet;
  5. using TeamAAS.FlowEditor.Models;
  6. using TeamAAS.FlowEditor.Plugins;
  7. using Plugins.Halcon.Models;
  8. using Plugins.Halcon;
  9. namespace Plugins.Halcon
  10. {
  11. // ─────────────────────────────────────────────────────────────────────
  12. // HALCON 图像处理分类算子(从主程序集迁入分类 DLL)。
  13. // 显示名/类型全名保持不变 —— 工具箱、流程文件、公式绑定全部兼容。
  14. // ─────────────────────────────────────────────────────────────────────
  15. /// <summary>H阈值分割:提取灰度落在 [最小,最大] 区间的像素为区域。</summary>
  16. [Serializable]
  17. [Plugin("H阈值分割", PluginCategory.Halocn模块, typeof(HalconThresholdModel), "FilterOutline",
  18. NodeShape = NodeCategory.Normal, IsSubFlowNode = true, VisionCategory = VisionPlugin.图像处理,
  19. Description = "灰度阈值分割:把灰度∈[最小,最大]的像素提取为区域")]
  20. public class HalconThresholdPlugin : BasePlugin<HalconThresholdModel>
  21. {
  22. public override List<OutputField> DeclareOutputs() => new List<OutputField>
  23. {
  24. new OutputField("区域", typeof(object)),
  25. new OutputField("结果", typeof(bool)),
  26. };
  27. public override NodeRunStatus PluginRun(CancellationToken token, out Dictionary<string, object> results)
  28. {
  29. var res = new Dictionary<string, object>();
  30. results = res;
  31. NodeRunStatus Fail(string m) { res["Error"] = m; res["结果"] = false; Log(1, $"阈值分割失败: {m}", TeamAAS.LogLevel.Error); return NodeRunStatus.Failed; }
  32. bool owned = false;
  33. HObject image = null;
  34. try
  35. {
  36. var src = GetResolve(Model.ImageSource);
  37. if (src == null) return Fail("未获取到输入图像(请绑定「输入图像」,例如 &{输入.图像})");
  38. owned = !(src is HObject);
  39. image = HalconRuntime.ToHObject(src);
  40. Log(3, $"阈值分割:灰度区间[{Model.MinGray}, {Model.MaxGray}]");
  41. var region = HalconRuntime.Threshold(image, Model.MinGray, Model.MaxGray);
  42. res["区域"] = region;
  43. res["结果"] = true;
  44. HalconEditorPreview.Show(Model, src, region, "red"); // 图层发布 + 编辑器预览:底图 + 阈值区域叠加
  45. Log(2, $"阈值分割完成,区域对象数={HalconRuntime.CountObj(region)}");
  46. return NodeRunStatus.Success;
  47. }
  48. catch (Exception ex) { return Fail(ex.Message); }
  49. finally { if (owned) HalconRuntime.Dispose(image); }
  50. }
  51. }
  52. /// <summary>H连通域:把一个区域拆成互不相连的多个独立区域。</summary>
  53. [Serializable]
  54. [Plugin("H连通域", PluginCategory.Halocn模块, typeof(HalconConnectionModel), "VectorSquare",
  55. NodeShape = NodeCategory.Normal, IsSubFlowNode = true, VisionCategory = VisionPlugin.图像处理,
  56. Description = "连通域拆分:把一个区域拆成多个独立区域,输出区域集与数量")]
  57. public class HalconConnectionPlugin : BasePlugin<HalconConnectionModel>
  58. {
  59. public override List<OutputField> DeclareOutputs() => new List<OutputField>
  60. {
  61. new OutputField("区域集", typeof(object)),
  62. new OutputField("数量", typeof(int)),
  63. new OutputField("结果", typeof(bool)),
  64. };
  65. public override NodeRunStatus PluginRun(CancellationToken token, out Dictionary<string, object> results)
  66. {
  67. var res = new Dictionary<string, object>();
  68. results = res;
  69. NodeRunStatus Fail(string m) { res["Error"] = m; res["结果"] = false; Log(1, $"连通域失败: {m}", TeamAAS.LogLevel.Error); return NodeRunStatus.Failed; }
  70. try
  71. {
  72. var src = GetResolve(Model.RegionSource);
  73. if (!(src is HObject region)) return Fail("未获取到输入区域(请绑定上游「区域」输出)");
  74. var connected = HalconRuntime.Connection(region);
  75. int n = HalconRuntime.CountObj(connected);
  76. res["区域集"] = connected;
  77. res["数量"] = n;
  78. res["结果"] = true;
  79. HalconEditorPreview.Show(Model, null, connected, "yellow"); // 只更新叠加区域,保留底图
  80. Log(2, $"连通域拆分完成,得到 {n} 个独立区域");
  81. return NodeRunStatus.Success;
  82. }
  83. catch (Exception ex) { return Fail(ex.Message); }
  84. }
  85. }
  86. /// <summary>H图像预处理:滤波 / 灰度线性变换 / 转灰度。</summary>
  87. [Serializable]
  88. [Plugin("H图像预处理", PluginCategory.Halocn模块, typeof(HalconPreprocessModel), "Blur",
  89. NodeShape = NodeCategory.Normal, IsSubFlowNode = true, VisionCategory = VisionPlugin.图像处理,
  90. Description = "图像预处理:均值/中值/高斯滤波、灰度线性变换、转灰度")]
  91. public class HalconPreprocessPlugin : BasePlugin<HalconPreprocessModel>
  92. {
  93. public override List<OutputField> DeclareOutputs() => new List<OutputField>
  94. {
  95. new OutputField("图像", typeof(object)),
  96. new OutputField("结果", typeof(bool)),
  97. };
  98. public override NodeRunStatus PluginRun(CancellationToken token, out Dictionary<string, object> results)
  99. {
  100. var res = new Dictionary<string, object>();
  101. results = res;
  102. NodeRunStatus Fail(string m) { res["Error"] = m; res["结果"] = false; Log(1, $"图像预处理失败: {m}", TeamAAS.LogLevel.Error); return NodeRunStatus.Failed; }
  103. bool owned = false;
  104. HObject image = null;
  105. try
  106. {
  107. var src = GetResolve(Model.ImageSource);
  108. if (src == null) return Fail("未获取到输入图像(请绑定「输入图像」)");
  109. owned = !(src is HObject);
  110. image = HalconRuntime.ToHObject(src);
  111. HObject outImg;
  112. switch (Model.ProcessType)
  113. {
  114. case HalconPreprocessType.均值滤波:
  115. outImg = HalconRuntime.MeanImage(image, Model.Param1, Model.Param2 > 0 ? Model.Param2 : Model.Param1);
  116. break;
  117. case HalconPreprocessType.中值滤波:
  118. outImg = HalconRuntime.MedianImage(image, "circle", Model.Param1, "mirrored");
  119. break;
  120. case HalconPreprocessType.高斯滤波:
  121. outImg = HalconRuntime.GaussFilter(image, Model.Param1);
  122. break;
  123. case HalconPreprocessType.灰度线性变换:
  124. outImg = HalconRuntime.ScaleImage(image, Model.Param1, Model.Param2);
  125. break;
  126. case HalconPreprocessType.转灰度:
  127. outImg = HalconRuntime.RgbToGray(image);
  128. break;
  129. default:
  130. return Fail($"未知处理方式:{Model.ProcessType}");
  131. }
  132. res["图像"] = outImg;
  133. res["结果"] = true;
  134. HalconEditorPreview.Show(Model, outImg, null); // 图层发布:处理后的图像作底图
  135. Log(2, $"图像预处理完成:{Model.ProcessType}");
  136. return NodeRunStatus.Success;
  137. }
  138. catch (Exception ex) { return Fail(ex.Message); }
  139. finally { if (owned) HalconRuntime.Dispose(image); }
  140. }
  141. }
  142. /// <summary>H形态学:对区域做膨胀/腐蚀/开/闭运算。</summary>
  143. [Serializable]
  144. [Plugin("H形态学", PluginCategory.Halocn模块, typeof(HalconMorphologyModel), "ArrowExpandAll",
  145. NodeShape = NodeCategory.Normal, IsSubFlowNode = true, VisionCategory = VisionPlugin.图像处理,
  146. Description = "形态学:膨胀/腐蚀/开运算/闭运算(圆形结构元)")]
  147. public class HalconMorphologyPlugin : BasePlugin<HalconMorphologyModel>
  148. {
  149. public override List<OutputField> DeclareOutputs() => new List<OutputField>
  150. {
  151. new OutputField("区域", typeof(object)),
  152. new OutputField("结果", typeof(bool)),
  153. };
  154. public override NodeRunStatus PluginRun(CancellationToken token, out Dictionary<string, object> results)
  155. {
  156. var res = new Dictionary<string, object>();
  157. results = res;
  158. NodeRunStatus Fail(string m) { res["Error"] = m; res["结果"] = false; Log(1, $"形态学失败: {m}", TeamAAS.LogLevel.Error); return NodeRunStatus.Failed; }
  159. try
  160. {
  161. var src = GetResolve(Model.RegionSource);
  162. if (!(src is HObject region)) return Fail("未获取到输入区域(请绑定上游「区域」输出)");
  163. HObject outRegion;
  164. switch (Model.Operation)
  165. {
  166. case HalconMorphOperation.膨胀: outRegion = HalconRuntime.DilationCircle(region, Model.Radius); break;
  167. case HalconMorphOperation.腐蚀: outRegion = HalconRuntime.ErosionCircle(region, Model.Radius); break;
  168. case HalconMorphOperation.开运算: outRegion = HalconRuntime.OpeningCircle(region, Model.Radius); break;
  169. case HalconMorphOperation.闭运算: outRegion = HalconRuntime.ClosingCircle(region, Model.Radius); break;
  170. default: return Fail($"未知形态学操作:{Model.Operation}");
  171. }
  172. res["区域"] = outRegion;
  173. res["结果"] = true;
  174. HalconEditorPreview.Show(Model, null, outRegion, "orange"); // 只更新叠加区域,保留底图
  175. Log(2, $"形态学完成:{Model.Operation},半径={Model.Radius}");
  176. return NodeRunStatus.Success;
  177. }
  178. catch (Exception ex) { return Fail(ex.Message); }
  179. }
  180. }
  181. }