边缘设备上的实时交通冲突估计

衡量险情而非碰撞——通过跟踪轨迹计算TTC和PET,使用纯numpy实现。

边缘设备上的实时交通冲突估计
梯形图转SCL | AI模型价格对比 | AI工具导航 | ONNX模型库 | Vibe Coding教程 | PLC在线仿真器 | Tripo 3D | Meshy AI | ElevenLabs | KlingAI | ArtSpace | Phot.AI | InVideo

我部署的每个交通管道——包括Jetson上的YOLOv8 + TensorRT + ByteTrack——一旦跟踪器工作且相机标定完成,都会遇到同样的问题:接下来怎么办?速度很好,计数很好,但交通工程师真正获得资助要回答的问题是"这个处理措施是否使站点更安全?"碰撞计数需要多年才能变化。实时交通冲突估计是实用的答案:衡量险情而非碰撞,持续进行,在边缘设备上完成。本文结束了这个系列——跟踪轨迹、标定到米数,现在转化为安全事件。

1、为什么选择冲突而非碰撞

单个交叉口的碰撞是罕见事件;等待足够多的碰撞来比较前后时期是一个多年的项目。交通冲突技术比深度学习早了几十年:Perkins和Harris在1967年在通用汽车公司推广了这个想法,Hayward在1972年宾夕法尼亚州立大学报告中形式化了碰撞时间,Hydén的瑞典冲突技术在1987年将观察者评级转化为现场方法。从那时起改变的不是数学——而是一个小而便宜的盒子现在可以自动运行整个观察。

计算这些指标的现代参考是Gettman和Head的替代安全评估方法论(FHWA-RD-03-050;期刊版本在TRR 1840)。它定义了替代指标及其算法,用于冲突点(交叉流)和冲突线(汇合和跟随流)——任何认真实现都应该遵循的分类法。

2、承担大部分工作的两个指标

碰撞时间(TTC)。 Hayward的定义:如果两辆车继续以当前速度和相同路径行驶,碰撞所需的时间。对于跟踪的一对,你在每个时间步计算它,并在交互期间保持最小值。阈值是研究选择,而非物理:SSAM算法使用1.5秒作为交叉口入口有效冲突上限的工作示例——来自van der Horst的论文工作——而更高的临界值(2.6-3.5秒)出现在高速跟车中。

占用后时间(PET)。 一个道路使用者离开区域和另一个到达之间在交叉点的时间间隙。PET只需要路径交叉的位置和每个使用者通过的时间——不需要速度,这使其成为检测噪声不可避免时更稳健的选择。它的弱点:它假设你可以识别冲突点,而这正是两辆车在图像中相互遮挡的地方。

3、代码

前两篇文章的前提条件:来自跟踪器的每个道路使用者轨迹(id、像素位置、时间戳),以及将去畸变像素映射到地面米的单应性。以下所有内容都是纯numpy。

TTC,最近接近形式:

import numpy as np

def min_ttc(a, ta, b, tb, extent=1.0):
    """两个地面平面轨迹之间的最小碰撞时间。

    a, b: (N,2) 以米为单位的轨迹;ta, tb: 严格递增的秒数。
    extent: 被视为碰撞的中心到接触距离(米)。
    """
    bx = np.stack([np.interp(ta, tb, b[:, 0]),
                   np.interp(ta, tb, b[:, 1])], axis=1)
    dt = np.diff(ta)
    va = np.diff(a, axis=0) / dt[:, None]        # 速度样本
    vb = np.diff(bx, axis=0) / dt[:, None]
    r  = a[:-1] - bx[:-1]                        # 相对位置
    v  = va - vb                                  # 相对速度
    vv = np.einsum('ij,ij->i', v, v)
    t  = np.where(vv > 0, -np.einsum('ij,ij->i', r, v) / vv, np.inf)
    ok = (t > 0) & (t < 10)                      # 合理的视界
    dmin = np.linalg.norm(r + v * t[:, None], axis=1)
    hit = ok & (dmin <= extent)                  # 处于碰撞路线上
    return float(np.min(t[hit])) if hit.any() else np.inf

PET,路径交叉形式:

