3 个标注框、3 个类别,生成 COCO 风格的 JSON,共 869 个字符。原始文件校验 0 个问题; 故意改坏三处(框越界、类别 id 拼错、area 对不上)之后,校验器抓出 4 条问题。
前面四个实例都在「取信息」,这一节收口:把标好的东西存成下游能直接读的格式,并且能验出错误。 这是标注流程的最后一公里。
一、标注文件不是随便存存
标完的点、框、多边形,得存成一个大家都能读的格式,否则训练脚本还得为每个标注员写一个解析器。
目标检测里最通用的是 COCO 格式:一个 JSON,三个顶层键——images(图有哪些、多宽多高)、
categories(有哪些类别)、annotations(每个框的位置、类别、面积)。
这套格式看着啰嗦,但每一条都有用:images 让训练脚本知道要不要缩放坐标,
categories 保证类别 id 连续,annotations 里的 area 用来分大小目标。
自己定一套简单的格式也行,但一旦要和开源工具对接,就会痛苦。用通用的,省事。
二、三个必须校验的东西
- 框在图内。
x加width不能超过图宽。越界的框在训练时会被截断或者直接崩,两种都不好。 - 类别 id 合法。
category_id必须在categories里存在。 拼错一个数字,这条标注就永远学不到,而且不报错。 - area 和 bbox 一致。
area必须等于width乘height。 这条最隐蔽——训练不报错,评测算指标时才出问题。 第三条为什么重要?因为目标检测的评测要按目标大小分组算分数(小目标、中目标、大目标)。 分组靠的就是area。area 错了,分组就错,指标全偏。 所以提交前一定要跑一遍结构校验。这个脚本二十行就能写完,但能省掉几天的排查。
三、校验器抓到了什么
原始文件 0 个问题。改坏三处之后抓出 4 条。 多出来的一条,是因为改坏第一个框那一处同时触发了「越界」和「area 不符」两条规则。 一个问题被两条规则命中,是正常现象,不是重复报错。 改坏的另外两处各触发一条:类别 id 改成 9(不存在),area 从 5400 改成 9999(和 90 乘 70 对不上)。 这说明校验器的规则是独立的、可叠加的。 写校验器时就该这么设计:每条规则只管一件事,别写成一个大 if。
四、界面上的清单(我没有跑)
书里的最后一步是在 VGG 里把标注导出成 JSON。沙箱没有浏览器,没跑。
1. 在 VIA 里把所有图标的框标完。
2. 检查类别名有没有拼错、有没有多余空格——这是最常见的脏数据来源。
3. 用导出功能选 JSON 格式,勾上「包含图片名」。
4. 导出的文件直接用文本编辑器看一眼,确认顶层结构和类别表对得上。
5. 跑结构校验脚本,把问题清零再交给训练。
第 2 步值得强调:路灯 和 路灯 (带尾空格)在两份文件里是不同的类别,
模型会把它们学成两个东西。这种错肉眼几乎看不出来。
五、动手 Demo:标注文件:生成 COCO 风格 JSON 并做一致性校验
造 3 个框和 3 个类别(路灯、配电箱、监控杆),拼成 COCO 风格的三段结构, 序列化成 JSON 并打出前几行;写一个校验器查四件事——id 重复、类别不存在、框越界、area 与 bbox 不符; 然后故意改坏三处,再验一次。
anns.append({'id': i, 'image_id': iid, 'category_id': cid,
'bbox': [x, y, w, h], 'area': w * h, 'iscrowd': 0})
if x < 0 or y < 0 or x + w > W or y + h > H:
errs.append(u'标注 %d 的框超出图像边界' % a['id'])
if abs(a['area'] - w * h) > 1e-6:
errs.append(u'标注 %d 的 area 与 bbox 不符' % a['id'])
实跑输出:
--------------------------------------------------------------------
标注文件:生成 COCO 风格的 JSON 并做一致性校验
--------------------------------------------------------------------
图像 640 × 480
类别数 3
标注框 3 个
JSON 字符数 869
顶层键 images、categories、annotations
前几行长这样:
{
"images": [
{
"id": 1,
"file_name": "street_01.jpg",
"width": 640,
"height": 480
原始文件的校验结果:
问题数 0
故意改坏三处之后再校验:
问题数 4
标注 1 的框超出图像边界
标注 1 的 area 与 bbox 不符
标注 2 的类别 9 不存在
标注 3 的 area 与 bbox 不符
三处改动被校验器抓出 4 条问题——改坏第一个框那一处同时触发了「越界」和「area 不符」,一个问题会被两条规则同时命中,这是正常的。
这三类错都是标注文件里最常见的:框越界、类别 id 拼错、area 和 bbox 对不上。
第三条尤其隐蔽——训练时不报错,评测时算 mAP 要靠 area 分大小目标,area 一错,指标直接偏。所以提交前一定要跑一遍结构校验。
JSON 一共 869 个字符,三个顶层键都在。
这个体积说明 COCO 格式的开销主要不在数据,在结构——三条标注就要这么多字。
原始文件 0 条问题,说明生成逻辑本身是对的,框都在界内、area 都是现算的。
改坏之后 4 条问题。想一下为什么不是 3 条:因为改坏框那一处同时踩了两条规则。
写校验器时这种「一处错触发多条」很常见,梳理时要按问题去重,别按报错条数算。
这三类错在真实标注文件里几乎一定会出现。
特别是 area,很多导出工具压根不写这个字段,或者写的是多边形的面积而不是框的面积。
30 秒实验
- 再加一条规则:检查 bbox 的宽高是否为正数,看能不能抓到零宽框。
- 把类别名改成带尾空格的「路灯 」,看现有校验器能不能发现。
- 想一想:为什么 area 错了训练不报错,评测才出问题?
常见误区
- 「JSON 能读出来就行」——结构对不代表语义对,越界和 id 拼错都不报错。
- 「area 可以随便填」——评测按 area 分大小目标,填错指标全偏。
- 「类别名差个空格无所谓」——会被当成两个不同类别,模型学成两回事。
自测三问(点开对答案)
1. COCO 格式的三个顶层键是什么? —— images、categories、annotations。 2. 为什么 area 和 bbox 必须一致? —— 评测按目标大小分组算分,分组靠 area;area 错了分组错,指标全偏。 3. 为什么改坏三处会报出四条问题? —— 改坏第一个框同时触发越界和 area 不符两条规则,一处错可被多条命中。第七章到此结束。下一章进神经网络:从感知机一路讲到六种架构。
- ☐ (本章完,下一节 8.1.1 概念:什么是神经网络?)