最近被分配了一个任务,将crowdhuman的标注转换成coco。然鹅,刚进实验室没几天,真的是啥也不会,边用边学!!!呃,所以先从coco数据集的了解和标注格式先开始吧。参考了几篇博客资料,整理了下,好以后自己复习翻阅。参考链接在结尾。
推荐一篇博文:Dataset - COCO Dataset 数据特点,写得很详细。object instances 、object keypoints、 image captions的标注形式介绍都有。
在python里面,读取出json标注格式文件,实际上是一个dict,如下所示:
{
"info": info,
"licenses": [license],
"images": [image],
"annotations": [annotation],
"categories": [category]
}
包含5个字段信息:info, licenses, images, annotations,categories。上面3种标注类型共享的字段信息有:info、image、license。不共享的是annotation和category这两种字段,他们在不同类型的JSON文件中是不一样的。
object instances中,概述一下其中每个字段的结构与包含的信息:
(1)images字段列表元素的长度等同于划入训练集(或者测试集)的图片的数量;
(2)annotations字段列表元素的数量等同于训练集(或者测试集)中bounding box的数量;
(3)categories字段列表元素的数量等同于类别的数量,coco为80(2017年);
以下的各个字段,都是object instances中的。
info字段结构
info: {
"year": int,# 年份
"version": str,# 版本
"description": str, # 数据集描述
"contributor": str,# 提供者
"url": str,# 下载地址
"date_created": datetime
}
info字段的信息一般如下,在写程序时一般用不到:
"info":{
"description":"This is stable 1.0 version of the 2014 MS COCO dataset.",
"url":"http:\/\/mscoco.org",
"version":"1.0","year":2014,
"contributor":"Microsoft COCO group",
"date_created":"2015-01-27 09:11:52.357475"
},
licenses字段结构
license{
"id": int,
"name": str,
"url": str,
}
licenses字段的信息如下,在写程序时一般用不到:
{
"url":"http:\/\/creativecommons.org\/licenses\/by-nc-sa\/2.0\/",
"id":1,
"name":"Attribution-NonCommercial-ShareAlike License"
}
images字段结构:
image{
"id": int,# 图片的ID编号(每张图片ID是唯一的)
"width": int,#宽
"height": int,#高
"file_name": str,# 图片名
"license": int,
"flickr_url": str,# flickr网路地址
"coco_url": str,# 网路地址路径
"date_captured": datetime # 数据获取日期
}
Images是包含多个image实例的数组,对于一个image类型的实例:
{
"license":3,
"file_name":"COCO_val2014_000000391895.jpg",
"coco_url":"http:\/\/mscoco.org\/images\/391895",
"height":360,"width":640,"date_captured":"2013-11-14 11:18:45",
"flickr_url":"http:\/\/farm9.staticflickr.com\/8186\/8119368305_4e622c8349_z.jpg",
"id":391895
}
每一个image的实例是一个dict。其中有一个id字段,代表的是图片的id,每一张图片具有唯一的一个独特的id。
annotations字段是包含多个annotation实例的一个列表,annotation类型本身又包含了一系列的字段,如这个目标的category id和segmentation mask。segmentation格式取决于这个实例是一个单个的对象(即iscrowd=0,将使用polygons格式)还是一组对象(即iscrowd=1,将使用RLE格式)。如下所示:
annotation{
"id": int, # 对象ID,因为每一个图像有不止一个对象,所以要对每一个对象编号(每个对象的ID是唯一的)
"image_id": int,# 对应的图片ID(与images中的ID对应)
"category_id": int,# 类别ID(与categories中的ID对应)
"segmentation": RLE or [polygon],# 对象的边界点(边界多边形,此时iscrowd=0)。
#segmentation格式取决于这个实例是一个单个的对象(即iscrowd=0,将使用polygons格式)还是一组对象(即iscrowd=1,将使用RLE格式)
"area": float,# 区域面积
"bbox": [x,y,width,height], # 定位边框 [x,y,w,h]
"iscrowd": 0 or 1 #见下
}
注:单个的对象(iscrowd=0)可能需要多个polygon来表示,比如这个对象在图像中被挡住了。而iscrowd=1时(将标注一组对象,比如一群人)的segmentation使用的就是RLE格式。
什么是RLE格式:
RLE:Run Length Encoding(行程长度压缩算法)
在机器视觉领域的深度学习中,每个数据集都有一份标注好的数据用于训练神经网络。
为了节省空间,很多数据集的标注文件使用RLE的格式,比如 kaggle 挑战赛的 Airbus Ship Detection Challenge。
但是神经网络的输入一定是一张图片,为此必须把RLE格式的文件转变为图像格式。
图像格式主要又分为 .jpg 和 .png 两种格式,其中label数据一定不能使用 .jpg,因为它因为压缩算算法的原因,会造成图像失真,图像各个像素的值可能会发生变化。分割任务的数据集的 label 图像中每一个像素都代表了该像素点所属的类别,所以这样的失真是无法接受的。为此只能使用 .png 格式作为label,pascol voc 和 coco 数据集正是这样做的。
注意啊,iscrowd=0那么segmentation就是polygon格式;只要iscrowd=1那么segmentation就是RLE格式。另外,每个对象(不管是iscrowd=0还是iscrowd=1)都会有一个矩形框bbox,矩形框左上角的坐标和矩形框的长宽会以数组的形式提供,数组第一个元素就是左上角的横坐标值。polygon格式比较简单,这些数按照相邻的顺序两两组成一个点的xy坐标,如果有n个数(必定是偶数),那么就是n/2个点坐标。
area是area of encoded masks,是标注区域的面积。如果是矩形框,那就是高乘宽;如果是polygon或者RLE,那就复杂点。
在一个annotation的实例中有两个id,其中image_id指的是这个annotation属于哪一张图片,即前面提到的图片的id,另外一个“id”指的是这个annotation的一个id。
注意: annotation的image_id是不唯一的,代表的是,这个annotation是指向image_id图片的标注,因为图片的标注不止一个,可能有好几个标注。
一个annotation为segmentation是polygon格式的实例:
{
"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是一个包含多个category实例的列表,而一个category结构体描述如下:
{
"supercategory": str,# 主类别
"id": int,# 类对应的id (0 默认为背景)
"name": str # 子类别
}
categories类型实例:
{
"supercategory": "person",
"id": 1,
"name": "person"
},
{
"supercategory": "vehicle",
"id": 2,
"name": "bicycle"
}