def _time_at(track, ts, x):
    """轨迹通过最接近地面点x的时间戳。"""
    d = np.linalg.norm(track - x, axis=1)
    k = int(np.argmin(d))
    if k == 0 or k == len(ts) - 1:
        return float(ts[k])
    lo, hi = k - 1, k + 1
    seg = track[hi] - track[lo]
    t = np.clip((x - track[lo]) @ seg / (seg @ seg), 0.0, 1.0)
    return float(ts[lo] + t * (ts[hi] - ts[lo]))

def pet(a, ta, b, tb):
    """两条路径交叉处的占用后时间(秒)。"""
    D = np.linalg.norm(a[:, None, :] - b[None, :, :], axis=2)
    i, j = np.unravel_index(np.argmin(D), D.shape)
    x = 0.5 * (a[i] + b[j])          # 冲突点(米)
    return _time_at(b, tb, x) - _time_at(a, ta, x)

对于交叉冲突,报告两者;它们以有信息量的方式不一致。

4、实时冲突估计在边缘设备上的成本

好消息是:以上所有都是numpy的微秒级操作。这个管道的计算预算在安全阶段之前就花完了——在检测器上。这就是为什么跟踪文章中的TensorRT引擎是正确的基础:导出一次,在Jetson上运行批量1推理,并将冲突估计视为跟踪更新的回调。两个实际注意事项:

  • 在运行TTC/PET之前,通过空间接近性(几米)门控候选对。在典型的交叉口密度下,完整的成对矩阵已经微不足道,但门控在高峰期保持其微不足道。
  • 在每个跟踪更新上运行安全阶段,而不是在保存的视频上。值得存储的输出是事件日志——时间戳、配对、度量值、冲突点——而不是视频本身。一天的事件是千字节;一天的视频是隐私负担。

5、出错的地方

  • ID切换。 将两辆车合并为一个身份的跟踪器会默默地消除冲突。ByteTrack很稳健,但不完美:在信任低计数之前审计切换,并在跟踪较短时优先使用PET(基于路径)。
  • 质心与接触点。 车辆长4.5米。将检测框的底部中心映射到地面平面,而不是框中心,并根据实际车辆尺寸设置extent——而不是习惯性地设为1.0。
  • 远场放大。 速度可容忍的单应性误差在TTC中会放大,TTC除以接近速度。在你的地面控制区域内测量冲突,就此为止。
  • 最糟糕时刻的遮挡。 两辆即将冲突的车辆在最需要的时候在图像中重叠。使用匀速模型预测短间隙,并标记轨迹被修补的事件。
  • 仅阈值报告。 "14个冲突低于1.5秒"隐藏的比显示的多。按小时和位置报告TTC/PET的分布——形状在计数之前移动。
路边研究也会产生文书工作——碰撞报告、调查表、截图和附加到论文的文件。那也是个人数据。如果文件需要离开设备用于报告或论文,请先编辑:PrivateRedact可以100%离线地从PDF、扫描件、DOCX和图像中删除标识符——本地LLM,无需上传。

6、常见问题

我应该首先计算哪个指标,TTC还是PET?

交叉运动用PET——它不需要速度,能承受噪声检测。跟车和追尾交互用TTC,因为没有清晰的交叉点。尽可能同时报告两者。

冲突估计需要特殊的相机放置吗?

标定文章的要求仍然适用,加上一个:冲突区域本身必须可见。能看到长进场腿但看不到交叉点的相机产生速度,而不是冲突。

我需要多少视频才能获得稳定的估计?

比你想象的要多——严重冲突比车辆更罕见。方法与数量同样重要:进行类似比较(相同工作日组合、相同时段),并将事件计数视为趋势线,而不是一次性结论。

我可以只用CPU运行这个吗?

安全阶段,轻而易举。检测器是成本——而那是TensorRT/Jetson的问题,在跟踪文章中有介绍。

这结束了本文承诺的系列。它建立的基础:Jetson上的检测和跟踪以及路边相机标定;更广泛的研究方向在交通安全中的LLM中。


原文链接:Real-Time Traffic Conflict Estimation on an Edge Device

汇智网翻译整理,转载请标明出处