CVAT 中的 YOLO 格式:数据集导出、导入与 YOLO 风格任务创建的完整指南
2026/9/14 11:23:47 网站建设 项目流程

CVAT 中的 YOLO 格式:数据集导出、导入与 YOLO 风格任务创建的完整指南

【免费下载链接】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 将 YOLO(You Only Look Once)作为官方支持的数据集交换格式之一,用于在标注平台与实时目标检测模型之间流转边界框(Bounding Box)标注。本文基于 CVAT 仓库的官方文档与 formats/yolo.py 的源码实现,系统讲解 YOLO 格式的目录结构、obj.data/obj.names/标注文本文件的内容规范、导入时的帧匹配机制,以及如何从一个 YOLO 风格数据集(例如由 VOC 转换而来)批量创建 CVAT 标注任务,读完即可独立完成“YOLO 数据集 ↔ CVAT”的双向流转。

YOLO 格式概述

YOLO 是实时目标检测领域的代表性框架,其数据格式因结构简单、解析成本低,也被许多其他目标检测模型采用。CVAT 对该格式的支持要点如下(与官方文档 format-yolo.md 一致):

  • 支持的标注类型:仅 Bounding Boxes(矩形边界框);
  • 属性(Attributes):不支持;
  • Tracks(跨帧跟踪):不支持。

在 CVAT 中,该格式以显示名YOLO 1.1注册,扩展名为ZIP。这一点可以从格式注册源码确认:

# cvat/apps/dataset_manager/formats/yolo.py @exporter(name="YOLO", ext="ZIP", version="1.1") def _export_yolo(*args, **kwargs): _export_common(*args, format_name="yolo", **kwargs) @importer(name="YOLO", ext="ZIP", version="1.1") def _import_yolo(*args, **kwargs): _import_common(*args, format_name="yolo", **kwargs)

注册器 formats/registry.py 中的exporter/importer装饰器以NAME VERSION(即YOLO 1.1)作为键写入全局EXPORT_FORMATS/IMPORT_FORMATS字典,前端界面和 REST API 中可选的“YOLO 1.1”即来自这张注册表。

YOLO 导出:zip 包结构与文件规范

导出结果为.zip压缩包,其目录结构必须与下方约定一致:

archive.zip/ ├── obj.data ├── obj.names ├── obj_<subset>_data │ ├── image1.txt │ └── image2.txt └── train.txt # list of subset image paths # the only valid subsets are: train, valid # train.txt and valid.txt: obj_<subset>_data/image1.jpg obj_<subset>_data/image2.jpg # obj.data: classes = 3 # optional names = obj.names train = train.txt valid = valid.txt # optional backup = backup/ # optional # obj.names: cat dog airplane # image_name.txt: # label_id - id from obj.names # cx, cy - relative coordinates of the bbox center # rw, rh - relative size of the bbox # label_id cx cy rw rh 1 0.3 0.8 0.1 0.3 2 0.7 0.2 0.3 0.1

各文件的语义与取值规范如下:

文件作用关键规范
obj.names标签名称的有序列表每行一个类名,行号(从 0 起)即类 id,如cat是 0、dog是 1、airplane是 2
obj.data数据集入口配置names = obj.names指向名称文件;train = train.txt必选;validbackupclasses可选
train.txt/valid.txt子集图片清单每行一个相对路径,例如obj_train_data/image1.jpg;合法的子集只有trainvalid两种
image_name.txt单张图片的标注与图片同名同目录,例如frame_000001.txt对应frame_000001.jpg

标注文本文件image_name.txt中,每一行描述一个标签加一个边界框,格式为label_id cx cy w h

  • label_id:该框的类别编号,取值对应obj.names中的行序;
  • cx, cy:边界框中心的归一化坐标(相对图片宽高的比例,0~1);
  • w, h:边界框宽高占图片宽高的归一化比例(0~1)。

“标注文件与图片文件同名(仅扩展名不同)”这一约定是 YOLO 格式的核心索引机制,也是后续 CVAT 导入时进行帧匹配的基础。

