MS COCO segmentation编码存储(RLE&polygon)

读coco数据集的代码接口了解segmentation的处理方法

COCO数据集是微软团队制作的一个数据集,通过这个数据集我们可以训练到神经网络对图像进行detection,classification,segmentation,captioning。具体介绍请祥见官网。

  • annotation格式介绍
  • mask存储处理方式简单介绍
  • 相关代码分析
  • 一个实例

annotation格式介绍

//从官网拷贝下来的
{
    "info": info,
    "images": [image],
    "annotations": [annotation],
    "licenses": [license],
}

info{
    "year": int,
    "version": str,
    "description": str,
    "contributor": str,
    "url": str,
    "date_created": datetime,
}

image{
    "id": int,
    "width": int,
    "height": int,
    "file_name": str,
    "license": int,
    "flickr_url": str,
    "coco_url": str,
    "date_captured": datetime,
}

license{
    "id": int,
    "name": str,
    "url": str,
}
----------

    Object Instance Annotations

    Each instance annotation contains a series of fields, including the category id and segmentation mask of the object. The segmentation format depends on whether the instance represents a single object (iscrowd=0 in which case polygons are used) or a collection of objects (iscrowd=1 in which case RLE is used). Note that a single object (iscrowd=0) may require multiple polygons, for example if occluded. Crowd annotations (iscrowd=1) are used to label large groups of objects (e.g. a crowd of people). In addition, an enclosing bounding box is provided for each object (box coordinates are measured from the top left image corner and are 0-indexed). Finally, the categories field of the annotation structure stores the mapping of category id to category and supercategory names.

    中文翻译如下: 每个实例注释包含一系列字段,这些字段有category id和segmentation mask。segementation字段的格式取决于实例是代表单个物体(具体来说iscrowd=0,这时候就会用到polygon,也就是多边形)还是目标的集合体(此时iscrowd=1, 会用到RLE,后面解释这个的意思)。注意到单个目标可能需要多个多边形来表示,例如在被遮挡的情况下。群体注释是用来标注目标的集合体(例如一群人)。除此之外,每个目标都会有一个封闭的外接矩形框来标记(矩形框的坐标从图像的左上角开始记录,没有索引)。最后,类别字段存储着category id到category和父级category名字的映射。

    
    
    annotation{
        "id": int,
        "image_id": int,
        "category_id": int,
        "segmentation": RLE or [polygon],
        "area": float,
        "bbox": [x,y,width,height],
        "iscrowd": 0 or 1,
    }
    
    categories[{
        "id": int,
        "name": str,
        "supercategory": str,
    }]
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    mask存储处理方式简单介绍

    上面提到coco数据集使用了两种方式进行mask存储,一是polygon,一是RLE。polygon比较好理解,就是多边形嘛!RLE是什么呢?

    简单点来讲,RLE是一种压缩方法,也是最容易想到的压缩方式。

    举个例子:M = [0,0,0,1,1,1,1,1,1,0,0],则M的RLE编码为[3,6,2],当然这是针对二进制进行的编码,也是coco里面采用的。RLE远不止这样简单,我们这里并不着重讲RLE,请百度吧。

    代码中注释说的

    # RLE is a simple yet efficient format for storing binary masks. RLE
    # first divides a vector (or vectorized image) into a series of piecewise
    # constant regions and then for each piece simply stores the length of
    # that piece. For example, given M=[0 0 1 1 1 0 1] the RLE counts would
    # be [2 3 1 1], or for M=[1 1 1 1 1 1 0] the counts would be [0 6 1]
    # (note that the odd counts are always the numbers of zeros). Instead of
    # storing the counts directly, additional compression is achieved with a
    # variable bitrate representation based on a common scheme called LEB128.
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    解释一下就是:RLE将一个二进制向量分成一系列固定长度的片段,对每个片段只存储那个片段的长度。例如M=[0 0 1 1 1 0 1], RLE就是[2 3 1 1];M=[1 1 1 1 1 1 0], RLE为[0 6 1],注意奇数位始终为0的个数。另外,也使用一个基于LEB128的通用方案的可变比特率来完成额外的压缩。

    相关代码分析

    COCO是官方给出的一个api接口,具体来说是一个python和C编写的工具代码。mask相关内容是用c编写的。
    
    //代码来源于FastMaskRCNN
    
    **1.convert img and annotation to TFRecord**
    //加载标注文件
    coco = COCO(annFile)
    //加载类别信息
    cats = coco.loadCats(coco.getCatIds())
    print ('%s has %d images' %(split_name, len(coco.imgs)))
    //将img信息转存
    imgs = [(img_id, coco.imgs[img_id]) for img_id in coco.imgs]
    //获取分片信息
    num_shards = int(len(imgs) / 2500)
    num_per_shard = int(math.ceil(len(imgs) / float(num_shards)))
    
    2.获取coco中的mask,bbox信息
    def _get_coco_masks(coco, img_id, height, width, img_name):
      """ get the masks for all the instances
      Note: some images are not annotated
      Return:
        masks, mxhxw numpy array
        classes, mx1
        bboxes, mx4
      """
      annIds = coco.getAnnIds(imgIds=[img_id], iscrowd=None)
      # assert  annIds is not None and annIds > 0, 'No annotaion for %s' % str(img_id)
      anns = coco.loadAnns(annIds)
      coco.showAnns(anns)
      # assert len(anns) > 0, 'No annotaion for %s' % str(img_id)
      masks = []
      classes = []
      bboxes = []
      mask = np.zeros((height, width), dtype=np.float32)
      segmentations = []
      for ann in anns:
        m = coco.annToMask(ann) # zero one mask
        assert m.shape[0] == height and m.shape[1] == width, \
                'image %s and ann %s dont match' % (img_id, ann)
        masks.append(m)
        cat_id = _cat_id_to_real_id(ann['category_id'])
        classes.append(cat_id)
        bboxes.append(ann['bbox'])
        m = m.astype(np.float32) * cat_id
        mask[m > 0] = m[m > 0]
    
      masks = np.asarray(masks)
      classes = np.asarray(classes)
      bboxes = np.asarray(bboxes)
      # to x1, y1, x2, y2
      if bboxes.shape[0] <= 0:
        bboxes = np.zeros([0, 4], dtype=np.float32)
        classes = np.zeros([0], dtype=np.float32)
        print ('None Annotations %s' % img_name)
        LOG('None Annotations %s' % img_name)
      bboxes[:, 2] = bboxes[:, 0] + bboxes[:, 2]
      bboxes[:, 3] = bboxes[:, 1] + bboxes[:, 3]
      gt_boxes = np.hstack((bboxes, classes[:, np.newaxis]))
      gt_boxes = gt_boxes.astype(np.float32)
      masks = masks.astype(np.uint8)
      mask = mask.astype(np.uint8)
      assert masks.shape[0] == gt_boxes.shape[0], 'Shape Error'
    
      return gt_boxes, masks, mask
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    一个实例

    # get all images containing given categories, select one at random
    catIds = coco.getCatIds(catNms=['animal']);
    imgIds = coco.getImgIds(catIds=catIds );
    imgIds = coco.getImgIds(imgIds = [324139])
    img = coco.loadImgs(imgIds[np.random.randint(0,len(imgIds))])[0]
    
    
    print imgIds
    print img['coco_url']
    I = io.imread(img['coco_url'])
    plt.axis('off')
    plt.imshow(I)
    plt.show()  //图一
    
    
    
    plt.imshow(I); plt.axis('off')
    annIds = coco.getAnnIds(imgIds=img['id'], catIds=catIds, iscrowd=None)
    anns = coco.loadAnns(annIds)
    print len(anns)
    masks = []
    showonce = True
    for ann in anns:
        if type(ann['segmentation']) == list and showonce:
            print ann['segmentation']
            showonce = False
        if type(ann['segmentation']) != list:
            print ann['segmentation']
        m = coco.annToMask(ann)
        masks.append(m)
    print len(masks)
    coco.showAnns(anns) //图二
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    15
    [[151.06, 113.6, 168.95, 102.49, 182.53, 92.62, 193.64, 80.28, 203.51, 70.4, 208.45, 61.76, 206.6, 53.74, 209.68, 49.42, 220.17, 50.04, 220.79, 55.59, 222.64, 59.3, 222.64, 59.91, 227.58, 66.7, 228.2, 77.19, 228.2, 83.98, 228.2, 87.06, 228.2, 92.0, 227.58, 96.32, 220.79, 101.87, 213.39, 104.96, 205.36, 111.75, 202.9, 113.6, 201.04, 114.22, 202.9, 123.47, 200.43, 129.64, 200.43, 125.94, 198.58, 113.6, 190.55, 111.75, 181.91, 113.6, 168.95, 114.83, 168.95, 114.83, 162.17, 120.39, 157.23, 119.15, 146.74, 117.92, 142.42, 115.45]]
    {u’counts’: [113441, 1, 423, 6, 427, 7, 3, 1, 422, 8, 3, 1, 421, 9, 2, 2, 420, 10, 2, 1, 421, 10, 1, 2, 419, 12, 1, 2, 418, 15, 419, 15, 418, 16, 418, 16, 418, 15, 419, 15, 418, 16, 417, 16, 418, 16, 418, 15, 419, 14, 419, 14, 419, 14, 420, 13, 420, 13, 421, 11, 422, 11, 423, 10, 423, 10, 424, 9, 425, 8, 426, 7, 427, 6, 427, 5, 429, 5, 429, 5, 429, 5, 429, 5, 428, 5, 429, 5, 428, 6, 428, 6, 428, 6, 428, 5, 429, 5, 429, 5, 408, 7, 14, 5, 407, 9, 13, 5, 406, 11, 11, 5, 407, 12, 9, 6, 406, 13, 9, 6, 404, 15, 8, 7, 402, 18, 7, 7, 401, 20, 6, 6, 401, 21, 6, 6, 400, 34, 399, 35, 399, 12, 1, 22, 398, 13, 3, 19, 399, 12, 6, 17, 399, 12, 8, 15, 399, 12, 10, 13, 400, 10, 13, 10, 401, 10, 15, 8, 400, 11, 17, 5, 401, 10, 20, 2, 402, 11, 423, 11, 423, 11, 423, 11, 423, 12, 422, 13, 422, 13, 421, 14, 421, 14, 420, 15, 420, 14, 420, 15, 420, 15, 419, 16, 419, 16, 418, 17, 418, 17, 418, 17, 418, 17, 417, 18, 4, 4, 409, 24, 411, 23, 412, 22, 412, 22, 411, 23, 411, 22, 412, 22, 412, 22, 413, 21, 413, 20, 414, 20, 414, 19, 416, 18, 416, 17, 417, 17, 417, 17, 417, 16, 419, 14, 420, 14, 421, 13, 422, 11, 424, 10, 425, 8, 428, 4, 112407, 8, 422, 16, 416, 19, 414, 21, 2, 6, 405, 30, 403, 32, 402, 33, 401, 34, 400, 35, 400, 34, 400, 34, 401, 33, 402, 32, 277], u’size’: [434, 640]}
    15


    MS COCO segmentation编码存储(RLE&polygon)
    图一
    MS COCO segmentation编码存储(RLE&polygon)
    图二

    上一篇:SegNet 理解与文章结构


    下一篇:uniapp 开发视频解析app