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;
}
}