导出流程的源码实现

从 formats/yolo.py 的_export_common可以看到完整的导出调用链:

  1. 通过GetCVATDataExtractor(instance_data, include_images=save_images)构造从 CVAT 数据库/任务抽取标注(可选抽取图片)的 datumaro 抽取器;
  2. StreamDataset.from_extractors(...)把标注加载为流式数据集,再调用 datumaro 的dataset.export(temp_dir, "yolo", save_media=..., **kwargs)按 YOLO 规范写出上述目录结构;
  3. 最后make_zip_archive(temp_dir, dst_file)把临时目录打包为下载的.zip文件。

也就是说,CVAT 本身不逐字段手写 YOLO 文本,而是复用 datumaro 框架内建的yolo导出器;CVAT 侧负责数据抽取、打包与错误包装(_wrap_format会把AnnotationExportError转译为 CVAT 异常)。仓库测试 tests/test_formats.py 中的test_empty_images_are_exported明确将("YOLO 1.1", "yolo")纳入导出回归用例,校验导出 zip 能被 datumaro 的yolo导入器重新读回且条目数与任务帧数一致。

YOLO 导入:帧匹配机制

导入时上传的文件同样是上述结构的.zip压缩包。CVAT 必须能把包中的每个标注文件对应到任务中的一帧,官方文档给出两种匹配方式:

  1. 按完整文件名匹配:图片名与标注*.txt文件名完全一致(适用于由图片或图片压缩包创建的任务);
  2. 按帧号匹配:当 CVAT 无法按名称匹配时,文件名需为<number>.jpg形式(适用于由视频创建的任务,CVAT 会把视频帧编号为0.jpg1.jpg…)。

这两个规则在源码中的落点是 bindings.py 的match_dm_item函数,其匹配顺序为:

# cvat/apps/dataset_manager/bindings.py def match_dm_item(item, instance_data, root_hint=None): frame_number = None # 1) 名称+扩展名 全匹配 if frame_number is None and isinstance(item.media, dm.Image): frame_number = instance_data.match_frame(item.id + item.media.ext, root_hint) # 2) 去掉扩展名再匹配(对应 *.txt 与图片名一致的常见情况) if frame_number is None: frame_number = instance_data.match_frame(item.id, root_hint, path_has_ext=False) # 3) 标注自带的 frame 属性 if frame_number is None: frame_number = datumaro.util.cast(item.attributes.get("frame", item.id), int) # 4) 视频任务的 frame_<N> 前缀兜底 if frame_number is None and is_video: frame_number = datumaro.util.cast(osp.basename(item.id)[len("frame_"):], int) ...

即 CVAT 依次尝试“全名匹配 → 去扩展名匹配 → 数值化匹配 → 视频帧前缀匹配”。导入流程(_import_common)会先解压 zip,调用detect_dataset校验包结构确实符合yolo格式,然后递归glob找出所有*.txt标注文件、用find_dataset_root推断数据集根前缀以便剥离多余目录层级,最后经StreamDataset.import_from载入并应用SetKeyframeForEveryTrackShape转换,由import_dm_annotations把 datumaro 标注写回 CVAT(bbox 映射为ShapeType.RECTANGLE)。若某个标注文件匹配不到任何帧,match_dm_item会抛出CvatImportError,提示无法匹配的文件 id,便于定位命名问题。

从 YOLO 数据集(如 VOC 转换而来)创建 CVAT 任务

官方文档给出了一个从零开始导入 YOLO 风格数据集的完整实操流程(以 YOLO 官方指南从 VOC 准备的数据为例),步骤完整保留如下:

第 1 步:准备 YOLO 格式标注文件。参照 YOLO 官方指南中“Training YOLO on VOC”一节,准备出 YOLO 格式的标注文件。

第 2 步:压缩 train 图片。

zip images.zip -j -@ < train.txt

第 3 步:创建 CVAT 任务,标签设置为(VOC 20 类,与obj.names行序一一对应):

