CVAT Points 模式实战:面部关键点标注一次讲透(68 点)
【免费下载链接】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
先说任务:一张 AffectNet 风格的人脸图,要按顺序打 68 个关键点——眼角各 2 个、鼻孔 1 个、嘴角 1 个。矩形框表达不了"位置",多边形画起来又太浪费。CVAT 里专门有个工具解决这件事:Points 模式,也就是 CVAT 点集标注的专用入口。本文用这个真实任务带你看它怎么用,以及PointsShape/PointsTrack在前端核心库里的实现逻辑。
🎯 任务背景:不是"在脸上打点"这么简单
Points 模式在官方文档里定位就是人脸与 landmarks(关键点)标注。要标的对象是一组离散坐标,而不是一个区域。同样的逻辑也适用于身体姿态:比如下图中橄榄球运动员身上的各个关节点,每个点都没有"内部",姿态标注本质上就是"每个人身上固定 N 个点"。
CVAT 身体姿态关键点标注示例
这一点决定了它的交互特性:对象没有边界,所以选中、删除、微调全部以"单个点"为粒度。
快速上手:从选中工具到画完的最短路径
- 选工具:在左侧控制面板点
Points,弹出 "Draw new points" 对话框。 - 选标签:在 Label 选择器里挑一个标签。
- 设点数:在
Number of points输入框填数字(例如 68);留空则点数不限。 - 进入绘制:点
Shape按钮(单帧图形)或Track按钮(跨帧轨迹)。 - 落点与结束:在画布上依次点击落点;若第 3 步填了数字,落满即自动完成,留空则需再按一次
N或点顶部Done结束。
固定 68 个关键点怎么设
这个输入框与多边形、折线工具共用,取值会先被限制区间再向下取整,见 draw-shape-popover.tsx#L156-L199。其中minimumPoints是图形类型的最小点数,Points 为 1;填 68 之后,一旦落满第 68 个点绘制就自动停止,这就是"达到数量自动收尾"的来源。
交互行为深潜
一次落下的点为什么是一个整体
进入绘制模式后,从开始到结束点击的所有点会被自动归为一组,互相视为关联。所以一次绘制产生的是"一个点集对象",而不是 68 个孤立圆点——之后可以整体拖拽,右键菜单也作用在整个对象上。
删除单个控制点的两种方式
- 按住
Ctrl点击目标点; - 右键该点,在菜单中选
Delete point。
两种方式都只动这一个点,其余点不受影响。
给已有图形追加新点
按住Shift点击点集对象,会打开 points 编辑器,可以往已画好的图形里继续加点。绘制完成后,对象支持整体拖拽,也能单独拖动某个控制点微调位置。
绘制过程中怎么移动视野
滚轮缩放,按住鼠标中键拖动平移。绘制中的控制点半径会除以当前缩放比例,所以放大画布后圆点视觉大小保持稳定,高分辨率大图上也能精准落点。
🔍 内核透视:决定行为的三个判断
点集合法的下限是 1 个点
校验入口在 object-utils.ts#L25-L28:
} else if (shapeType === ShapeType.POINTS) { if (points.length / 2 < 1) { // 点集至少要有 1 个点 throw new DataError(`Points must have at least 1 points, but got ${points.length / 2}`); } }注意points存的是[x1, y1, x2, y2, …]扁平数组,长度除以 2 才是真实点数。PointsShape构造时会执行一次该校验,PointsTrack则对每个关键帧图形各查一次,0 个点的空集根本进不了数据模型。
命中检测:"没有面,只有点"
矩形和多边形靠"到边界的距离"判断命中,点集不同,见 points-shape.ts#L28-L38:
static distance(points: number[], x: number, y: number): number { const distances = []; for (let i = 0; i < points.length; i += 2) { const x1 = points[i]; const y1 = points[i + 1]; distances.push(Math.sqrt((x1 - x) ** 2 + (y1 - y) ** 2)); } return Math.min.apply(null, distances); }这段代码返回"鼠标位置到所有控制点的最小距离",意味着点击命中的永远是离得最近的那个点,而不是某片区域——这就是"删单点、微调单点"操作体验的直接来源。
自动收尾:numberOfPoints 在哪里生效
点绘制的入口是 drawPoints(),它创建一个透明的 SVG 容器承载后续各点;控制数量的关键行在 drawHandler.ts#L903:
let size = this.drawData.shapeType === 'cuboid' ? 4 : this.drawData.numberOfPoints;弹窗里填的数字被直接当作"本次绘制预期落点数",落满即自动完成绘制;留空时该值为空,绘制不会自动停,必须按N或Done手动结束。
🚂 轨迹与插值:为什么多点不插值
选Track时对象是PointsTrack,插值逻辑在 points-track.ts#L31-L52:
protected interpolatePosition(leftPosition, rightPosition, offset): InterpolatedPosition { // interpolate only when one point in both left and right positions if (leftPosition.points.length === 2 && rightPosition.points.length === 2) { return { points: leftPosition.points.map( (value, index) => value + (rightPosition.points[index] - value) * offset, ), // rotation / occluded / outside / zOrder 均继承左关键帧 }; } return { points: [...leftPosition.points], /* 其余字段同样继承左关键帧 */ }; }代码只在points.length === 2(即恰好存了一对 x、y)时做线性插值,也就是说只有左右关键帧都含 1 个点时才逐坐标按 offset 插值;多点点集直接复制左关键帧位置。源码没有注释原因,合理推测是:多点的线性插值要求两个点集严格一一对应,而真实画面里点数因遮挡、排序差异很容易对不上,硬插值容易得到错误中间态,保守做法是不插。
所以做单点线性插值的实操是:Number of points填 1 并选Track,在关键帧上移动点,CVAT 会自动填充中间帧。完整官方操作见 liner-interpolation-with-one-point.md。
📋 速查与文件索引
| 操作 | 触发方式 | 对应源码入口 |
|---|---|---|
| 固定点数,落满自动结束 | Number of points填数字 | draw-shape-popover.tsx#L156-L199 |
| 进入绘制 | 点Shape(单帧)/Track(轨迹) | draw-shape-popover.tsx#L200-L216 |
| 手动结束绘制 | 再按N,或点Done | drawHandler.ts#L903 |
| 删除单个控制点 | Ctrl+ 点击,或右键 →Delete point | points-shape.ts#L28-L38 |
| 追加 / 微调点 | Shift+ 点击打开编辑器;绘制后拖整体或单点 | drawHandler.ts#L1060-L1067 |
| 单点轨迹线性插值 | Number of points填 1 +Track | points-track.ts#L31-L52 |
参考文件清单(以仓库根目录为起点):
- 图形模型:points-shape.ts、points-track.ts
- 点数校验与命中:object-utils.ts#L12-L54
- 绘制处理器:drawHandler.ts#L1060-L1067
- 绘制弹窗:draw-shape-popover.tsx#L156-L216
- 操作文档:points-in-shape-mode.md、liner-interpolation-with-one-point.md
【免费下载链接】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),仅供参考