ARTICLE DETAIL

资讯详情

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

CVAT自动标注实战:Nuclio+nuctl部署YOLOv5全流程踩坑指南

CVAT自动标注实战:Nuclio+nuctl部署YOLOv5全流程踩坑指南 CVAT自动标注这件事我前后折腾了将近两周。不是CVAT本身多难装而是从nuclio到nuctl再到YOLOv5函数部署这一条链路每一步都有官方文档没写透但实际一定会碰到的坑。等我全跑通之后回头看真正花时间的不是模型本身而是理解CVAT的自动标注为什么要走Nuclio这条服务器无状态计算路径以及nuctl这个命令行工具在整个环节里到底扮演什么角色。这篇文章就把我完整的踩坑过程和最终跑通的配置原样放出来给正准备入坑CVAT自动标注的朋友省点时间。先说清楚我当时的现状本地Ubuntu 20.04Docker部署的CVAT 2.3.0显卡是RTX 3090标注目标是自己的工业零件数据集需要借助YOLOv5模型对检测框做预标注。模型本身我已经在本地训练好期望的流程是把YOLOv5权重交给CVAT在标注界面里选中视频或图片序列一键让模型把目标框先画出来我再人工修正。这个流程听起来简单实际涉及的是CVAT标注平台和Nuclio serverless引擎两个系统之间的联动再加上模型推理函数在Nuclio里的构建与部署。任何一个环节版本对不上、网络访问不了、参数配错结果都是界面上点自动标注后长时间无响应然后在浏览器F12里看到一堆让你摸不着头脑的502或500报错。1. 自动标注的原理CVAT为什么要扒着Nuclio不放很多人第一次接触CVAT自动标注都会困惑一个问题明明CVAT是Python写的一个单体应用为什么自动标注非要额外部署一套Nuclio直接在CVAT进程里调用模型推理不行吗我一开始也这么想直到翻了源码才理解。CVAT的自动标注架构把推理这件事完全外包给了Nuclio这一套serverless平台。标注界面上点完自动标注按钮CVAT后端做的事情是把当前任务的数据集封装成一个事件请求调用Nuclio平台上注册好的函数函数内部完成模型加载、推理、结果解析、转换成CVAT可识别的标注格式最后回调CVAT并把标注写回服务器。这么设计的直接原因是性能和隔离。如果你的标注任务很大模型推理是个高CPU/GPU消耗操作放在CVAT主进程里跑一个任务就能把整个平台拖垮。在Nuclio上每个函数是一个独立容器资源可以限制、可以伸缩、可以单独重启平台稳定性高得多。基于同一套架构你还可以同时挂载YOLOv5、Detectron2、PaddlePaddle等多个模型做不同任务的标注互不干扰。理解了这个架构你就明白为什么nuctl这个命令行客户端如此重要了。函数的上传、构建、部署、查看状态全都通过nuctl和Nuclio平台通信完成。没有nuctl你只能用Nuclio的Web界面手动点点点但CVAT场景下很多配置和调试操作命令行的效率优势是界面完全比不上的。2. nuctl安装与对接第一道门槛怎么跨过去nuctl是Nuclio提供的命令行工具本质是一个二进制文件没有复杂的安装依赖。但正因为太简单反而容易让人忽略它的版本兼容性。2.1 下载对应版本的nuctl二进制这里有一个前提必须强调nuctl的版本尽量和你部署的Nuclio平台版本保持一致。不要无脑下载最新版。我最初用的是nuctl 1.11.x去连CVAT 2.3.0自带的Nuclio出现了接口字段不兼容的问题部署函数时一直报unknown field错误。后来把nuctl降到和容器镜像相同的大版本才正常。下载方式很简单直接从Nuclio的GitHub Releases页面拿对应平台的二进制文件。Linux系统命令大致如下# 注意把版本号替换成你实际需要的版本 curl -sSL -o /usr/local/bin/nuctl \ https://github.com/nuclio/nuctl/releases/download/1.15.0/nuctl-1.15.0-linux-amd64 chmod x /usr/local/bin/nuctl # 验证安装 nuctl versionmacOS用户下载darwin-amd64或darwin-arm64版本Windows用户下载exe文件后配置好环境变量即可。如果你在Docker容器里装也可以考虑用docker run镜像的方式但我不推荐因为嵌套Docker场景下的网络配置会很麻烦。2.2 配置nuctl连接到Nuclio平台安装完nuctl后首先要让它找到Nuclio平台。CVAT部署时会启动一个名为cvat-nuclio的容器daemon端口是8070。默认情况下nuctl会查找本地的dashboard所以如果你在宿主机上执行命令通常只需要设置环境变量指向这个端口export NUCLIO_DASHBOARD_URLhttp://localhost:8070然后执行nuctl get projects如果能看到输出列表说明nuctl已经和Nuclio平台打通了。这个命令也是我后续排查问题最高频使用的一个命令它能够快速确认nuctl和平台之间的连接状态。2.3 用nuctl先跑通一个最简单的函数在碰YOLOv5之前我强烈建议先用nuctl部署一个空函数或测试echo函数把整个部署链路跑通。这能帮你把nuctl问题和模型函数问题分开排查。Nuclio平台提供了内置示例在dashboard页面的Create Function里可以选。命令行方式下可以用官方仓库里自带的一个简单处理器进行部署测试nuctl deploy test-func --path https://raw.githubusercontent.com/nuclio/nuclio/master/cmd/processor/test/functions/empty/empty.yaml这个测试的目的是验证nuctl能正常发起构建、能看到构建日志、函数能进入ready状态。实话说这一步如果卡住大概率是你和Nuclio之间的网络或者环境变量有问题而不是模型本身的锅。3. YOLOv5模型侧的准备工作权重、参数与配置文件很多人以为模型部署就是把.pt文件扔进去就行实际操作中这也是犯错的重灾区。CVAT的YOLOv5自动标注函数并不加载你训练出来的权重文件就直接跑你需要明确CVAT对模型格式、类别定义、标签映射等有一系列特殊要求。3.1 模型格式选择PyTorch权重还是ONNXCVAT serverless函数里YOLOv5的推理代码支持PyTorch和ONNX等格式。使用PyTorch格式最方便因为你的训练产物就是.pt文件。如果为了推理速度考虑要转成TensorRT或ONNX那涉及的部署配置项会略有不同这里以最常用的PyTorch权重为例。你需要确认的事模型类别名列表。COCO预训练的YOLOv5输出80个类别类别名是person、bicycle、car等。如果你用自己的数据集训练类别名可能完全不同。CVAT函数运行时会读取你的类别名列表并将它们在内存中映射成推理时模型输出tensor的索引位置。这个映射关系一旦对不上自动标注出来的框就全部是乱的。3.2 配置文件里最容易错的两个字段CVAT自动标注函数在部署时需要指定一个config.json或模型配置文件里面最重要的两个字段是labels和threshold。以我自己的工业零件数据集为例模型训练时用了5个类别配置文件大致长这样{ labels: [ nut, bolt, washer, bearing, gear ], threshold: 0.25 }labels的排列顺序必须和模型训练时data.yaml里面类的顺序完全一致。这里的顺序决定了推理结果中类别索引和文本标签之间的映射差一个就全歪了。另外threshold是置信度阈值建议先用默认0.25跑看看预标注密度如果框太多太杂就调高如果漏检明显就调低。3.3 自定义数据集模型的特别注意事项你的模型如果是在自定义数据集上训练的还需要额外确认三点第一训练时的输入尺寸。YOLOv5的模型通常用640x640作为输入但CVAT自动标注函数在推理时会对原图做letterbox后统一resize到模型输入尺寸。这个步骤理论上不需要你配置但你的模型如果本身用了奇怪的输入尺寸需要在配置文件里显式声明input_width和input_height否则推理出来的框的位置会有系统性偏移。第二如果你训练时用了多尺度训练或特殊anchors转出来的模型仍然可以直接用因为.pt文件里已经包含了模型结构和权重。第三如果训练模型最终导出格式不对部署后函数能跑起来但推理出的结果为空。检查模型输出的shapeYOLOv5的推理输出应该是[batch, 25200, 5num_classes]形式如果你这个输出的维度不对大概率是模型导出时有额外预处理层被加进去了。4. 自动标注函数部署从项目文件到Nuclio上线这里进入正题把YOLOv5模型函数完整部署到Nuclio平台上。CVAT官方其实提供了serverless函数的示例代码源码里有一份现成的YOLOv5函数目录。你不需要从零写推理逻辑但需要理解部署过程中每个文件的作用。4.1 准备函数项目目录推荐做法是先从CVAT源码仓库里把serverless/pytorch/facebookresearch/yolov5这个目录拷贝出来。目录结构大致包含function.yamlNuclio函数的部署配置main.py函数入口包含模型加载和推理逻辑nuclio.yamlNuclio相关元数据Dockerfile构建函数镜像的配方直接使用官方示例代码省去了自己写解析器的麻烦。CVAT社区对示例函数有较完善的维护主流程大概率不会有坑。4.2 修改function.yaml的关键配置项function.yaml是最核心的配置文件。你需要根据实际环境修改几个地方metadata: name: cvat-yolov5 namespace: nuclio labels: platform: nuclio spec: runtime: python:3.8 handler: main:handler minReplicas: 1 maxReplicas: 1 env: - name: CVAT_BASE_URL value: http://host.docker.internal:8080 build: commands: - pip install -r requirements.txt其中CVAT_BASE_URL是Nuclio函数容器回调CVAT服务器的地址。这是个很容易踩坑的配置项Nuclio函数如果跑在Docker容器里它不能直接通过localhost访问宿主机上的CVAT服务需要通过host.docker.internal这样的特殊域名来访问宿主机IP。如果是Kubernetes部署环境这里的值需要换成CVAT的Service名称写法完全不同。4.3 加载自定义模型权重的几种方式模型权重文件可以以三种方式提供给Nuclio函数方式一将权重文件放到函数目录下并且目录作为Path传给nuctl构建的时候文件会被打进镜像。这种方式在镜像构建时最直观但如果权重很大镜像体积会膨胀得厉害。方式二把权重文件放OSS存储或HTTP可访问地址函数启动时动态下载。这种方式在团队协作时比较友好每个人不用存着同样的权重文件。方式三直接把模型权重放在Docker卷或host路径下通过volume挂载到函数容器。我最终用的是方式一因为我的权重文件只有十几MB打镜像完全没压力。如果你是超大模型或者高频迭代推荐方式二更理性。4.4 nuctl deploy部署命令详解万事俱备后执行部署命令。注意--path指向你的函数目录--file指向function.yaml文件nuctl deploy cvat-yolov5 \ --path /path/to/yolov5-function \ --file function.yaml \ --project-name cvat \ --registry cvat部署过程中nuctl会实时输出构建日志。你能看到镜像构建、依赖安装、函数创建的过程。看到Function deploy complete并且状态为ready基本就成功了一半。部署完成后用nuctl get function -n nuclio查看函数的运行状态nuctl get function cvat-yolov5 -n nuclio如果状态是ready说明函数已经正常注册。如果状态是error或unhealthy则要看日志排查原因这里我再强调一句不要急着换配置重试先把日志拉到本地看错误信息多数情况下是权重文件路径写错、依赖没装全、回调地址不对这三个原因。5. 部署与使用阶段的深度踩坑记录整个流程里我遇到过的坑挑几个印象最深、最典型的写出来这些都是网上资料很少提到的。5.1 函数部署成功但自动标注一直转圈这是最让人崩溃的。函数显示readyCVAT界面也能在模型列表里看到但点击自动标注按钮后任务状态一直处于pending或running持续很久都没有结果。排查思路按步骤走先看Nuclio函数日志nuctl logs cvat-yolov5 -n nuclio最常见的日志信息是connect: connection refused。这是CVAT_BASE_URL配置有误。你要理解的是Nuclio函数容器在构建/运行时调用的是容器视角的CVAT地址。如果是Docker Compose方式安装的CVAT那host.docker.internal:8080是最常见的解决方案。如果是K8s环境这里应该是http://cvat-server:8080这种基于Service名的内部地址。另一个容易忽略的问题是函数在回调CVAT进行标注保存时如果任务权限不够或者数据过大CVAT端可能需要较长时间处理这不属于函数故障需要耐心等待。我踩过一次坑是视频序列有几百帧模型逐帧推理加保存结果总共耗时十几分钟中间界面看起来都像卡死其实底层一直在跑。5.2 标注框全部乱码标签映射错位的排查这是自定义数据集场景下一个很容易碰到的问题。我第一次用自定义模型部署后自动标注确实画框了但框的位置是对的标签却是完全错乱的。比如实际是nut的目标被标成bearing。我折腾了很久才发现问题在模型配置文件的labels顺序和模型训练时的类别顺序不一致。这里要补充一个CVAT机制不同模型输出的类别数量可以不同CVAT的自动标注流程会把模型的预测结果和任务已有的标签进行映射匹配。如果你的CVAT任务里定义了大量标签而模型只预测少数类别映射关系就变得非常关键。某些情况下CVAT需要你在模型配置里提供一个显式的映射关系否则它默认按类别名称匹配名称对不上就乱标。所以labels名称尽量和CVAT任务里的标签文本保持一致这会省掉大量后期人工修正。5.3 GPU资源浪费函数跑在CPU上你在宿主机上有GPU但部署出的函数默认不一定能用上GPU。Nuclio函数默认只使用CPU资源。要让YOLOv5函数跑在GPU上需要修改function.yaml增加GPU资源声明spec: resources: limits: nvidia.com/gpu: 1但注意这要求你的Nuclio平台得支持GPU设备插件。Docker方式下还需要额外在nuclio.yaml或部署命令中指定--gpus参数或者配置Docker runtime。如果你的函数没有申请到GPU资源模型的推理速度会非常慢尤其是处理视频序列标注时CPU推理和GPU推理能差20倍以上。如果条件允许建议在本地先把模型推理速度单独测一遍确认推理时间可接受后再挂到CVAT里。不然部署上去之后每次标注都要等待特别影响整体体验。5.4 权重版本和代码不匹配导致推理崩溃YOLOv5的官方仓库迭代非常快不同版本的模型文件结构有差异。CVAT serverless里内置的YOLOv5推理代码是基于特定版本开发的。你把最新版本YOLOv5训练出来的权重搞进去大概率出现类似AttributeError或KeyError这种推理时崩溃。解决办法有两个方向一是把训练时的yolov5仓库版本锁定到CVAT serverless的requirements.txt里对应版本然后重新导出模型权重二是在你自己的推理脚本里先把模型load起来测一遍确认能出结果再把权重丢给CVAT用。我自己更推荐第二个思路因为它逼着你先在本地把加载权重-推理图片-拿到结果整条链路跑通。这一步通过之后再回CVAT部署问题就能被限制在配置层而不是模型层。5.5 多个函数并发问题如果你和我一样在一个CVAT实例上同时挂了检测、分割等多个模型注意给每个函数设置好资源上限。Nuclio函数默认的并发模型在不同版本表现不太一样当多任务同时触发推理时可能造成OOM。这里的建议很简单不用的函数及时停掉nuctl delete function可以随时清理用的时候再deploy。6. 自动标注的实用技巧从能用到好用部署跑通只是第一步真正提升效率还要做一些额外调优。这里分享几个我实测有效的技巧。6.1 针对不同任务调整模型批处理大小CVAT自动标注默认是一张一张图推理速度较慢。如果你的图片序列数量很大可以考虑在函数配置里调高批处理大小batch size。但这需要你的模型推理代码支持batch输入并且GPU显存充裕。以RTX 3090 24GB为例YOLOv5s模型在batch size为8时推理速度能比单张快好几倍。6.2 用重叠掩码和后处理参数提升标注质量CVAT自动标注中有一个重叠掩码overlap mask参数用于控制半自动标注时对目标轮廓的处理。对检测框任务来说这个参数影响没那么大。但如果你用的是带分割头的模型它直接决定标注结果的精细度。另外很多模型在推理后会输出一些概率极低的噪声框。可以通过调高threshold过滤掉。我发现对大多数目标检测任务阈值设在0.3到0.4之间比较合适既不会漏检严重也不会出现满屏的垃圾框。6.3 CVAT任务标签和模型标签的映射小技巧如果你给不同任务定义了不同的标签集不要指望一个模型部署解决所有任务的自动标注。最实用的做法是在CVAT中创建任务时让任务标签的文本和模型配置文件中的labels一一对应。比如你的模型能识别nut和bolt那么任务标签里也要有这两个标签大小写和空格都要一致。CVAT在自动标注时会尝试将模型输出标签名和任务已有标签名做匹配名字不匹配的输出会被丢弃。这是一个低成本的避坑手段能省掉大量后期人工改标签的工作。6.4 自动标注结果的人机协作修正节奏自动标注不可能100%准确合理的流程应该是先用自动标注生成初稿然后人工在CVAT界面里逐帧检查修正。这里有一个建议先让自动标注跑完整个任务再统一进行人工修正而不是边标注边修正。原因在于CVAT的任务更新机制可以批量处理标注结果你边跑边改容易把一次性的修改操作变成多次冲突。等所有自动标注完成后在CVAT的任务-标注页面里使用键盘快捷键快速翻看每一帧只关注置信度较低的框和明显漏检的区域。这样通常能把标注时间压缩到原来的三分之一以下。7. 最后再分享一点个人使用体会整套CVATNuclioYOLOv5的链路跑通后我一个明显的感觉是自动标注真正带来的效率提升不是完全不用人工而是把标注工作从画框变成了修改框。后者在心理负担和操作层面上都要轻松得多。尤其对于工业数据集这种目标形状较为固定的场景模型预标注的框已经很接近最终结果人工只需要微调边缘和漏检速度远超从零开始画框。如果你正准备在自己的项目里铺开使用建议给团队留出三四天时间去摸索这些坑。第一天安装和环境配置第二天跑通nuctl和Nuclio部署第三天处理模型格式和标签映射第四天做完整流程的验收。不要指望一天搞定这个链路涉及的组件太多知识缺口会不断出现。另外一个小建议是部署之前把CVAT源码仓库里serverless目录下的示例函数浏览一遍理解官方推荐的函数编写规范包括main.py的handler处理逻辑和函数返回的数据格式。这比直接修改别人的配置文件要有效得多。因为CVAT自动标注函数对返回结果的数据结构定义有自己的约定格式一旦不对函数本身跑不报错但CVAT端可能拿不到任何标注结果这个现象排查起来非常痛苦。我现在的日常使用已经稳定在训练新模型→更新权重→重新部署函数→自动标注新任务这个循环里了。每次换模型权重后先跑通一条样例视频确认效果再放量处理大批量数据。这套流程稳定之后我基本上再也没有在标注工具上浪费过时间更多精力都花在模型精度迭代上这大概才是自动标注真正该有的价值。
返回列表