ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

CVAT + YOLOv5 自动标注全流程:从 Nuclio 部署到模型优化

CVAT + YOLOv5 自动标注全流程:从 Nuclio 部署到模型优化 做目标检测的朋友应该都体会过人工标注的痛一张图几十个框框到天昏地暗眼睛酸疼不说标出来的质量还不稳定。我前段时间为了给一批工业零件图片做标注把 CVAT 这套自动标注流程整个跑了一遍从 nuctl 安装到 YOLOv5 模型部署前后折腾了两三天中间踩了不少坑。今天把完整的流程和避坑要点整理出来给准备上 CVAT 自动标注的朋友做个参考。CVAT 是目前开源界很能打的视觉标注工具界面清爽、支持多人协作最关键的是它的自动标注机制做得很完整。搭配 Nuclio 这个 Serverless 平台和 YOLOv5 模型就可以实现“模型先框一遍人工只修错漏”的半自动标注模式。对于有几千几万张图要标、又不想全靠人力的团队来说这套方案非常实用。适合已经跑通过 YOLOv5 训练流程、想进一步提升标注效率的开发者阅读。1. 先理清这套自动标注方案的整体链路1.1 CVAT、Nuclio、nuctl、YOLOv5 各自扮演什么角色很多人在这一套环境里绕晕是因为分不清这几个组件的关系。简单来说CVAT 是你看到的网页界面负责项目管理、任务分配、标注展示Nuclio 是一个无服务器计算平台跑在 Docker 里专门执行推理函数nuctl 是 Nuclio 的命令行工具用来部署和管理这些函数而 YOLOv5 模型则作为推理函数的核心负责真正输出检测框。用生活化的比喻来讲CVAT 是餐厅前台Nuclio 是后厨nuctl 是传菜员手里的对讲机YOLOv5 是厨师本厨。你在 CVAT 界面点一下“自动标注”后台就把图片打包送到 NuclioNuclio 调用 YOLOv5 模型推理把每个目标的坐标和类别返回给 CVAT最后在界面上生成标注框。理解了这个链路后面部署排错的思路就清晰了。1.2 为什么推荐“CVAT YOLOv5”这套组合我不是说别的标注工具不好但 CVAT 这套组合有几个非常核心的优势。第一它完全开源免费数据都在自己服务器上不牵扯上传第三方平台这对很多有数据保密要求的项目来说很重要。第二CVAT 不止支持自动标注它本身就是一个完整的标注平台从数据上传、多人协同标注、质量检查到数据集导出一条龙都齐了。第三YOLOv5 生态成熟、权重文件好拿部署起来门槛相对低。当然这套组合也不是没有代价。最大的问题就是部署链路长中间任何一个环节版本不匹配都会让你卡住半天。我自己就在 nuctl 安装和模型注册这两个环节折腾了很久。所以这篇文章会把每一步操作和容易踩的坑都写清楚尤其是那些官方文档里含糊带过的地方。2. 环境准备与 CVAT 安装先把坑埋在前面2.1 安装 Docker 和 Docker Compose 的版本要求CVAT 的部署方式很统一就是 Docker Compose 一把梭。所以第一步其实是把 Docker 环境收拾利索这里反而有不少细节值得注意。CVAT 官方建议 Docker Engine 版本在 19.03 以上Docker Compose 版本用 V2 格式。如果你的系统自带的是老版本 Compose后面执行docker compose up的时候可能会报“unsupported config option for services”之类的错误识别方法很简单命令能正常执行基本就没问题。安装基础环境之后强烈建议顺手建立一个普通用户并加入 docker 组别全程用 root 操作。用 root 部署 CVAT 虽然能跑起来但后面创建的一些数据目录、模型缓存目录权限都会挂在 root 下等你想用普通用户去读、去清理的时候各种 Permission denied 会把人逼疯。我一开始图省事用 root 部署后面上传模型权重的时候吃了不少苦头后来全部删掉重来一遍才算清净。2.2 用 Docker Compose 部署 CVAT 并创建管理员账号代码拉取和启动的过程本身不复杂但有几个关键点要提醒。先要把 CVAT 仓库克隆下来然后切到目标版本的分支。这里有一个很多人忽略的细节CVAT 的主分支跟最新的 Nuclio 函数模板可能不完全兼容稳妥的做法是直接使用最新的 release 分支。git clone https://github.com/cvat-ai/cvat.git cd cvat docker compose --profile nuclio up -d注意--profile nuclio这个参数它非常关键没有它的话Nuclio 平台不会被启动后面你想注册模型函数的时候根本找不到目标。这也是我第一次部署时被卡住的地方CVAT 界面能打开但自动标注按钮形同虚设查了半天才发现是 Nuclio 压根没跑起来。启动完成后创建管理员账号docker exec -it cvat_server bash -c python3 manage.py createsuperuser按提示输入用户名、邮箱、密码。等这一步完成打开http://localhost:8080用刚创建的管理员账号登录CVAT 的主界面就出来了。如果你的机器还装了其他东西8080 端口可能被占可以在.env文件里改端口映射或者先docker ps查一下端口占用情况再处理。环境这部分给一个硬指标建议机器内存不低于 16GB。CVAT 本身不算重但 Nuclio 加推理函数跑起来之后内存占用会明显上涨8GB 内存的机器很可能在推理高峰期被系统 OOM 杀掉容器。如果条件达不到至少要保证有足够的 swap 空间兜底。3. nuctl 安装与 Nuclio 配置自动标注的心脏3.1 nuctl 的两种安装方式Nuclio 这套平台提供命令行工具 nuctl用来从终端部署和管理函数。安装方式有两种一种是直接跑安装脚本另一种是去 Nuclio 的 GitHub Releases 页面下载对应平台的二进制。我这边的环境是 Linux x86_64直接用脚本方式安装curl -s https://nuctl.io/install.sh | bash脚本执行完会把可执行文件放到系统 PATH 里然后验证一下版本nuctl version这里有个坑要提前讲清楚nuctl 版本和 Nuclio 平台的版本最好保持一个大版本范围内的一致。CVAT 某个 release 依赖的 Nuclio 平台版本是固定的如果你装了一个很新的 nuctl去连接旧版 Nuclio有可能会出现“unexpected EOF”或者连接被重置这种看起来像网络问题的报错实际上就是版本不匹配。遇到这种情况不要死磕网络优先检查版本。3.2 配置 nuctl 连接 Nuclio 并验证部署完 CVAT 并且带上了 Nuclio profile 之后Nuclio 的界面默认跑在 8080 端口的/路径下不对准确说 Nuclio 的 dashboard 默认是 8070 端口而 CVAT 主界面在 8080。在浏览器访问http://localhost:8070能看到 Nuclio 的网页控制台这一步是为了确认 Nuclio 平台确实活着。接着在服务器上用 nuctl 配置项目。CVAT 里自动标注函数默认放在cvat项目空间下所以要先用 nuctl 创建这个项目nuctl create project cvat然后可以用命令查看当前平台上有哪些函数确认通道畅通nuctl get function --namespace processor注意--namespace这个参数Nuclio 里函数命名空间默认是nuclio但 CVAT 的自动标注函数模板走的是processor这个命名空间。如果你看官方文档抄命令时没注意这个参数后面会发现函数列表是空的但函数实际部署在另一个命名空间里。这个细节非常刁钻我也是查了不少 issue 才弄明白。3.3 部署这步常见的版本坑关于 nuctl 部署模型函数有个经验必须分享官方仓库里提供了一系列现成的函数模板路径在 CVAT 仓库的utils/auto_annotation目录下。你可以用 nuctl 直接把模板函数部署过去然后通过 CVAT 界面的“模型注册”功能关联上。nuctl deploy --project-name cvat --path \ https://raw.githubusercontent.com/cvat-ai/cvat/develop/utils/auto_annotation/yolov5/function.yaml这条命令会从远程拉取函数定义并部署。执行之前确认服务器能正常访问 GitHub 的 raw 域名否则拉取会失败。部署成功后在 Nuclio 控制台里就能看到函数状态变成 ready这一步成功之后CVAT 和推理后端之间的通道才算真正打通。还有一个细节函数部署时如果涉及本地镜像构建Nuclio 会把构建过程跑在它自己的 builder 容器里。这个 builder 容器需要拉取基础镜像如果服务器网络环境特殊、镜像拉取超时函数部署就会卡在 building 状态大半天。遇到这种情况可以给 Docker 配置镜像加速或者提前手动把函数模板里用到的基础镜像拉取到本地。4. YOLOv5 模型准备从训练到可部署的模型文件4.1 模型选择与权重准备自动标注的效果上限取决于你给它的模型有多强。如果你要做通用场景的预标注直接用 YOLOv5 官方在 COCO 上训练好的权重就能有一个不错的底子如果你标注的是特定场景比如我这边的工业零件、或者口罩、车牌这类专用目标就一定得用在自己数据集上微调过的权重。YOLOv5 训练流程很多朋友已经跑通了训练完会在runs/train/exp/weights/目录下得到best.pt和last.pt。自动标注场景下一般选best.pt。但这里有个关键问题Nuclio 里的 YOLOv5 函数模板在加载权重时对格式有要求不建议直接把.pt文件丢进去而是要先转换成 ONNX 格式。原因一是 ONNX 格式在 Nuclio 的推理环境里加载更稳定二是 ONNX 可以脱离 PyTorch 环境运行减少依赖冲突。转换命令在 YOLOv5 仓库目录下执行python export.py --weights best.pt --include onnx --opset 11导出完会生成best.onnx留着待会儿用。如果你机器有 NVIDIA GPU并且确认 Nuclio 部署时能访问到 GPU也可以尝试导出成 TensorRT 格式推理速度会再上一档。但没 GPU 就别折腾 TensorRT 了CPU 环境下 ONNX 更稳妥。4.2 标签映射与目录结构这个坑非常隐蔽但后果很严重如果你在 CVAT 项目里定义的标签顺序和模型训练时的类别顺序不一致自动标注出来的框会张冠李戴。比如你训练模型时类别顺序是[cat, dog]但在 CVAT 项目里先创建了dog再创建了cat那么模型输出的第一个类别的框会被 CVAT 标注成dog实际上它是cat。所以创建 CVAT 项目时标签顺序必须和模型训练时的类别顺序严格一致。最稳妥的做法是打开训练用的data.yaml照着里面的类别列表从上到下依次在 CVAT 里创建标签。不要嫌麻烦这一步值得反复核对。4.3 模型权重上传到 Nuclio 可访问的位置ONNX 权重生成好了接下来要想办法让 Nuclio 函数能读到它。常见做法有两种一是把权重文件放到一个 Nuclio 函数容器内可以通过挂载路径访问的位置二是直接把权重文件打进函数镜像里。我自己的实操路径是这样的先把best.onnx放到了 CVAT 部署目录下的一个自定义挂载目录中然后修改函数 YAML 里的 volume 配置把宿主机该目录映射进函数容器。具体路径因为每个人环境不同而有差异但核心思路很简单让函数容器内某个固定路径能读取到这个文件。这里提醒一下第一次调试自动标注时可以先用官方已有的 YOLOv5 模板配合 COCO 预训练权重把整条链路跑通确认 CVAT 能正常展示推理结果之后再换成你的自定义权重。这样能避免“权重有问题”和“配置有问题”两件事搅在一起排查起来难度会小很多。5. 在 CVAT 中跑自动标注实际操作流程5.1 在 CVAT 创建项目、任务并上传数据模型函数部署好之后剩下的就是在 CVAT 界面里操作了。第一步是创建项目项目的标签列表就是前面强调过的“必须和模型类别顺序一致”的那个列表。创建完项目接着创建任务一个任务可以包含多张图片也可以按帧序列处理视频。任务创建时有几个参数值得注意。图片上传支持压缩包批量上传但单次上传的图片数量别贪多我建议一个任务控制在几百张到一千张左右。数量太多的话自动标注跑起来时间非常长万一中间有参数要调整前面跑的全白费。如果数据总量很大拆成多个任务分批处理反而更灵活。5.2 打开 Auto Annotation 并配置推理参数任务创建好、图片传完进入任务界面右上角有一个“自动标注”按钮点开之后会让你选择模型函数。这里能看到你之前通过 nuctl 部署或者通过界面注册的函数名称选中之后会展开参数配置面板。对于 YOLOv5 函数比较常用的参数有三个conf_threshold控制置信度阈值默认值可以参考 0.35如果发现漏检多就调低一点如果错检多就往上调iou_threshold控制 NMS 的 IoU 阈值默认 0.45 基本不用动img_size控制推理时输入图片的分辨率如果原图很大可以适当调小来提升速度但代价是小目标可能漏检。这几个参数直接决定了自动标注结果的质量建议先拿一小批图片试跑肉眼检查一轮再批量跑。跑起来之后CVAT 界面会显示任务状态后端日志里也能看到推理进度。图片多的任务可能要跑几十分钟甚至更久期间不要去重启容器否则进度直接清零。5.3 机器标注后的校验与修改技巧自动标注不是终点人工校验才是真正花时间的地方。CVAT 的标注界面支持框的选中、拖拽、删除、修改标签操作手感跟 LabelImg 差不太多但效率要高不少因为大部分框已经在了你要做的是“找茬”而不是“创建”。校验时我一般按这个顺序来先按置信度从低到高过一遍小目标的框低置信度区域往往是错检重灾区然后整体扫一遍漏检区域尤其是图像边缘和遮挡部分最后检查类别是否标错。有些老手会直接在 CVAT 里写个简单的标签搜索把所有低置信度框过滤出来批量处理这样可以省下不少时间。6. 数据导出与 YOLOv5 训练闭环6.1 导出 YOLO 格式数据集标注校验完成之后数据的价值才真正体现出来。CVAT 支持多种格式导出对 YOLOv5 用户来说直接在任务页面选择导出为 YOLO 格式即可。导出时会有几个选项包括导出哪些标签、是否包含未标注图片等建议把“unannotated only”相关的选项关掉只导出已经标注过的图片避免后续训练时混入大量没有目标的背景图干扰模型。导出的压缩包解压之后是标准的 YOLO 目录结构images和labels两个文件夹labels里是每张图对应的 txt 文件每行一个目标格式为class_id x_center y_center width height。有了这套数据放到你自己的 YOLOv5 训练工程里配合data.yaml就可以直接开跑下一轮训练。6.2 用自动标注结果迭代训练模型一套真正好用的自动标注系统一定是能自我迭代的。第一轮你可能用 COCO 预训练模型或者初版模型跑自动标注然后人工校验修正得到一批质量还不错的数据用这批数据训练出更好的模型再用新模型去标注下一批图片。每一轮下来模型精度提升需要人工修正的框会越来越少标注效率会越来越高。实际操练下来第一个版本的自动标注结果可能让你想骂人但不要因此放弃。先挑简单、目标清晰的数据集启动迭代把流程跑顺再逐步挑战复杂场景。模型这个东西数据质量上去了效果自然会跟着上去而自动标注的价值恰恰在于帮你更快地积累高质量数据。7. 避坑总结常见问题排查速查表7.1 高频问题速查表把我在部署和使用 CVAT 自动标注过程中遇到的高频问题整理成一张表方便大家按图索骥快速定位问题所在。现象可能原因解决办法nuctl 命令找不到安装脚本没把可执行文件放入 PATH重新安装或手动把 nuctl 二进制软链到/usr/local/binnuctl 连接不上 Nuclio部署 CVAT 时没加--profile nuclio重新执行带 profile 的 compose 命令并确认 8070 端口可访问nuctl 报 unexpected EOFnuctl 与 Nuclio 平台版本差距过大检查并统一版本CVAT 界面没有自动标注按钮没有登录管理员账号或 Nuclio 未启动用管理员登录检查 Nuclio 控制台状态函数部署卡在 building基础镜像拉取失败或超时配置 Docker 镜像加速或手动拉取基础镜像自动标注结果类别错乱CVAT 标签顺序与模型类别顺序不一致删除任务按模型类别顺序重建项目和任务推理速度极慢CPU 推理或参数设置不合理使用 GPU 版 Nuclio调低img_size合理设置 batch size容器在推理时被 OOM kill内存不足增加内存或 swap减少单批任务图片数量7.2 性能优化与替代路径如果说自动标注一定要选一个优化方向我建议优先保证模型质量其次再谈推理速度。模型质量不行推理再快也是白搭。如果模型本身精度够高自动标注结果几乎不用改那整体效率提升是肉眼可见的。最后再分享一条备选路径如果你实在搞不定 Nuclio 这一整套部署还有一个土办法——用 YOLOv5 直接批量推理生成每张图片的 txt 标注文件再配合脚本把结果导入 CVAT 进行人工校验。这条路跳过了 nuctl 和 Nuclio部署负担小很多适合小数据量、快速验证的场景。但如果你要长期、批量地做数据生产CVAT 加 Nuclio 这套体系还是更值得打通毕竟平台化的标注管理能力是脚本替代不了的。我个人在实际操作中的体会是自动标注的价值不在于让你完全不用标注而是把你从“画框工人”变成一个“审核员”。同样一批数据全人工标注可能要一个星期自动标注加人工校验可能一天就搞定质量还更稳定。但前提是你得先把模型调到能用的水平再把流程跑顺这两个前置条件缺一不可。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进