COCO数据集是我们经常使用的一个数据集,并且 COCO数据集格式也很受大家欢迎,但不同于 VOC数据格式,COCO是将所有的标注数据存放在一个json文件中,使得查看的时候云里雾里,最近也在用COCO数据集做实例分割,顺道整理下,为自己扫清一些盲区,如有解释不清的地方,欢迎留言
官网地址: https://cocodataset.org/
标注文件的格式说明: https://cocodataset.org/#format-data
MC COCO2017年主要包含以下四个任务:目标检测与分割、图像描述、人体关键点检测,如下所示:
annotations: 对应标注文件夹
├── instances_train2017.json : 对应目标检测、分割任务的
├── instances_val2017.json : 对应目标检测、分割任务的验证集标注文件
├── captions_train2017.json : 对应图像描述的训练集标注文件
├── captions_val2017.json : 对应图像描述的验证集标注文件
├── person_keypoints_train2017.json : 对应人体关键点检测的训练集标注文件
└── person_keypoints_val2017.json : 对应人体关键点检测的验证集标注文件夹
Object segmentation : 目标级分割
Recognition in context : 图像情景识别
Superpixel stuff segmentation : 超像素分割
330K images (>200K labeled) : 超过33万张图像,标注过的图像超过20万张
1.5 million object instances : 150万个对象实例
80 object categories : 80个目标类别
91 stuff categories : 91个材料类别
5 captions per image : 每张图像有5段情景描述
250,000 people with keypoints : 对25万个人进行了关键点标注
""" 注意 """
COCO数据集格式中,bbox 的保存格式为 [x, y, w, h]
如果需要转换为[x1,y1,x2,y2],可以通过如下进行转换
bbox = [x1, y1, x1 + w - 1, y1 + h - 1]
JSON文件的基本格式,以实例分割为例,主要有五个部分:info、licenses、images、annotations、categories
- info记录关于数据集的一些基本信息
"info":{
"description":"This is stable 1.0 version of the 2014 MS COCO dataset.",
"url":"http:\/\/mscoco.org",
"version":"1.0",
"year":2017,
"contributor":"Microsoft COCO group",
"date_created":"2017-01-27 09:11:52.357475"
}
- licenses是数据集遵循的一些许可
"licenses":{
"url":"http:\/\/creativecommons.org\/licenses\/by-nc-sa\/2.0\/",
"id":1,
"name":"Attribution-NonCommercial-ShareAlike License"
}
- images是数据集中包含的图像,长度等于图像的数量
"images":{
"coco_url": "",
"date_captured": "",
"file_name": "000001.jpg",
"flickr_url": "",
"id": 1,
"license": 0,
"width": 416,
"height": 416
}
- annotations是数据集中包含的实例掩膜,数量等于bounding box的数量。segmentation格式取决于这个实例是一个单个的对象(即iscrowd=0,将使用polygons格式,以多边形顶点表示)还是一组对象(即iscrowd=1,将使用RLE格式,mask编码)
"annotations":{
"id": int,
"image_id": int,
"category_id": int,
"segmentation": RLE or [polygon],
"area": float,
"bbox": [x,y,width,height],
"iscrowd": 0 or 1
}
# 以多边形顶点形式表示的实例:
"annotations":{
"segmentation": [[510.66,423.01,511.72,420.03,510.45......]],
"area": 702.1057499999998,
"iscrowd": 0,
"image_id": 289343,
"bbox": [473.07,395.93,38.65,28.67],
"category_id": 18,
"id": 1768
}
- categories是数据集中的类别信息
"categories":{
"id": int,
"name": str,
"supercategory": str,
}
解析其中的类别ID、图像ID:
coco = COCO(annotation_file.json)
catIds = coco.getCatIds()
imgIds = coco.getImgIds()
mask 读取模式
对于灰度模式,直接使用cv2.imwrite()函数进行保存即可,只不过读取时,需要按照灰度图的方式读取|(用OpenCV或者PIL格式均可以):
# 方式一:
label = cv2.imread(label_path, 0)
# 方式二:
label = np.asarray(Image.open(label_path), dtype=np.int32)
调色板模式,mask保存 方式如下:
def save_colored_mask(mask, save_path):
lbl_pil = Image.fromarray(mask.astype(np.uint8), mode="P")
colormap = imgviz.label_colormap()
lbl_pil.putpalette(colormap.flatten())
lbl_pil.save(save_path)
需要先将array格式的mask转为PIL.Image格式,然后,使用imgviz中的Label colormap给mask添加调色板,最后保存PIL.Image格式的图像即可。读取时,则需要同样使用PIL.Image格式来读取,然后转为array,而不可以使用OpenCV进行读取:
# 正确的读取方式
label = np.asarray(Image.open(label_path), dtype=np.int32)
# 错误的读取方式:因为调色板模式下,使用cv2.imread(label_path, 0)
# 会默认以BGR转灰度图的模式读取,从而导致得到的label值不一致
label = cv2.imread(label_path, 0)
mask 可视化
将 mask 与原图叠加可视化的方式有两种,可通过OpenCV的加权叠加也可以采用Pillow的 blend方法
# OpenCV方式:
image = cv2.imread('2007_000033.jpg')
mask = cv2.imread('2007_000033.png')
mask_img = cv2.addWeighted(image, 0.5, mask, 0.7, 0.9)
cv2.imwrite("vis.jpg", mask_img)
# PIL方式:
image = Image.open('2007_000033.jpg')
mask = Image.open('2007_000033.png')
mask_img = Image.blend(image.convert('RGBA'), mask.convert('RGBA'), 0.7)
mask_img.save("vis2.png")