using UnityEngine;
namespace LightGlue.Unity.Networking
{
///
/// LightGlue算法结果数据类
/// 包含相机位置、匹配质量等信息
///
public struct LightGlueResult
{
///
/// 坐标映射目标类型:
/// - GameScreen:用于 Camera.ScreenPointToRay 等“屏幕坐标”场景(左下角原点)
/// - UIAnchored:用于 RectTransform.anchoredPosition 等 UI 场景(通常也是左下角原点,但可能需要 offset)
///
public enum MappedCoordinateType
{
GameScreen = 0,
UIAnchored = 1,
}
///
/// 结果是否有效(单应性矩阵计算成功且匹配点数量足够)
///
public bool IsValid { get; }
///
/// 匹配点数量(参考帧与当前帧之间的匹配关键点数量)
///
public ushort NumMatches { get; }
///
/// 内点比例(单应性矩阵计算中的内点比例,范围 0.0-1.0)
///
public float InliersRatio { get; }
///
/// 相机位置(在参考图像坐标系中的像素坐标,原点在左上角)
///
public Vector2 CameraPosition { get; }
///
/// 构造函数
///
public LightGlueResult(bool isValid, ushort numMatches, float inliersRatio, float cameraX, float cameraY)
{
IsValid = isValid;
NumMatches = numMatches;
InliersRatio = inliersRatio;
CameraPosition = new Vector2(cameraX, cameraY);
}
///
/// 创建无效结果(当算法计算失败时使用)
///
public static LightGlueResult CreateInvalid(ushort numMatches = 0)
{
return new LightGlueResult(false, numMatches, 0.0f, 0.0f, 0.0f);
}
///
/// 将参考图像坐标(原点左上,Y向下)映射到目标坐标(原点左下,Y向上)。
/// 用于统一 UI / Camera 的坐标转换逻辑,避免重复实现。
///
/// 参考图宽(必须与 Python --resize 一致)
/// 参考图高(必须与 Python --resize 一致)
/// 目标宽(Screen.width 或 Canvas 宽)
/// 目标高(Screen.height 或 Canvas 高)
/// 目标使用场景(UI / Camera)。当前两者映射规则一致,差别主要体现在 offset 用途。
/// 额外偏移(用于 UI anchoredPosition 的中心偏移等)。
public Vector2 GetMappedPosition(
int referenceWidth,
int referenceHeight,
float targetWidth,
float targetHeight,
MappedCoordinateType type = MappedCoordinateType.GameScreen,
Vector2 offset = default)
{
if (referenceWidth <= 0 || referenceHeight <= 0) return offset;
if (targetWidth <= 0f || targetHeight <= 0f) return offset;
float scaleX = targetWidth / referenceWidth;
float scaleY = targetHeight / referenceHeight;
float x = CameraPosition.x * scaleX;
float y = targetHeight - (CameraPosition.y * scaleY);
// 当前映射规则在 UI / Camera 两类场景相同;UI 额外通过 offset 适配 anchoredPosition 的坐标原点偏移
_ = type; // 保留参数,便于未来扩展不同映射策略
return new Vector2(x + offset.x, y + offset.y);
}
public override string ToString()
{
if (IsValid)
{
return $"LightGlueResult(Valid, Matches={NumMatches}, Inliers={InliersRatio:P1}, Pos=({CameraPosition.x:F1}, {CameraPosition.y:F1}))";
}
else
{
return $"LightGlueResult(Invalid, Matches={NumMatches})";
}
}
}
}