3、常见标注格式详解(上):COCO JSON格式(目标检测)、LabelMe JSON格式

好,咱们今天来啃两块硬骨头——COCO JSONLabelMe JSON

这两个格式,做目标检测的朋友肯定不陌生。我个人习惯把 COCO 格式称为「工业标准」,而 LabelMe 更像是「个人作坊」的产物。为什么这么说?往下看你就明白了。

3.1 COCO JSON 格式:目标检测的「通用语言」

先聊聊 COCO。这个格式最早来自微软的 COCO 数据集,后来慢慢成了目标检测、实例分割领域的通用格式。说白了,你训练 YOLO、Mask R-CNN、Detectron2 这些模型,最后导出标注时,十有八九会碰到它。

3.1.1 整体结构长什么样?

COCO JSON 是一个大的字典,里面包含几个关键字段。我直接给你看一个简化版的结构:

{
  "images": [
    {
      "id": 1,
      "file_name": "img_001.jpg",
      "width": 1920,
      "height": 1080
    }
  ],
  "annotations": [
    {
      "id": 1,
      "image_id": 1,
      "category_id": 2,
      "bbox": [100, 150, 200, 300],
      "area": 60000,
      "iscrowd": 0
    }
  ],
  "categories": [
    {
      "id": 1,
      "name": "person"
    },
    {
      "id": 2,
      "name": "car"
    }
  ]
}

嗯,这里要注意:bbox 的格式是 [x, y, width, height],不是 [x1, y1, x2, y2]。我刚开始做标注时,就因为这个搞混过,结果模型训练出来检测框全偏了……

3.1.2 三个核心字段详解

字段 作用 关键点
images 记录每张图片的元信息 id 必须唯一,file_name 建议用相对路径
annotations 存储每个标注框的数据 bbox 是 [x,y,w,h],area 可以手动算
categories 定义类别列表 id 从 1 开始,不要用 0
我的小技巧: 写导出脚本时,先打印 categories 列表看看。我遇到过类别 id 从 0 开始的情况,结果模型训练时直接报错。嗯,这种坑踩一次就够了。

3.1.3 避坑指南:bbox 和 area

我曾经在导出 COCO 格式时,把 bbox 写成了 [x1, y1, x2, y2]。结果呢?模型训练出来的检测框全跑到图片外面去了。排查了半天才发现是格式问题。

还有 area 字段。很多人觉得它不重要,随便填个 0。但如果你用 COCO 的评估工具(比如 cocoapi),area 会影响小目标、中目标、大目标的统计。我建议你老老实实算一下:area = width * height

3.2 LabelMe JSON 格式:多边形标注的「老朋友」

LabelMe 是 MIT 开发的一个标注工具,它的 JSON 格式和 COCO 完全不同。我个人觉得,LabelMe 更适合做语义分割实例分割的标注,因为它天然支持多边形。

3.2.1 结构长什么样?

LabelMe JSON 是每张图片一个 JSON 文件。不像 COCO 把所有图片的标注塞到一个大文件里。来看个例子:

{
  "version": "5.0.1",
  "flags": {},
  "shapes": [
    {
      "label": "car",
      "points": [
        [120, 150],
        [200, 150],
        [200, 300],
        [120, 300]
      ],
      "group_id": null,
      "shape_type": "polygon",
      "flags": {}
    }
  ],
  "imagePath": "img_001.jpg",
  "imageData": null,
  "imageHeight": 1080,
  "imageWidth": 1920
}

你想想看,这里最核心的是 shapes 数组。每个 shape 就是一个标注对象,points 是多边形的顶点坐标。如果是矩形,shape_type 可以写成 rectangle,但一般建议统一用 polygon

3.2.2 和 COCO 的关键区别

对比项 COCO JSON LabelMe JSON
文件组织 所有图片一个文件 每张图片一个文件
标注形状 矩形框 (bbox) 多边形 (polygon)
坐标格式 [x, y, w, h] [[x1,y1], [x2,y2], ...]
适用场景 目标检测、实例分割 语义分割、实例分割
注意: LabelMe 的 imageData 字段有时会包含 base64 编码的图片数据。如果你导出时不需要,记得设为 null,不然 JSON 文件会变得巨大。我见过一个标注文件因为带了图片数据,直接飙到 50MB……

3.3 两种格式的转换思路

实际项目中,你经常需要在 COCO 和 LabelMe 之间来回转换。比如你用 LabelMe 标注了数据,但训练模型时要用 COCO 格式。怎么办?

我一般这样处理:

  1. LabelMe → COCO: 遍历所有 LabelMe JSON,把 shapes 里的多边形转成 bbox(取最小外接矩形),然后合并到一个大 JSON 里。
  2. COCO → LabelMe: 把 COCO 的 annotations 拆开,每个 bbox 转成四个点的多边形,生成独立的 JSON 文件。

核心逻辑: 转换的本质就是「坐标格式的映射」和「文件结构的重组」。别被复杂的字段吓到,抓住这两个核心,你就能写出通用的转换脚本。

3.4 本章小结

COCO JSON 和 LabelMe JSON,一个适合大规模数据集,一个适合灵活标注。我个人建议:

  • 如果你做目标检测,优先用 COCO 格式。
  • 如果你做分割任务,或者标注工具是 LabelMe,那就用 LabelMe 格式。
  • 不管用哪种,一定要写一个验证脚本,检查坐标、类别 id 是否正确。

嗯,今天就先聊到这儿。这两种格式搞明白了,后面再讲其他格式(比如 YOLO、Pascal VOC)就轻松多了。