1874c4a5bb
统一补齐对齐核心工具类、RoiAlignment 算子、模板匹配对齐扩展和多语言资源,便于在检测前稳定完成示教 ROI 到运行图的变换。 Co-authored-by: Cursor <cursoragent@cursor.com>
115 lines
4.2 KiB
C#
115 lines
4.2 KiB
C#
namespace XP.ImageProcessing.Core.Alignment;
|
|
|
|
/// <summary>
|
|
/// 流水线胶水入口:模板匹配 OutputData → ROI 变换 → 写入下游 VoidMeasurement 等算子参数字典。
|
|
/// 不依赖 XplorePlane;由 PipelineExecutionService 在步骤间调用。
|
|
/// </summary>
|
|
public static class RoiAlignmentPipelineBridge
|
|
{
|
|
/// <summary>
|
|
/// 将测量位姿写入 RoiAlignment 算子参数(MeasuredCenterX/Y/Angle)。
|
|
/// </summary>
|
|
public static void InjectMeasuredPose(IDictionary<string, object> roiAlignmentParameters, Pose2D measuredPose)
|
|
{
|
|
if (roiAlignmentParameters == null)
|
|
throw new ArgumentNullException(nameof(roiAlignmentParameters));
|
|
|
|
roiAlignmentParameters["MeasuredCenterX"] = measuredPose.X;
|
|
roiAlignmentParameters["MeasuredCenterY"] = measuredPose.Y;
|
|
roiAlignmentParameters["MeasuredAngle"] = measuredPose.AngleDegrees;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 将示教基准位姿写入 RoiAlignment 算子参数(RefCenterX/Y/Angle)。
|
|
/// </summary>
|
|
public static void InjectReferencePose(IDictionary<string, object> roiAlignmentParameters, Pose2D referencePose)
|
|
{
|
|
if (roiAlignmentParameters == null)
|
|
throw new ArgumentNullException(nameof(roiAlignmentParameters));
|
|
|
|
roiAlignmentParameters["RefCenterX"] = referencePose.X;
|
|
roiAlignmentParameters["RefCenterY"] = referencePose.Y;
|
|
roiAlignmentParameters["RefAngle"] = referencePose.AngleDegrees;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 从模板匹配一步 OutputData 读取位姿并对齐示教 ROI。
|
|
/// </summary>
|
|
public static bool TryAlignFromTemplateMatch(
|
|
AlignmentRecipe recipe,
|
|
IReadOnlyDictionary<string, object>? templateMatchOutput,
|
|
out RoiAlignmentResult result,
|
|
int matchIndex = 0)
|
|
{
|
|
result = RoiAlignmentApplier.ApplyFromTemplateMatchOutput(recipe, templateMatchOutput, matchIndex);
|
|
return result.Success;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 将 RoiAlignment 算子 OutputData 中的 Poly* 拷贝到检测算子参数字典(如 VoidMeasurement)。
|
|
/// </summary>
|
|
public static bool TryCopyAlignedRoiToDetectionParameters(
|
|
IReadOnlyDictionary<string, object>? roiAlignmentOutput,
|
|
IDictionary<string, object> 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<string, object> 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;
|
|
}
|
|
}
|