CVAT 画笔工具(Brush Tool)完全指南:从手绘 Mask 到多边形转换的像素级标注实战
CVAT 画笔工具Brush Tool完全指南从手绘 Mask 到多边形转换的像素级标注实战【免费下载链接】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/cvatBrush Tool 是 CVAT 中用于创建和编辑分割掩码Mask的核心标注工具专门解决房屋被树木遮挡、车辆被行人遮挡、交通标志被立柱遮挡等不连续、多部件对象的像素级标注需求。本文基于 CVAT 官方文档与 masksHandler.ts 源码实现系统讲解画笔工具菜单的每个控件、手绘与多边形转掩码两种标注流程、底层像素删除机制以及 AI 工具与数据集导入导出中的掩码转换能力帮助你完整掌握 Semantic/Panoptic 与 Instance 分割任务的标注工作流。适用场景什么时候该用 Brush ToolBrush Tool 专为**分割掩码Segmentation Mask**标注而设计。当标注对象具有以下特征时它是比普通多边形更合适的选择对象由多个不相连的部件组成例如隐藏在树后的房子、行人身后的汽车、交通标志后面的立柱——掩码天然支持一个对象由多个分离区域组成无需为每个部件单独建对象对象边界高度不规则如毛发、树叶、破损边缘等难以用直线或贝塞尔曲线逼近的轮廓需要精细到像素级的编辑掩码可以在绘制完成后继续用画笔增补、用橡皮擦擦除实现逐像素修正。从 masksHandler.ts 的实现看CVAT 的掩码标注支持三种工作模式draw绘制新掩码、edit编辑已有掩码和isInsertion粘贴已有掩码其核心数据结构BrushTool定义了画笔的全部形态参数见 canvasModel.tsexport interface BrushTool { type: brush | eraser | polygon-plus | polygon-minus; color: string; form: circle | square; size: number; onBlockUpdated: (blockedTools: Recorderaser | polygon-minus, boolean) void; }Brush Tool 适用于SemanticPanoptic分割与Instance 分割两类任务。关于分割掩码在 CVAT 中的更多概念可参阅 Creating masks 文档。本文接下来将按以下路径展开Brush 工具菜单详解使用画笔标注掩码多边形转掩码标注删除底层像素AI 工具掩码转多边形导入与导出Brush 工具菜单详解在左侧 controls sidebar 选择Brush工具然后在图像上点击Shape屏幕顶部即出现 Brush 工具菜单菜单包含以下控件元素说明保存掩码保存创建的掩码保存后对象会出现在 objects sidebar 中。保存掩码并继续将当前掩码添加到对象侧边栏并允许立即绘制下一个新掩码适合连续批量标注。画笔Brush向当前掩码添加新区域/像素是绘制掩码的默认工具。橡皮擦Eraser擦除掩码的一部分像素。多边形Polygon多边形选择工具选中区域将转换为掩码。移除多边形选择从多边形选择中减去一部分区域。画笔大小Brush size以像素为单位的画笔直径。注意仅在选中画笔或橡皮擦时显示。画笔形状Brush shape画笔形状可选圆形circle和方形square。注意仅在选中画笔或橡皮擦时显示。删除底层像素Remove underlying pixels在绘制或编辑掩码时当前掩码像素位置对应的其他掩码像素会被同时删除。隐藏掩码Hide mask绘制或编辑掩码时可临时隐藏当前掩码更清晰地看到下方对象。标签Label为新建掩码分配的标签。移动Move按住并拖动可将菜单栏移动到屏幕其他位置。从源码实现看画笔的size、form等参数直接驱动底层渲染逻辑。在 masksHandler.ts 中画笔标记brush marker会根据形状创建对应图形this.brushMarker this.tool.form circle ? new fabric.Circle({ ...common, radius: Math.round(this.tool.size / 2), }) : new fabric.Rect({ ...common, width: this.tool.size, height: this.tool.size, });即圆形画笔半径为size / 2方形画笔边长等于size这与菜单中画笔大小像素的语义完全一致。快捷键实时调整画笔大小除了在菜单中调整画笔大小还可以在绘制过程中直接通过快捷键微调按住Alt 键 鼠标右键并左右拖动鼠标画笔大小会实时增减。在 masksHandler.ts 中isBrushSizeChanging状态下通过xDiff鼠标水平位移更新画笔尺寸且最小值被钳制为 1 像素onUpdateConfiguration({ brushTool: { size: Math.trunc(Math.max(1, this.tool.size xDiff)), }, });这一交互设计让你无需中断绘制即可快速切换粗细适合先大面积铺色再精细描边的两段式标注。使用画笔标注掩码手绘掩码是最直接的标注方式操作步骤如下从 controls sidebar 中选择Brush工具。在弹出的Draw new mask菜单中为掩码选择标签然后点击Shape。此时Brush工具默认处于选中状态。使用画笔在要标注的对象上绘制掩码需要修正时切换到Eraser擦除。掩码绘制完成后点击顶部菜单栏的Save mask或按键盘N键结束流程。添加的对象会出现在 objects sidebar 中。添加下一个对象时重复步骤 1 至 5。所有已添加对象都会同时显示在图像和对象侧边栏中。完成整个任务的所有标注后点击顶部菜单的Save保存该 job。掩码的底层存储RLE 编码手绘掩码并非以位图形式直接存储而是被转换为行程长度编码RLE。从 shared.ts 可以看到转换过程——绘制结束时会截取掩码包围盒内的像素数据imageDataFromCanvas按像素行的 alpha 通道逐段压缩export function imageDataToRLE(imageData: Uint8ClampedArray): number[] { const rle []; let prev 0; let summ 0; for (let i 3; i imageData.length; i 4) { const alpha imageData[i] 0 ? 1 : 0; if (prev ! alpha) { rle.push(summ); prev alpha; summ 1; } else { summ; } } rle.push(summ); return rle; }在 masksHandler.ts 中绘制结束时 RLE 数据会连同掩码的包围盒left, top, right, bottom一起通过onDrawDone回调交给上层最终作为掩码对象的points字段持久化。这也是 CVAT 掩码对象在数据集导出时体积紧凑、易于传输的原因。反之编辑已有掩码时则通过RLEToImageData将 RLE 还原为位图进行像素级操作shared.ts。绘制过程中的撤销与重做绘制或编辑掩码过程中每一笔按下鼠标到松开都会被记录为一个历史动作history action支持CtrlZ 撤销与CtrlY/CtrlShiftZ 重做。在 masksHandler.ts 中private startHistoryAction(): void { this.activeHistoryAction []; } private addToHistoryAction(object: DrawnObject): void { this.activeHistoryAction?.push(object); } private finishHistoryAction(): void { if (this.activeHistoryAction?.length) { this.undoStack.push(this.activeHistoryAction); this.redoStack []; } this.activeHistoryAction null; }鼠标按下时开启一个历史动作移动绘制时不断向其中追加图形对象鼠标松开时mouseup事件结束并压入撤销栈undo()从栈中弹出并移除对应图形redo()则反向恢复masksHandler.ts。多边形转掩码标注当对象轮廓较为规整、用多边形描边更高效时可以使用polygon-to-mask模式先用多边形工具勾勒再将其转换为掩码。操作步骤如下从 controls sidebar 中选择Brush工具。在Draw new mask菜单中为掩码选择标签然后点击Shape。在 Brush 工具菜单中选择Polygon。使用Polygon工具为要标注的对象绘制掩码选区需要修正时使用Remove polygon selection减去错误区域。点击Save mask或按N键在添加/移除多边形工具之间切换反复修正选区多边形选区确认后点击顶部菜单栏的Save mask或按N键完成流程。再次点击Save mask或按N键添加的对象即出现在 objects sidebar 中。添加下一个对象时重复步骤 1 至 5。最后点击顶部菜单的Save保存整个 job。多边形与画笔的切换原理在源码中多边形转掩码实际上复用了一个独立的矢量绘制处理器DrawHandler。当工具类型以polygon-开头时masksHandler.ts 会切换到矢量绘制管线if (this.tool?.type?.startsWith(polygon-)) { this.isPolygonDrawing true; this.vectorDrawHandler.draw({ enabled: true, shapeType: polygon, onDrawDone: (data: { points: number[] } | null) { // 将多边形顶点转为 fabric.Polygon const polygon new fabric.Polygon(points, { fill: color.toRgba(), selectable: false, objectCaching: false, absolutePositioned: true, globalCompositeOperation: this.tool.type polygon-minus ? destination-out : xor, }); ... }, }, this.geometry); }关键差异在于合成方式globalCompositeOperationpolygon-plus添加多边形使用xor合成新增区域与已有掩码进行异或叠加polygon-minus移除多边形使用destination-out合成从已有掩码中挖去选区。同理画笔与橡皮擦也遵循同一套像素合成逻辑masksHandler.ts画笔以 50% 透明度xor叠加橡皮擦则以destination-out方式将对应像素 alpha 置零。这意味着在最终落盘前所有操作都发生在独立的掩码绘制画布上保存时统一转换回 RLE从而支持橡皮擦、移除多边形与画笔之间的任意组合与反复修正。工具可用性守卫为防止误操作CVAT 在绘制管线中内置了工具阻塞机制onBlockUpdated。当掩码尚未有任何有效像素时橡皮擦和移除多边形会被禁用——因为它们没有可擦除/可减去的对象masksHandler.tsprivate updateBlockedTools(): void { if (this.drawnObjects.length 0) { this.tool.onBlockUpdated({ eraser: true, polygon-minus: true }); return; } // 通过 RLE 判断当前掩码是否为空 const rle imageDataToRLE(imageData); const isEmptyMask rle.length 2; this.tool.onBlockUpdated({ eraser: isEmptyMask, polygon-minus: isEmptyMask, }); }掩码的隐藏与查看在处理多层遮挡对象时隐藏掩码功能非常实用。开启后当前正在绘制或编辑的掩码会被临时隐藏画布透明度置为 0露出被其覆盖的下层对象便于看清边界后再继续绘制。源码中通过updateHidden实现masksHandler.ts隐藏期间画笔光标恢复为系统默认样式且鼠标移动不会触发绘制masksHandler.ts 中!this.isHidden条件避免盲画。删除底层像素Remove underlying pixels删除底层像素用于边画边删当你正在绘制或编辑某个掩码时开启此功能后当前掩码像素所在位置上的其他掩码像素会被自动删除。该功能最大的价值在于两个相邻对象的交界处无需反复精修两次边缘。例如为道路两侧的绿化带与路面分别建掩码时只要先完成一个掩码再在删除底层像素开启的状态下绘制另一个交界处就能自动对齐避免白色缝隙或重叠像素大幅提升标注效率与掩码质量。AI 工具掩码转多边形Brush Tool 与 CVAT 的 AI Tools 联动可以将 AI 工具生成的掩码转换为多边形从而获得可直接编辑顶点、更适合后续人工精修的矢量轮廓具体操作打开 AI 工具面板进入Detectors选项卡。将Masks to polygons开关切换到右侧开启。从下拉列表中选择源标签source label和目标标签destination label。点击Annotate运行。执行后AI 模型输出的掩码会先被提取轮廓再转换为多边形对象落盘。在 tools-control.tsx 中可以找到对应的轮廓提取实现它通过 OpenCV 封装openCVWrapper.getContoursFromStateSync从掩码 RLE 数据中计算轮廓点集并校验掩码像素数不少于 6 个才继续处理。这条调用链同样服务于AI 工具交互结果转形状receiveContoursFromMask说明掩码与多边形两种表示在 CVAT 内部可以互相转换这为后续数据集导出提供了格式灵活性。导入与导出导出掩码标注的导出遵循通用的 Export dataset 流程。选择目标格式后掩码会按各格式规范序列化输出如前文所述掩码以 RLE 包围盒形式存储导出时由后端还原为对应格式的掩码数据。导入掩码转多边形导入遵循通用的 Import dataset 流程并额外提供一个**掩码转多边形Convert masks to polygons**选项上传数据集时将Convert masks to polygons开关切换到右侧即可启用。注意该选项仅适用于只支持掩码masks only的格式。如果导入格式本身原生支持多边形如 COCO、Segmentation Mask 1.1 等则无需此转换。该开关的提示文案与实现均可从导入对话框源码得到印证import-dataset-modal.tsxSpace classNamecvat-modal-import-switch-conv-mask-to-poly-container ... Text strongConvert masks to polygons/Text CVATTooltip titleThe option is relevant for formats that work with masks only /Space选择该选项后导入的掩码数据会先转换为多边形再入库使原本只能以掩码形式存储的格式也能在 CVAT 中获得可编辑的多边形对象与上文 AI 工具的掩码转多边形能力形成闭环。小结Brush Tool 是 CVAT 处理分割任务的核心工具其能力可概括为三条主线绘制方式灵活纯手绘画笔/橡皮擦适合不规则对象多边形转掩码适合规整对象且两者在底层统一为像素级合成xor/destination-out并最终以 RLE 编码存储masksHandler.ts、shared.ts编辑手段完备支持撤销/重做、实时调整画笔大小、隐藏掩码查看下层对象、删除底层像素自动对齐相邻对象边界格式转换顺畅AI 工具生成的掩码可转多边形tools-control.tsx数据集导入时也提供掩码转多边形选项import-dataset-modal.tsx。掌握了上述菜单、快捷键与底层原理你就能在 Semantic/Panoptic 与 Instance 分割任务中针对多部件、不规则边界对象高效产出高质量的像素级标注。【免费下载链接】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),仅供参考