aeroplane bicycle bird boat bottle bus car cat chair cow diningtable dog horse motorbike person pottedplant sheep sofa train tvmonitor

数据源选择images.zip。由于该压缩包通常超过 500MB,官方建议借助 CVAT 的文件 share 功能挂载大文件(详见文档 tasks-page 中创建标注任务的章节)。

第 4 步:创建obj.names,内容与任务标签顺序严格一致:

aeroplane bicycle bird boat bottle bus car cat chair cow diningtable dog horse motorbike person pottedplant sheep sofa train tvmonitor

注意:obj.names中的行序就是导入后的类 id,务必与 CVAT 任务中 label 的创建顺序保持完全一致,否则类别会张冠李戴。

第 5 步:把所有 train 子集对应的标注文件打包。

cat train.txt | while read p; do echo ${p%/*/*}/labels/${${p##*/}%%.*}.txt; done | zip labels.zip -j -@ obj.names

该 shell 管道的含义:从train.txt逐行读取图片相对路径,把路径中图片所在目录替换为labels/目录、扩展名替换为.txt,列出全部标注文件路径;-j丢弃目录层级,-@从标准输入读取文件列表,最后把obj.names一并压入labels.zip

第 6 步:在 CVAT 中点击Upload annotation,格式选择YOLO 1.1,上传上一步生成的标注 zip。CVAT 将按“名称匹配优先、帧号匹配兜底”的策略把每帧标注写入任务。

源码级补充:YOLO 家族与边界情况

从 formats/yolo.py 的注册清单还可以看到,CVAT 在同一模块中维护了一整套 YOLO 家族格式(均注册为 ZIP、版本 1.0):

  • Ultralytics YOLO Detection 1.0/Ultralytics YOLO Detection Track 1.0(后者通过write_track_id=True额外写出跟踪 id,是唯一支持 Tracks 变体);
  • Ultralytics YOLO Oriented Bounding Boxes 1.0(带角度的边界框);
  • Ultralytics YOLO Segmentation 1.0(分割多边形,导出前会先用EllipsesToMasksmasks_to_polygons转换);
  • Ultralytics YOLO Pose 1.0(关键点,导入时从 CVAT 元数据读取骨架子标签作为skeleton_sub_labels);
  • Ultralytics YOLO Classification 1.0(图像分类)。

这些变体与经典YOLO 1.1共用_export_common/_import_common基础设施,差别仅在于 datumaro 侧的format_name与少量转换参数。若你的数据包含 Tracks、多边形或关键点,应优先考虑对应的 Ultralytics 变体,而不是经典 YOLO 1.1(后者仅边界框、无属性、无 Tracks)。

此外有两点边界情况值得注意:

  • 空标注帧同样会被导出:测试test_empty_images_are_exported保证无标注帧也会生成空.txt,从而保持图片与标注文件的一一对应,这是 YOLO 目录约定的要求;
  • 导入失败的可诊断性:匹配不到帧时抛出的是带文件 id 的CvatImportError,结合 bindings.py 中match_dm_item的四级匹配顺序,通常可以快速判断是命名不一致(缺少扩展名匹配)还是视频帧号问题(应使用<number>.jpg形式)。

小结

CVAT 对 YOLO 格式的支持覆盖了“导出即训练集、导入即预标注”两个方向:导出按obj.data+obj.names+ 子集清单 + 同名.txt的标准目录组织,label_id cx cy w h全部为归一化值;导入依赖图片名/帧号与标注文件名的两级匹配,源码中match_dm_item进一步提供去扩展名与数值化兜底。配合上文 VOC 示例的六步操作(压缩图片、按序建标签、构造obj.names、管道命令打包标注、Upload annotation选择YOLO 1.1),即可把既有 YOLO 数据集平滑接入 CVAT 工作流。相关实现与回归测试可分别参考 formats/yolo.py、formats/registry.py、bindings.py 与 tests/test_formats.py。

【免费下载链接】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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询