ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

CVAT Track 模式实战:从关键帧标注到轨迹插值、合并与拆分的全流程指南

CVAT Track 模式实战:从关键帧标注到轨迹插值、合并与拆分的全流程指南 CVAT Track 模式实战从关键帧标注到轨迹插值、合并与拆分的全流程指南【免费下载链接】cvatComputer Vision Annotation Tool (CVAT) is a leading platform for building high-quality visual datasets for vision AI. It offers open-source, cloud, and enterprise products, as well as labeling services, for image, video, and 3D annotation with AI-assisted labeling, quality assurance, team collaboration, analytics, and developer APIs.项目地址: https://gitcode.com/GitHub_Trending/cvat/cvat本文基于 CVAT 官方文档Track mode页面site/content/en/docs/annotation/manual-annotation/modes/track-mode-basics.md编写系统讲解视频序列标注中 Track 模式的核心工作流如何用关键帧 自动插值的思路高效标注移动目标、如何用 Outside Property 结束轨迹、如何用 Merge/Split 重组轨迹并结合 CVAT 源码库中的 Track 对象、矩形轨迹插值、合并处理器 与 拆分处理器还原每个界面操作背后的数据模型与插值算法。一、Track 模式解决什么问题Track轨迹模式面向同一目标在多帧中持续存在的标注场景。相比逐帧绘制Interpolation/Shape 模式下的逐帧操作Track 模式允许标注员只在目标发生显著变化的帧上手动绘制/修正其余帧由系统自动推算。官方文档给出的典型使用场景有三类为一整段帧序列创建新的标注对已有标注中的对象进行增、改、删编辑轨迹修正轨迹、把多个矩形合并为一条轨迹。在 CVAT 的任务类型体系中这与后端的Task.Mode.INTERPOLATION interpolation任务模式相呼应见 cvat/apps/engine/models.py即任务允许对轨迹做跨帧插值。二、第一步选择矩形、标签与绘制方式与 Shape 模式的入口相同在 Track 模式下在侧边栏选择Rectangle矩形等图形在弹出的表单中选择合适的Label标签选择Drawing method绘制方式这里要选择Track。选择Track作为绘制方式后你画出的矩形不再是单帧形状而是一条轨迹的起始关键帧。此时 CVAT 会在内部为它创建一个Track对象——从 track.ts 的类定义可以看到Track的核心数据是一个shapes: Recordnumber, TrackedShape字典以帧号为键、以该帧的几何状态点集、旋转、outside、occluded、z_order 等为值。只有手动确认过的帧才会出现在这个字典里这些帧就是关键帧keyframe。三、创建轨迹与关键帧只标变化的帧官方示例以一辆车cyclist/car为例说明完整节奏创建初始关键帧在 Track 模式下画出第一个Rectangle它成为轨迹的第一个关键帧。此后矩形会在后续帧上被自动插值显示。把对象开始运动的帧标记为关键帧例如目标从第 2270 帧开始移动就在此帧按下快捷键K或点击 Objects 侧边栏的星标按钮将该帧固化为关键帧。在位置变化处修正矩形当对象开始位移/形变时只需在变化发生的那一帧修改矩形不必逐帧修改——更新若干关键帧后中间帧会自动插值。跳帧微调例如向前跳 30 帧到第 2300 帧再调整一次边界之后第 22702300 帧之间的矩形会自动、平滑地过渡变化。3.1 插值算法的源码级解释中间帧自动过渡由 track.ts 中的boundedKeyframes()与getPosition()协同完成boundedKeyframes(targetFrame)遍历轨迹所有关键帧跳过已删除帧找出目标帧左侧最近的关键帧prev、右侧最近的关键帧next以及整条轨迹的first/lastgetPosition()L551-L582取出左右两个关键帧后计算插值偏移量offset (targetFrame - leftFrame) / (rightFrame - leftFrame)再调用具体图形类的interpolatePosition(left, right, offset)得到当前帧几何。以矩形轨迹为例rectangle-track.ts 的实现是protected interpolatePosition(leftPosition, rightPosition, offset): InterpolatedPosition { const positionOffset leftPosition.points.map((point, index) rightPosition.points[index] - point); return { points: leftPosition.points.map((point, index) point positionOffset[index] * offset), rotation: (leftPosition.rotation findAngleDiff( rightPosition.rotation, leftPosition.rotation, ) * offset 360) % 360, occluded: leftPosition.occluded, outside: leftPosition.outside, zOrder: leftPosition.zOrder, }; }可以看出两点细节矩形以及椭圆、多边形等参见同目录下ellipse-track.ts、poly-track.ts、polygon-track.ts采用逐坐标线性插值每个顶点按帧间比例在两关键帧之间线性移动旋转角则走最短角度差findAngleDiff插值避免 350°→10° 时倒着转一圈occluded、outside、zOrder等状态属性不参与插值直接继承自左关键帧——所以这些状态需要你在关键帧上显式确认。另外目标帧超出两端关键帧范围时prev或next为nullgetPosition()直接返回单端位置左端之前完全复制左关键帧右端之后复制右关键帧并置outside: true两端都没有关键帧时才抛出InterpolationNotPossibleError。3.2 关键帧与 Outside 属性在数据层的落点按K触发的是 track.ts 的saveKeyframe(frame, keyframe)把当前帧的几何状态含插值后的points拷贝进this.shapes字典取消关键帧则直接从字典中删除该帧。这正是字典里有的帧才是关键帧这一设计的具体实现按下OOutside Property对应 track.ts 的saveOutside(frame, outside)把该帧关键帧的outside标记为true表示对象已移出画面/不再存在。官方文档建议当标注对象消失或小到无法可靠框定时用 Outside Property 结束轨迹。注意Outside 只是给该关键帧打标记轨迹本身的边界由首末关键帧决定是否需要在此后终止标注取决于你的数据集规范。四、Merge把多段轨迹合并为一条如果目标在若干帧内被遮挡、不可见随后又重新出现常见做法是先把可见区间分别标成多条独立轨迹再用Merge功能合并为对象可见的区间分别创建轨迹选中Merge按钮或按M然后在第一条轨迹的任意矩形、第二条轨迹的任意矩形……上逐一点击再次选中Merge按钮或按M应用变更。4.1 合并的约束条件源码验证合并行为由 mergeHandler.ts 中的MergeHandlerImpl控制其中有两个容易被忽视的硬性约束同类约束点击的第一个对象会建立约束{ labelID, shapeType }addConstraintsL30-L36之后所有候选对象必须与第一个对象标签相同、图形类型相同才能被选中checkConstraintsL42-L47同帧互斥select()中通过stateFrames.includes(objectState.frame)拒绝选择与已选对象处于同一帧的形状L127保证合并后每帧至多一个关键帧Mask 不可合并select()开头直接对shapeType mask提前返回L107-L109。点击次数 ≥ 2 时才会真正提交合并closeMerging()中statesToBeMerged.length 1的分支L67-L81。合并完成后最终序列在回放时由插值引擎在两段关键帧之间平滑过渡五、Split把一条轨迹拆成两条当一条轨迹中混入了不该属于该目标的一段或需要把目标拆成两个实体时用Split功能选中 Split 按钮后点击轨迹上任意矩形即可在该帧处把一条轨迹一分为二。从源码看splitHandler.ts 的SplitHandlerImpl只在objectType track时响应选中L84-L101——Split 仅对轨迹对象有效且整个交互是高亮跟随鼠标 → 单击确定切分位置的两步流程。六、轨迹专属的导航按钮在 Track 模式下创建的图形带有额外的导航按钮帮助你在关键帧之间快速跳转Previous / Next跳到当前轨迹的上一个/下一个关键帧Initial frame / Last frame跳到轨迹的首个关键帧和最后一个关键帧。这与boundedKeyframes()返回的first/last/prev/next一一对应track.ts界面按钮本质上是把这四个值包装成了可点击的跳转目标。七、一条轨迹最终长什么样序列化视角理解数据落盘结构有助于排查为什么插值结果不是我想要的。track.ts 的toJSON()把轨迹导出为如下结构节选并注释const result: SerializedTrack { clientID: this.clientID, label_id: this.label.id, frame: this.frame, group: this.group, source: this.source, // 标注来源手动/AI 等 attributes: /* 不可变属性mutablefalse整条轨迹共享 */, elements: [], shapes: [ /* 每个关键帧一项 { type: rectangle, // 图形类型 occluded, z_order, rotation, outside, // 该关键帧的 Outside 标记 attributes: /* 该帧的可变属性mutabletrue */, frame, // 关键帧帧号 points: [...] // 矩形/多边形等点集 } */ ], };两个值得注意的设计属性分两层标签定义为不可变的属性放在轨迹级attributes随帧变化的属性放在每个关键帧的attributes里读取某帧属性时getAttributes()L160-L180采用不可变属性全量继承 可变属性取 ≤ 目标帧的最近关键帧值的向下继承策略只存关键帧shapes数组里只有手动确认过的帧插值出的中间帧并不入库——这解释了为什么文档反复强调只需修正关键帧。八、操作小结与注意事项操作界面入口快捷键源码落点绘制 Track 方式矩形侧边栏 Rectangle → Drawing method: Track—Drawn创建流程设为/取消关键帧Objects 侧边栏星标按钮KsaveKeyframeOutside PropertyObjects 侧边栏 Outside 按钮OsaveOutside合并轨迹Merge 按钮MmergeHandler.ts拆分轨迹Split 按钮仅对 track 生效—splitHandler.ts关键帧跳转Previous/Next、Initial/Last 按钮—boundedKeyframes最后提醒三条实操边界其一插值只在两个关键帧之间进行越界帧直接复制单端关键帧因此轨迹起点之前、终点之后的画面表现由首末关键帧的outside状态决定其二Merge 要求所有被合并对象标签与图形类型一致且同一帧内不能同时选中两个对象其三所有对几何、属性的修改都会写入对象的历史栈history.do见 track.ts因此关键帧、Outside、合并等操作均支持撤销/重做标注过程中可以放心试错。【免费下载链接】cvatComputer Vision Annotation Tool (CVAT) is a leading platform for building high-quality visual datasets for vision AI. It offers open-source, cloud, and enterprise products, as well as labeling services, for image, video, and 3D annotation with AI-assisted labeling, quality assurance, team collaboration, analytics, and developer APIs.项目地址: https://gitcode.com/GitHub_Trending/cvat/cvat创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表