You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于VNDetectTrajectoriesRequest来球轨迹获取及衔接问题的技术咨询

关于VNDetectTrajectoriesRequest轨迹衔接问题的解决方案

针对你遇到的轨迹无法衔接问题,核心原因在于VNDetectTrajectoriesRequest生成的轨迹UUID并不保证在连续帧中持续绑定同一个运动物体——当球出现短暂遮挡、检测置信度波动或运动状态变化时,系统可能会生成新的UUID,导致旧轨迹无法关联新的观测结果。结合你的代码,给出以下修复方案:

关键修改点

  • 放弃单纯依赖UUID做轨迹匹配,改用空间距离+运动一致性关联帧间轨迹
  • 增加轨迹超时机制,避免误删暂时未被检测到的轨迹
  • 优化检测点的追加逻辑,确保轨迹点的连续性

修改后的代码

guard let observations = request.results as? [VNTrajectoryObservation] else { return }

// 先更新所有已有轨迹的计数器(用于超时清理)
for (uuid, property) in trajectoryDictionary {
    property.count += 1
    // 连续5帧未匹配到则删除轨迹
    if property.count > 5 {
        trajectoryDictionary.removeValue(forKey: uuid)
    }
}

for observation in observations {
    /// 适当放宽置信度阈值,避免临时波动导致轨迹断裂
    if observation.confidence < 0.7 { continue }
    
    let detectedPoints: [CGPoint] = observation.detectedPoints.compactMap { point in
        CGPoint(x: point.x, y: 1 - point.y)
    }
    let projectedPoints: [CGPoint] = observation.projectedPoints.compactMap { point in
        CGPoint(x: point.x, y: 1 - point.y)
    }
    
    var matchedUUID: UUID?
    let currentLastPoint = detectedPoints.last!
    let maxMatchDistance: CGFloat = 0.05 // 可根据画面尺寸调整
    
    // 遍历已有轨迹,寻找空间上连续的匹配项
    for (uuid, property) in trajectoryDictionary {
        guard let existingLastPoint = property.detectedPoints.last else { continue }
        let distance = hypot(currentLastPoint.x - existingLastPoint.x, currentLastPoint.y - existingLastPoint.y)
        if distance < maxMatchDistance {
            matchedUUID = uuid
            break
        }
    }
    
    if let uuid = matchedUUID {
        // 匹配到已有轨迹,追加新的检测点并更新数据
        trajectoryDictionary[uuid]!.detectedPoints.append(currentLastPoint)
        trajectoryDictionary[uuid]!.projectedPoints = projectedPoints
        trajectoryDictionary[uuid]!.equationCoefficients = observation.equationCoefficients
        trajectoryDictionary[uuid]!.confidence = observation.confidence
        trajectoryDictionary[uuid]!.count = 0 // 重置超时计数器
    } else {
        // 无匹配轨迹,创建新条目
        trajectoryDictionary[observation.uuid] = TrajectoryProperty(
            detectedPoints: detectedPoints,
            projectedPoints: projectedPoints,
            equationCoefficients: observation.equationCoefficients,
            confidence: observation.confidence
        )
    }
}

drawTrajectories(trajectoryDictionary)

额外建议

  • 你可以进一步优化匹配逻辑,比如结合observation.equationCoefficients比较轨迹的运动方向和加速度,提升匹配准确性
  • 如果你的场景中球的尺寸固定,可以结合VNDetectRectanglesRequest先检测球的位置,再辅助轨迹匹配,进一步提升稳定性

球的轨迹示例

内容的提问来源于stack exchange,提问作者Mike

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 05:22:20