CVAT 椭圆(Ellipse)标注完整指南:两点绘制、旋转与底层数据模型解析
【免费下载链接】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 手工标注工具集中最常用的形状之一,主要用于道路标志(road sign)、圆形仪表盘、硬币、行星等近似圆形目标的框选。与矩形相比,椭圆能更贴合圆形物体的轮廓,减少标注框内的背景噪声。本文以仓库文档 annotation-with-ellipses.md 为主体,结合 cvat-canvas 与 cvat-core 的源码实现,完整讲解椭圆的绘制流程、旋转操作、完成方式及其底层数据模型,让你既能快速上手操作,也能理解椭圆标注在引擎层的真实工作原理。
椭圆标注的典型应用场景
椭圆(Ellipse)形状在 CVAT 中属于基础形状之一,文档明确指出它的典型用途是道路标志(road sign)标注。道路标志大多为圆形,使用椭圆可以:
- 用最少的点精确覆盖圆形目标,标注结果更贴近真实轮廓;
- 后续可通过旋转适配倾斜拍摄的圆形标志(例如从侧面拍摄的限速牌);
- 与矩形、多边形等形状共同构成混合标注方案,见 types-of-shapes.md。
绘制前的准备:选择工具与配置弹窗
开始标注前,首先在**左侧控件侧边栏(controls sidebar)**中点击Ellipse按钮。该按钮在前端由 draw-ellipse-control.tsx 组件实现:它使用EllipseIcon图标渲染,点击后通过DrawShapePopoverContainer弹出 "Draw new ellipse" 配置窗口,并挂载CVATTooltip(提示语 "Draw an ellipse")以及激活态样式cvat-active-canvas-control。
在弹窗中需要完成两项配置:
| 配置项 | 说明 |
|---|---|
Label | 选择标注标签。标签是在创建任务(task)时预先定义的类别,例如 "sign"(见上图弹窗中的示例); |
Shape或Track | 选择标注模式:Shape创建独立的静态形状(适用于单帧物体),Track创建跨帧跟踪的轨迹(适用于视频中持续出现的物体)。两种模式的基础操作可分别参考 shape-mode-basics.md 与 track-mode-basics.md。 |
两点法绘制:椭圆内接于虚拟矩形
选择好Label并点击Shape或Track后即进入绘制模式。椭圆的创建方式与 矩形(rectangle) 完全一致:只需指定两个对角点,椭圆就会被"内接"在由这两个点构成的虚拟矩形中——即椭圆的水平半径等于矩形宽度的一半,垂直半径等于矩形高度的一半。
从源码层面看,这一交互由 drawHandler.ts 中的drawEllipse()方法实现:
- 创建 SVG 椭圆实例:
(this.canvas as any).ellipse(),并设置描边宽度、填充透明度等绘制态样式; - 监听
mousedown.draw:第一次左键点击记录初始点initialPoint(通过translateToSVG将屏幕坐标换算为 SVG 坐标);第二次左键点击触发drawstop完成绘制(前提是未按住Alt键); - 监听
mousemove.draw:实时根据鼠标位置计算rx = |x - initialPoint.x| / 2、ry = |y - initialPoint.y| / 2,再结合符号函数计算圆心cx、cy,调用center()与radius()实时预览椭圆; drawstop时通过getFinalEllipseCoordinates()规整坐标,最后经checkConstraint('ellipse', points)校验后提交。
getFinalEllipseCoordinates()(drawHandler.ts)返回的坐标格式为[cx, cy, rightX, topY]——即圆心坐标加上椭圆最右点 X 与最上点 Y,这是 CVAT 椭圆在内部的标准存储格式。
rx = rightX - cx # 水平半径 ry = cy - topY # 垂直半径尺寸下限校验
checkConstraint('ellipse', ...)会拒绝过小的误操作椭圆,其校验规则见 drawHandler.ts:
if (shapeType === 'ellipse') { const [width, height] = [(points[2] - points[0]) * 2, (points[1] - points[3]) * 2]; return width >= consts.SIZE_THRESHOLD && height > consts.SIZE_THRESHOLD; }其中SIZE_THRESHOLD在 consts.ts 中定义为1,即宽、高均需达到至少 1 个像素单位,防止产生退化椭圆。
十字辅助线(Crosshair)
为提升定位精度,CVAT 为矩形、立方体、椭圆这三种"框选型"形状启用了十字辅助线(crosshair)。相关逻辑见 annotation-actions.ts 与 draw-shape-popover.tsx:当活动形状类型属于[RECTANGLE, CUBOID, ELLIPSE]时,绘制过程中会显示十字线辅助对齐。
完成椭圆:N 键与 Done 按钮
绘制完成后,按键盘N键,或点击顶部面板(top panel)的Done按钮即可完成并提交该形状。此外如前文所述,在画布上再次左键点击同样会触发drawstop完成绘制。绘制期间按Esc可取消。
提示:
Done按钮与完成类快捷键的显隐由 left-group.tsx 中的finishDrawAvailable()控制,其判定逻辑见 drawing.ts,主要面向多边形、折线、点等需要多段点击的形状;椭圆由于天然是"两点击成",画布内二次点击即为最直接的完成方式。
旋转椭圆:旋转点、中心旋转与 15° 吸附
椭圆绘制完成后同样支持旋转,操作方式与矩形完全一致(参见 annotation-with-rectangles.md#rotation-rectangle):
- 拖拽旋转点:选中椭圆后,其外侧会显示一个旋转点(rotation point),按住并拖动即可绕椭圆中心旋转;
- 角度吸附:按住
Shift再旋转,旋转角度会吸附到 15° 的整数倍,便于对齐水平/垂直方向的标志物; - 角度实时显示:旋转过程中可看到当前角度数值。
源码侧,旋转能力在 canvasView.ts 中统一开启:
rotationPoint: shape.type === 'rect' || shape.type === 'ellipse',即矩形与椭圆是仅有的两类带旋转点的形状。椭圆的实际渲染也充分考虑了旋转角,见 canvasView.ts:
ctx.ellipse(cx, cy, rightX - cx, cy - topY, (state.rotation * Math.PI) / 180.0, 0, 2 * Math.PI);旋转角以度为单位存储,渲染时转换为弧度,并绕圆心绘制完整椭圆。选中椭圆时,右上角的尺寸提示(ShapeSizeElement)会同时显示宽、高与旋转角度,实现见 shared.ts:对rect与ellipse类型调用getRoundedRotation()读取当前旋转角(结果保留 5 位小数以规避浮点误差),再通过composeShapeDimensions()拼装尺寸文本。
椭圆的数据模型与底层原理
要理解椭圆标注的存储与交互,需要了解 cvat-core 中的两个核心类。
坐标约定与合法性校验
椭圆在数据层由 4 个浮点数描述:[cx, cy, rightX, topY]。创建 EllipseShape 实例时,构造函数会调用checkNumberOfPoints(ShapeType.ELLIPSE, points)进行校验,规则见 object-utils.ts:
} else if (shapeType === ShapeType.ELLIPSE) { if (points.length / 2 !== 2) { throw new DataError(`Ellipse must have 1 point, rx and ry but got ${points.toString()}`); } }即椭圆必须恰好包含 2 个二维点(共 4 个坐标值),否则视为非法数据直接抛错。
命中检测:点到椭圆的距离
EllipseShape类中实现了一个静态方法distance(points, x, y, angle)(ellipse-shape.ts),用于判断鼠标光标是否位于椭圆内部并计算距离,其数学原理是标准椭圆方程:
(x - cx)² / rx² + (y - cy)² / ry² ≤ 1算法流程为:先将光标坐标按椭圆旋转角反向旋转(rotatePoint,见 object-utils.ts),判断点是否在椭圆内;若在内部,再通过该点引水平、垂直两条线与椭圆边界求交,取到边界的最小距离作为结果。这套命中检测保证了在旋转后的椭圆上依然能精确选中、拖拽和调整。
轨迹(Track)模式下的插值
当以Track模式创建椭圆时,对应类为 EllipseTrack。除了逐帧校验点数外,它重写了interpolatePosition(),在关键帧之间线性插值椭圆的位置(圆心与半径)与旋转角:
rotation: (leftPosition.rotation + findAngleDiff( rightPosition.rotation, leftPosition.rotation, ) * offset + 360) % 360,旋转角插值通过findAngleDiff处理角度环绕问题(如 350° 到 10° 不会绕大圈),并将结果归一到[0, 360)区间,保证视频跟踪过程中椭圆旋转平滑连续。
实用技巧小结
- 快速切换:椭圆标注适合批量标注圆形目标,绘制期间配合十字线(crosshair)可更精确地对准圆心;
- 撤销与重做:绘制或调整椭圆后可随时使用
Ctrl+Z撤销、Shift+Ctrl+Z或Ctrl+Y重做; - 遮挡标注:若目标被其他物体部分遮挡,可在对象侧边栏将其标记为Occluded(快捷键
Q); - 锁定对象:帧内形状过多时可按
L锁定已标注对象,避免误操作; - 尺寸校验:椭圆最小宽高阈值为 1 像素(
SIZE_THRESHOLD),过小的误点击不会被保存。
相关文档导航
- 矩形标注(含旋转详解)
- Shape 模式基础
- Track 模式基础
- 形状类型总览
原文档还提供了配套的椭圆标注视频教程(内嵌于 annotation-with-ellipses.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),仅供参考