本文首先简单介绍了coco数据集的整体构成,之后重点介绍了标注类型为object detection的所有字段的含义。
COCO通过大量使用Amazon Mechanical Turk来收集数据。COCO数据集现在有5种标注类型:object detection, keypoint detection, stuff segmentation, panoptic segmentation,以及image captioning,使用json文件存储,一个json文件包括info、licenses、images、以及annotations四个基本类型,其中info表示test/val/train所有实例的整体信息,如创建年份、版本等等,而licenses、images、annotations都是包含多个对应实例的数组。
1. {
2. "info": info,
3. "images": [image],
4. "annotations": [annotation],
5. "licenses": [license],
6. }
5种标注类型(object detection, keypoint detection, stuff segmentation, panoptic segmentation)共享info、licenses、images基本类型,结构如下所示:
1. info{
2. "year": int,
3. "version": str,
4. "description": str,
5. "contributor": str,
6. "url": str,
7. "date_created": datetime,
8. }
9.
10. image{
11. "id": int,
12. "width": int,
13. "height": int,
14. "file_name": str,
15. "license": int,
16. "flickr_url": str,
17. "coco_url": str,
18. "date_captured": datetime,
19. }
20.
21. license{
22. "id": int,
23. "name": str,
24. "url": str,
25. }
其中“flickr_url”字段是flickr是一个存放图片的网站,指的是图片在这个网站上的网址,这个字段可以不写。而“coco_url”也表示图片地址,可以是http格式的,也可以使用“file://”+绝对文件夹目录的格式,如: “file:///ldap_shared/coco/train2017/1_toy001040.PNG”
前面提到info、images、license这三个基本类型是共享的,而annotations类型对于5种标注类型呈现多态,下面只介绍在object detection标注类型中annotations的情况(如下所示),下面将详细展示annotation中的每个字段的含义。
1. annotation{
2. "id": int,
3. "image_id": int,
4. "category_id": int,
5. "segmentation": RLE or [polygon],
6. "area": float,
7. "bbox": [x,y,width,height],
8. "iscrowd": 0 or 1,
9. }
10.
11. categories[{
12. "id": int,
13. "name": str,
14. "supercategory": str,
15. }]
所有的图片上有多少对象就有多少对应的annotation,id代表annotation id,每张图片上每个对象都对应一个annotation id,image_id代表存在这个对象的图片id,因为一张图片可能有多个对象,所以存在一张图片对应多个annotation id的情况,每个对象又有一个对应的类别,即category_id ,可能有点绕,给大家举个例子,下面分别是coco中某一张图片及其对应的标注文件:
1. {"segmentation": [[376.45,226.52,416.36,215.73,437.93,210.34,439.01,185.53,445.48,165.03,429.3,145.62,418.52,119.73,414.2,116.49,407.73,127.28,404.49,130.52,405.57,121.89,412.04,117.57,410.97,108.94,419.6,74.43,419.6,70.11,423.91,38.83,451.96,20.49,484.31,22.65,497.26,22.65,515.6,46.38,537.17,77.66,542.56,93.84,556.58,103.55,556.58,126.2,542.56,131.6,531.78,180.13,540.4,206.02,588.94,239.46,640.0,268.58,640.0,480.0,293.39,477.84,311.73,442.25,330.07,450.88,336.54,333.3,353.8,263.19]],
2. "area": 97618.01770000001,
3. "iscrowd": 0,
4. "image_id": 6894,
5. "bbox": [293.39,20.49,346.61,459.51],
6. "category_id": 1,
7. "id": 493059},
8. {"segmentation": [[0.0,86.29,31.28,91.69,74.43,94.92,85.21,91.69,92.76,88.45,117.57,88.45,138.07,94.92,156.4,110.02,172.58,118.65,184.45,125.12,204.94,133.75,221.12,129.44,243.78,130.52,275.06,133.75,291.24,130.52,300.94,129.44,376.45,142.38,415.28,115.42,419.6,134.83,432.54,158.56,436.85,174.74,433.62,192.0,436.85,203.87,433.62,212.49,367.82,230.83,330.07,309.57,318.2,362.43,317.12,428.22,294.47,474.61,1.08,473.53],[537.17,195.24,634.25,204.94,638.56,210.34,637.48,264.27,583.55,234.07,545.8,211.42,533.93,199.55]],
9. "area": 131594.76034999997,
10. "iscrowd": 0,
11. "image_id": 6894,
12. "bbox": [0.0,86.29,638.56,388.32],
13. "category_id": 22,
14. "id": 580616},
如coco中图片所示,该图片上有人和大象两个对象,因此在标注文件中也使用了两个annotation字段来分别表示这两个对象,这两个对象的image_id相同,category_id不同。
segmentation格式有两种表示,polygon以及RLE。
polygon格式:
1. {
2. "segmentation": [[510.66,423.01,511.72,420.03,510.45......]],
3. "area": 702.1057499999998,
4. "iscrowd": 0,
5. "image_id": 289343,
6. "bbox": [473.07,395.93,38.65,28.67],
7. "category_id": 18,
8. "id": 1768
9. },
polygon格式比较简单,这些数按照相邻的顺序两两组成一个点的xy坐标,如果有n个数(必定是偶数),那么就是n/2个点坐标。
RLE格式:
1. {
2. "segmentation":
3. {
4. u'counts': [272, 2, 4, 4, 4, 4, 2, 9, 1, 2, 16, 43, 143, 24......],
5. u'size': [240, 320]
6. }
7. "area": 18419,
8. "iscrowd": 1,
9. "image_id": 448263,
10. "bbox": [1,0,276,122],
11. "category_id": 1,
12. "id": 900100448263
13. }
RLE全称(run-length encoding),称变动长度编码法(run coding),在控制论中对于二值图像而言是一种编码方法,对连续的黑、白像素数(游程)以不同的码字进行编码。举个简单的例子:对于一个很长的二值的序列,如00000111100111110……,我们直接存储整个二值序列很浪费空间,如果使用RLE编码方法的话,我们存储的是其连续的0/1的数目,对于这个二值序列用RLE可以表示为54251……。RLE所占字节的大小和边界上的像素数量是正相关的。RLE格式带来的好处就是当基于RLE去计算目标区域的面积以及两个目标之间的unoin和intersection时会非常有效率。上面的segmentation中的counts数组和size数组共同组成了这幅图片中的分割 mask。其中size是这幅图片的宽高。因为在这幅图像中,每一个像素点要么在目标区域中,要么在背景中,所以这副图像的分割结果是一个bool量:如果该像素在目标区域中为true那么在背景中就是False;如果该像素在目标区域中为1那么在背景中就是0。对于一个240x320的图片来说,一共有76800个像素点,根据每一个像素点在不在目标区域中,我们就有了76800个bit,使用RLE编码格式存储分割结构既可以直观地表示这些bit,也可以大大节省存储空间。
iscrowd=0的时候,表示这是一个单独的物体,轮廓用Polygon(多边形的点)表示,iscrowd=1的时候表示多个没有分开的物体,轮廓用RLE编码表示(只要是iscrowd=0那么segmentation就是polygon格式;只要iscrowd=1那么segmentation就是RLE格式)。比如说一张图片里面有三个人,一个人单独站一边,另外两个搂在一起(标注的时候距离太近分不开了),这个时候,单独的那个人的注释里面的iscrowd=0,segmentation用Polygon表示,而另外两个用放在同一个annotation的数组里面用一个segmentation的RLE编码形式表示(注意,单个的对象(iscrowd=0)可能需要多个polygon来表示,比如这个对象在图像中被挡住了)。
每个对象(不管是iscrowd=0还是iscrowd=1)都有一个矩形框bbox ,矩形框左上角的坐标和矩形框的长宽会以数组的形式提供,数组第一个元素就是左上角的横坐标值。
area是area of encoded masks,是标注区域的面积。如果是矩形框,那就是高乘宽;如果是polygon或者RLE,那就复杂点。
如下图所示,其中train2017、test2017、val2017文件夹中保存的是用于训练、测试、验证的图片,而annotations文件夹保存的是这些图片对应的标注信息,分别存在instance_test2017、instance_test2017、instance_val2017三个json文件中。