namespace XP.ImageProcessing.Core.Alignment; /// /// 流水线胶水入口:模板匹配 OutputData → ROI 变换 → 写入下游 VoidMeasurement 等算子参数字典。 /// 不依赖 XplorePlane;由 PipelineExecutionService 在步骤间调用。 /// public static class RoiAlignmentPipelineBridge { /// /// 将测量位姿写入 RoiAlignment 算子参数(MeasuredCenterX/Y/Angle)。 /// public static void InjectMeasuredPose(IDictionary roiAlignmentParameters, Pose2D measuredPose) { if (roiAlignmentParameters == null) throw new ArgumentNullException(nameof(roiAlignmentParameters)); roiAlignmentParameters["MeasuredCenterX"] = measuredPose.X; roiAlignmentParameters["MeasuredCenterY"] = measuredPose.Y; roiAlignmentParameters["MeasuredAngle"] = measuredPose.AngleDegrees; } /// /// 将示教基准位姿写入 RoiAlignment 算子参数(RefCenterX/Y/Angle)。 /// public static void InjectReferencePose(IDictionary roiAlignmentParameters, Pose2D referencePose) { if (roiAlignmentParameters == null) throw new ArgumentNullException(nameof(roiAlignmentParameters)); roiAlignmentParameters["RefCenterX"] = referencePose.X; roiAlignmentParameters["RefCenterY"] = referencePose.Y; roiAlignmentParameters["RefAngle"] = referencePose.AngleDegrees; } /// /// 从模板匹配一步 OutputData 读取位姿并对齐示教 ROI。 /// public static bool TryAlignFromTemplateMatch( AlignmentRecipe recipe, IReadOnlyDictionary? templateMatchOutput, out RoiAlignmentResult result, int matchIndex = 0) { result = RoiAlignmentApplier.ApplyFromTemplateMatchOutput(recipe, templateMatchOutput, matchIndex); return result.Success; } /// /// 将 RoiAlignment 算子 OutputData 中的 Poly* 拷贝到检测算子参数字典(如 VoidMeasurement)。 /// public static bool TryCopyAlignedRoiToDetectionParameters( IReadOnlyDictionary? roiAlignmentOutput, IDictionary detectionParameters, out string? errorMessage) { errorMessage = null; if (roiAlignmentOutput == null) { errorMessage = "ROI alignment output is null."; return false; } if (roiAlignmentOutput.TryGetValue(RoiAlignmentOutputKeys.Success, out var okObj) && okObj is bool ok && !ok) { if (roiAlignmentOutput.TryGetValue(RoiAlignmentOutputKeys.Message, out var msgObj) && msgObj is string msg && !string.IsNullOrWhiteSpace(msg)) errorMessage = msg; else errorMessage = "ROI alignment failed."; return false; } if (!roiAlignmentOutput.TryGetValue(RoiPolygonParameterNames.PolyCount, out var countObj)) { errorMessage = "ROI alignment output has no PolyCount."; return false; } int count = Convert.ToInt32(countObj); if (count < 3) { errorMessage = $"Invalid aligned PolyCount={count}."; return false; } RoiAlignmentApplier.WriteToParameters(detectionParameters, new RoiAlignmentResult { Success = true, TransformedPointsInt = ReadIntPointsFromOutput(roiAlignmentOutput, count) }); return true; } private static IReadOnlyList<(int X, int Y)> ReadIntPointsFromOutput( IReadOnlyDictionary output, int count) { var list = new List<(int X, int Y)>(count); for (int i = 0; i < count; i++) { int x = output.TryGetValue(RoiPolygonParameterNames.PolyX(i), out var xo) ? Convert.ToInt32(xo) : 0; int y = output.TryGetValue(RoiPolygonParameterNames.PolyY(i), out var yo) ? Convert.ToInt32(yo) : 0; list.Add((x, y)); } return list; } }