简介这份PPT围绕视频数据标注中的目标跟踪任务展开以百度EasyDL平台为操作主线面向刚接触计算机视觉数据标注的算法工程师、标注团队或相关专业学生。内容从创建模型、创建数据集、上传数据开始到在线标注、添加标签、标注关键帧与目标消失帧逐步演示了目标跟踪标注的完整流程能够帮助初学者理解从原始视频到可训练数据集的关键步骤与常见操作细节。PPT共1个演示文稿文件压缩包大小3.13MB单文件便于按页码翻看步骤截图与界面说明。目前已有1109人学习浏览适合需要快速上手视频目标跟踪标注或准备开展数据标注培训的读者。通过这份PPT可直观看到EasyDL目标跟踪标注界面的操作节奏包括矩形框选目标、多关键帧跟踪、消失帧处理等实用技巧同时强化标注质量对模型精度的重要认知有效节省自行摸索与踩坑时间。1. 视频数据标注的难点不在画框而在时间轴早上打开一份名为数据标注视频数据标注案例.pptx的材料时如果只看到满屏画好的框那这份复盘大概率漏掉了真正重要的环节。视频数据标注和普通图片标注的差别不在框的数量而在于时间轴上目标身份是否始终一致同一个行人在 25fps 的视频里被车挡住两秒标注员很容易把它标成两段轨迹后面做跟踪训练时算法再怎么调参也补不回来。对算法工程师、标注团队负责人和数据标注行业的新手来说这篇文章按一线落地顺序把链路拉通一遍需求维度怎么拆、抽帧和关键帧插值怎么设、半自动标注怎么提效、质检到底查哪几个指标以及最后用回放怎么验收。2. 视频数据标注的工具选型先定规范再选工具2.1 视频数据标注的三个维度空间框、时间流与属性状态视频数据标注和图片数据标注的本质区别是每次操作都要面对一个隐含的第四维时间。标注对象不再是静止的单帧画面而是一段连续动作。按我处理园区车辆与行人混合视频标注项目的惯例所有视频数据标注任务从需求上都可以拆成三个维度。第一个维度是空间标注。目标检测任务就是边界框实例分割任务就是多边形语义分割任务就是像素级掩码。这个维度和图片标注几乎一致差别只在于要连续地在多帧上重复。第二个维度是时间流标注。视频数据标注需要记录目标的跨帧轨迹同一个目标从第 100 帧进入画面到第 420 帧离开中间每一帧都要有同一个 track_id。第三个维度是属性状态比如这辆车是否被遮挡这个行人是否在打电话这是后续做困难样本挖掘和逻辑召回的关键字段。对三个维度的标注深度做决定时数据标注工具之间才具备真正意义上的可比性。很多团队把成本估算集中在画框个数上忽略了属性状态的字段设计。一个真实踩过的坑共享单车园区违规停放监控项目最初没标车篮是否有载物算法训练完无法区分载物和空载场景最后只能对整个视频数据标注任务回炉补标整体返工了两周。正确做法是在任务派发前先定属性清单比如是否被遮挡是/否/未知动作类型骑行/推行/静止并写进任务说明确保所有标注员口径一致。2.2 数据标注工具横向对比CVAT、Label Studio与X-AnyLabeling视频数据标注工具的选型通常不取决于哪个工具画框手感好而取决于它能否支持关键帧插值、轨迹 ID 管理和视频帧序列抽取。目前我常用的开源数据标注工具主要有三个各自的能力边界不太一样。工具视频标注能力插值方式适合场景注意点CVAT内置视频轨道标注关键帧之间自动插值可接 AI 模型检测、跟踪、分割一体部署偏重依赖 DockerLabel Studio视频帧序列标注人工逐帧插件可扩展事件打标、动作起止时间视频目标框标注体验一般X-AnyLabeling视频抽帧 模型预标注SAM 按帧生成掩码小团队快速出分割结果视频过大需要先单独抽帧CVAT 的插值模式是视频数据标注效率最高的实现方式标注员只在选定的关键帧上画框下一关键帧画完中间帧由平台自动补全轨迹。但如果需求主要是动作事件打标而不是目标跟踪Label Studio 更轻量不需要起一套重型服务。X-AnyLabeling 更适合本地小规模快速出掩码几十个 G 的视频建议先按 3.1 的抽帧逻辑变成图片序列再导入。2.3 数据标注规范任务怎么拆、帧段怎么切视频数据标注规范不能只写框住所有目标要写明任务切分和边界交接规则。切视频时我一般按一个动作闭环来切不要让一个视频文件横跨两个光照完全不同的场景。比如行人从室外走进室内环境亮度和背景完全变化应该切成两个任务段否则标注员会因目标突然不可见产生困惑track 也容易断。任务段的长度也要控制。一个标注员每天合理产出大约是 400 到 600 个有效关键帧如果每段抽帧后剩余 100 帧左右每人每天约处理 5 段。拆太短前一个任务段和后一个任务段之间的 ID 交接频繁后处理要花时间合并拆太长单任务盯太久容易疲劳错误率在第二小时明显上升。人员协作上要把 ID 一致性作为和框准确率并列的考核指标。多个标注员协作时如果任务段之间存在同一目标的跨段轨迹需要在导出结果里保留跨段交接字段或者直接在视频切片时预留 5 帧重叠后处理脚本再做 ID 归并。这个细节决定了最终数据能否训练跟踪模型。3. 用关键帧插值跑通视频标注前置流程ffmpeg抽帧与任务打包视频数据标注项目的第一步不是打开标注平台而是决定让标注员看到哪些帧。直接把 25fps 的视频原样导入工具一个 5 分钟的视频就有 7500 帧逐帧标注成本完全不可控。常规做法是抽帧加上关键帧插值先选一部分帧作为人工标注帧其余帧由数据标注工具在时间轴上自动补全。3.1 抽帧策略固定间隔还是场景切分默认策略是固定间隔抽帧间隔取 5 到 10 帧。目标运动越快、目标在画面里占据的像素越小间隔就要越短。比如园区出入口车辆起步慢10 帧间隔足够但行人突然转身或跑动5 帧间隔下插值更容易贴合实际位置。下面这条命令按每 5 帧抽取一帧输出的帧号按原视频时间轴保留下来后续训练时可以根据帧号直接换算真实时间戳# 从 input.mp4 中每 5 帧取一帧输出到 keyframes 目录 ffmpeg -i input.mp4 -vf selectnot(mod(n,5)),setptsN/FRAME_RATE/TB -vsync 0 keyframes/frame_%06d.jpgselectnot(mod(n,5))里的n是解码后的帧计数mod(n,5)取余数余数为 0 时保留当前帧setptsN/FRAME_RATE/TB把输出帧的时间戳重置为第 N 帧/帧率保证帧顺序正确-vsync 0让 ffmpeg 不要自作主张补帧或丢帧。很多人漏掉最后这个参数抽出来的帧序列偶尔会出现重复帧导致标注平台里轨迹抖动。如果视频场景切换频繁固定间隔会浪费大量标注工作量在无关帧上。可以先用镜头检测脚本找出切变点再按切变点分片抽帧# 输出发生场景切换的帧时刻用于后续切分视频 ffmpeg -i input.mp4 -vf selectgt(scene,0.4),showinfo -f null - 21 | grep pts_time这里的scene分数表示当前帧与前一帧画面的差异程度0.4 是保守阈值镜头切换、亮度突变都能捕获到。拿到pts_time后按时间点把视频切成短视频再对每个分段做固定间隔抽帧能省掉场景空白段带来的无效标注。场景类型建议帧间隔原因行人慢速行走10 帧位移小插值误差小车辆转弯、遮挡频繁5 帧避免轨迹断裂和插值偏移快速动作识别3 帧动作起止帧定位更准摄像头固定且画面静止1 帧即可减少存储和无效工作量3.2 关键帧插值让标注员只画 1/5 的帧抽帧完成后把图片序列导入支持视频标注的工具打开轨迹模式。标注员只标注第 0、5、10、15 帧也就是原视频每 25 帧中的 5 帧剩余中间帧由工具根据相邻关键帧自动生成插值结果track_id 保持不变。这是视频数据标注区别于普通图片标注的最大效率来源。在 CVAT 里做插值的常见配置是创建任务时选择插值标注模式标注员在时间轴上定位到关键帧画框到下一关键帧再调整框的位置工具会自动生成中间帧。参数上值得留意的是关键帧间隔不要设置过大默认的 10 帧对快速移动目标来说插值误差偏高我一般手动改成 5 帧以内的增量宁可让人多画一帧关键帧也不要让插值结果在视觉上抖得没法看。配合模型做自动插值的流程是抽帧后先运行检测模型生成各帧目标框再将检测框按跟踪算法关联成轨迹最后把轨迹结果作为预标注导入数据标注工具标注员负责删除误检、补充漏检、修改类别和属性。这样标注员每天的实际产出能从 400 帧提升到 1200 帧以上但前提是预标注质量本身不能太差。提示如果视频里目标大量相互遮挡预标注轨迹容易发生 ID 切换。此时不要盲目调低置信度优先检查跟踪器的max_age参数把目标丢失后保留轨迹的时间从默认值调大能明显减少被遮挡物的 ID 跳变。3.3 构建可追溯的数据标注任务目录标注任务不是一次性生产产出后还要清洗、合并、回滚。任务目录至少要能区分原始视频、抽帧图片、原始标注、已检核标注四类文件。我常用下面这套结构PROJECTgate-monitor mkdir -p $PROJECT/videos $PROJECT/frames $PROJECT/raw_anns $PROJECT/verified_anns find $PROJECT/frames/gate01 -name *.jpg | sort $PROJECT/raw_anns/gate01.txtraw_anns里放平台导出的原始标注 JSON文件名和帧号一一对应后续校验脚本直接从 JSON 重建标注verified_anns只保留通过质检的版本。数据标注工具导出的结果如果带 track_id 字段后处理时一定要保留一旦丢掉后续要定位某条轨迹在某帧的框时只能回原视频重看返工成本极高。4. 半自动标注与质量校验跑通视频数据标注流水线的关键节点4.1 用跟踪器和分割模型做视频预标注视频数据标注里最实用的提效手段是预标注。以常见的 YOLO 加 ByteTrack 方案为例先把视频切成帧列表用检测模型跑出每一帧的框然后用跟踪器为框分配稳定的 ID把跟踪结果导出成标注平台能识别的 JSON 格式标注员只需单击接受。下面的 Python 脚本示意了预标注主流程用的是 ultralytics 库的 track 接口from ultralytics import YOLO model YOLO(yolov8n.pt) # 检测模型 results model.track( gate-cam.mp4, persistTrue, trackerbytetrack.yaml, classes[0], # 只保留人这个类别 conf0.25, projectprelabel_out, nametracks, )persistTrue让跟踪器跨帧记忆同一个目标同一目标的框在连续帧中共享同一个 track_idtrackerbytetrack.yaml指定 ByteTrack 配置它是一个以检测框为输入的轻量跟踪器classes[0]限定模型只输出人这个类别减少误检和无效关联。输出目录里会生成一段带标注框的预览视频方便人工快速确认预标注效果。预标注的正确使用循环是今天标注、今晚训练、明早预标注拿已标注数据训一个初版模型第二天让模型辅助标注新的无标注视频如此迭代。半自动标注的核心价值不是消灭人工而是把标注员的精力集中在修正最难的目标上。4.2 质量校验统计标注框面积、ID与帧间跳变质量校验我一般写一个脚本扫批量的标注 JSON只检查四件事track_id 是否连续覆盖帧、同一 track 相邻帧边界框的重叠率是否突然掉到 0、框是否出现大面积绝对位置偏移、类别名是否超出规范清单。示例脚本片段如下设计成无第三方依赖即可运行import json with open(export_anns.json) as f: anns json.load(f) tracks {} for ann in anns: t_id ann[track_id] tracks.setdefault(t_id, []).append(ann) for t_id, frames in tracks.items(): frames.sort(keylambda x: x[frame_id]) for prev, curr in zip(frames, frames[1:]): gap curr[frame_id] - prev[frame_id] if gap 1: print(f[gap] track {t_id} frame {prev[frame_id]} - {curr[frame_id]}) iou compute_iou(prev[bbox], curr[bbox]) if iou 0.3: print(f[shift] track {t_id} frame {curr[frame_id]} iou{iou:.2f})逻辑说明track_id是视频数据标注中判断轨迹是否连续的锚点gap 1说明中间有帧漏标可能是插值任务没保存IOU 小于 0.3 说明框在相邻关键帧之间跳变太大大概率是标注员在关键帧之间漏画了一帧需要回去补。compute_iou函数按两个边界框交并比实现具体公式就是两个矩形的交集面积除以并集面积。质量参数的合理阈值可以参考下表指标阈值动作相邻关键帧 IOU不低于 0.4小于 0.4 查轨迹转折点track_id 缺失帧 gap0记录并补标类别取值与规范一致出现未知类别查原始帧边界框是否出画不允许裁边到画面外视为异常4.3 格式导出与数据切分COCO、YOLO与MOT下游任务不同要的标注格式也不同。目标检测用 YOLO 格式最方便实例分割用 COCO多目标跟踪直接吃 MOT 格式。视频数据标注工具导出的 JSON 一般都能转成这些格式但切分时最常见的错误是随机切帧导致同一段轨迹的一部分帧进 train一部分进 val评估出来的指标虚高。正确做法是按视频维度整体切分。比如手里 10 个视频来自同一环境、光照相似的 4 个放 val其余 6 个放 train不要从同一个视频里一半一半地切。对跟踪模型来说MOT 格式必须保留frame_id和track_id两列一行最小记录长这样1, 1, 722.5, 246.0, 88.0, 46, 1, 1, 1, 1字段依次是帧号、track_id、左上角 x、左上角 y、宽、高、置信度、类别、截断状态、保留字段。导出时如果标注属性里有截断或遮挡就映射到截断状态列别丢掉。核心转换逻辑可以这样写def ann_to_mot(ann, frame_id): x, y, w, h ann[bbox] return [frame_id, ann[track_id], round(x,1), round(y,1), round(w,1), round(h,1), 1, ann.get(cls_id, 0), 1, 1]参数说明bbox是边界框track_id对应跟踪 IDcls_id是类别的整数编码第 7 位的1是置信度占位值人工标注通常可以直接填 1。5. 用可视化回放审查视频数据标注的时序一致性5.1 插值结果的常见失真点关键帧插值不是万能的。目标做高速转向时插值框会因为线性假设偏离目标中心遮挡切换时插值框可能跟着背景里的其他目标走镜头晃动时中间帧的框会在目标周围漂移。这些异常在单张静态帧上几乎看不出问题只有把帧连续播放起来才会暴露。更隐蔽的是轨迹属性的连续性一个行人在第 40 帧被车挡住两秒如果插值没有处理遮挡关系车开走时标注工具可能重新创建一个新 ID算法会把同一个人当成两个人。检查时必须专门盯着这些遮挡切换位置看。5.2 用OpenCV合成带轨迹框的回放视频快速验收我最后一步的做法是把标注结果画回到每一帧上合成一个和原视频同帧率、同分辨率的 mp4然后以 1.5 到 2 倍速连续播放。这个回放视频就是验收物比任何统计报表都直接。import cv2 cap cv2.VideoCapture(frames_seq.mp4) out cv2.VideoWriter(review.mp4, cv2.VideoWriter_fourcc(*mp4v), 25, (w, h)) while True: ok, img cap.read() if not ok: break boxes get_boxes_from_ann(img, frame_id) # 从JSON按帧取框 for b in boxes: cv2.rectangle(img, (b[0], b[1]), (b[2], b[3]), (0, 255, 0), 2) cv2.putText(img, str(b[4]), (b[0], b[1] - 6), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) out.write(img) out.release()get_boxes_from_ann负责从标注 JSON 中按帧号取出所有边界框b[4]是 track_id把它直接画在框上方回放时能直观看到同一目标是否从头到尾用同一个编号。合成速度不用太讲究用 25fps 输出即可因为回放还要调速看。我通常会把没有通过回放的视频段单独截出来重新导入数据标注工具用插值修正模式重跑一遍直到连续回放不再出现视觉跳跃。这个回放不过就重画的较真动作往往就是视频数据标注和图片标注团队拉开差距的地方。本文还有配套的精品资源点击获取
