做视频隐私掩码时,碰到过一个让人摸不着头的bug:某条被真实检测到4.6秒、共76帧的完整人脸轨迹,最终输出了零帧遮挡。
排查过程从导出文件倒推。掩码数据按时间轴写入轨道列表,每条轨道由一个track ID作为key,包含逐帧的cx, cy坐标。问题锁定在硬切场景的处理逻辑上:硬切发生后需要重置追踪状态,此时底层OpenCV CSRT/KCF tracker被重新启动,ID从1开始重新编号;而轨迹数据的过期机制是只在活跃列表中删除标记为过期的track,数据本体故意保留到后处理阶段。
当旧轨因长时间未更新而被新检测覆盖时,它对应的轨道条目不会被清理。新的tracker发出tid=1后,下一行按key赋值的逻辑直接把旧tid=1对应的整条记录给覆盖了------下游的二分插值函数读到的是一个被改写了的坐标序列,导致那段真实的人脸遮挡数据在写入输出时被静默丢掉。
修法是把「碰撞处理」从覆盖改为安置:当检测到新track的ID与已存在且仍活跃的轨道冲突时,不再直接赋值重写,而是给即将失效的那条旧轨分配一个不会与新tracker产生碰撞的备用key,让它的坐标数据完整保留。这样做的前提是确认下游插值函数要求每个key对应单条单调轨迹------如果把两条交叉的话输出会产生跳变。
涉及多目标跟踪的场景里,状态迁移时的ID管理是一个容易忽略的细节。写追踪逻辑时建议先画一张从检测到输出的状态流转表,把每条边上的数据读写操作逐一核实,特别是覆盖类写入,确保不会误删还未到终态的活跃记录。
本文来自抹影的开发笔记。