namespace XP.ImageProcessing.Core.Alignment; /// /// 从旋转模板匹配算子(键 )的 OutputData 读取测量位姿。 /// public static class TemplateMatchOutputReader { public const string ProcessorKey = "RotatedTemplateMatching"; public static bool TryReadMeasuredPose( IReadOnlyDictionary? outputData, out Pose2D measuredPose, out string? errorMessage, int matchIndex = 0) { measuredPose = default; errorMessage = null; if (outputData == null || outputData.Count == 0) { errorMessage = "Template match output is empty."; return false; } if (outputData.TryGetValue("Matched", out var matchedObj) && matchedObj is bool matched && !matched) { if (outputData.TryGetValue("Message", out var msgObj) && msgObj is string msg && !string.IsNullOrWhiteSpace(msg)) errorMessage = msg; else errorMessage = "Template match failed (Matched=false)."; return false; } if (outputData.TryGetValue("MatchCount", out var countObj)) { int count = Convert.ToInt32(countObj); if (count <= 0) { errorMessage = "Template match count is zero."; return false; } if (matchIndex < 0 || matchIndex >= count) { errorMessage = $"Match index {matchIndex} is out of range (MatchCount={count})."; return false; } } string prefix = matchIndex == 0 ? string.Empty : $"[{matchIndex}]"; if (!TryReadDouble(outputData, "CenterX" + prefix, out double cx) || !TryReadDouble(outputData, "CenterY" + prefix, out double cy) || !TryReadDouble(outputData, "Angle" + prefix, out double angle)) { errorMessage = "Template match output is missing CenterX/CenterY/Angle."; return false; } measuredPose = new Pose2D(cx, cy, angle); return true; } private static bool TryReadDouble(IReadOnlyDictionary data, string key, out double value) { value = 0; if (!data.TryGetValue(key, out var obj) || obj == null) return false; try { value = Convert.ToDouble(obj); return true; } catch { return false; } } }