VOC2012 Segmentation¶
This topic describes how to manage the VOC2012 Segmentation dataset, which is a dataset with SemanticMask and InstanceMask labels (Fig. 4 and Fig. 5).
Create Dataset¶
gas.create_dataset("VOC2012Segmentation")
Organize Dataset¶
Normally, dataloader.py
and catalog.json
are required to organize the “VOC2012 Segmentation” dataset into the Dataset
instance.
In this example, they are stored in the same directory like:
VOC2012 Segmentation/
catalog.json
dataloader.py
It takes the following steps to organize “VOC2012 Segmentation” dataset by the Dataset
instance.
Step 1: Write the Catalog¶
A Catalog contains all label information of one dataset,
which is typically stored in a json file like catalog.json
.
1{
2 "SEMANTIC_MASK": {
3 "categories": [
4 { "name": "background", "categoryId": 0 },
5 { "name": "aeroplane", "categoryId": 1 },
6 { "name": "bicycle", "categoryId": 2 },
7 { "name": "bird", "categoryId": 3 },
8 { "name": "boat", "categoryId": 4 },
9 { "name": "bottle", "categoryId": 5 },
10 { "name": "bus", "categoryId": 6 },
11 { "name": "car", "categoryId": 7 },
12 { "name": "cat", "categoryId": 8 },
13 { "name": "chair", "categoryId": 9 },
14 { "name": "cow", "categoryId": 10 },
15 { "name": "diningtable", "categoryId": 11 },
16 { "name": "dog", "categoryId": 12 },
17 { "name": "horse", "categoryId": 13 },
18 { "name": "motorbike", "categoryId": 14 },
19 { "name": "person", "categoryId": 15 },
20 { "name": "pottedplant", "categoryId": 16 },
21 { "name": "sheep", "categoryId": 17 },
22 { "name": "sofa", "categoryId": 18 },
23 { "name": "train", "categoryId": 19 },
24 { "name": "tvmonitor", "categoryId": 20 },
25 { "name": "void", "categoryId": 255 }
26 ]
27 },
28 "INSTANCE_MASK": {
29 "categories": [
30 { "name": "background", "categoryId": 0 },
31 { "name": "void", "categoryId": 255 }
32 ]
33 }
34}
The annotation types for “VOC2012 Segmentation” are SemanticMask and InstanceMask, and there are 22 category types for SemanticMask. There are 2 category types for InstanceMask, category 0 represents the background, and category 255 represents the border of instances.
Note
By passing the path of the
catalog.json
,load_catalog()
supports loading the catalog into dataset.The categories in InstanceMaskSubcatalog are for pixel values which are not instance ids.
Important
See catalog table for more catalogs with different label types.
Step 2: Write the Dataloader¶
A dataloader is needed to organize the dataset into
a Dataset
instance.
1#!/usr/bin/env python3
2#
3# Copyright 2021 Graviti. Licensed under MIT License.
4#
5# pylint: disable=invalid-name
6
7"""Dataloader of VOC2012Segmentation dataset."""
8
9import os
10
11from tensorbay.dataset import Data, Dataset
12from tensorbay.label import InstanceMask, SemanticMask
13
14_SEGMENT_NAMES = ("train", "val")
15DATASET_NAME = "VOC2012Segmentation"
16
17
18def VOC2012Segmentation(path: str) -> Dataset:
19 """`VOC2012Segmentation <http://host.robots.ox.ac.uk/pascal/VOC/voc2012/>`_ dataset.
20
21 The file structure should be like::
22
23 <path>/
24 JPEGImages/
25 <image_name>.jpg
26 ...
27 SegmentationClass/
28 <mask_name>.png
29 ...
30 SegmentationObject/
31 <mask_name>.png
32 ...
33 ImageSets/
34 Segmentation/
35 train.txt
36 val.txt
37 ...
38 ...
39 ...
40
41 Arguments:
42 path: The root directory of the dataset.
43
44 Returns:
45 Loaded :class: `~tensorbay.dataset.dataset.Dataset` instance.
46
47 """
48 root_path = os.path.abspath(os.path.expanduser(path))
49
50 image_path = os.path.join(root_path, "JPEGImages")
51 semantic_mask_path = os.path.join(root_path, "SegmentationClass")
52 instance_mask_path = os.path.join(root_path, "SegmentationObject")
53 image_set_path = os.path.join(root_path, "ImageSets", "Segmentation")
54
55 dataset = Dataset(DATASET_NAME)
56 dataset.load_catalog(os.path.join(os.path.dirname(__file__), "catalog.json"))
57
58 for segment_name in _SEGMENT_NAMES:
59 segment = dataset.create_segment(segment_name)
60 with open(os.path.join(image_set_path, f"{segment_name}.txt"), encoding="utf-8") as fp:
61 for stem in fp:
62 stem = stem.strip()
63 data = Data(os.path.join(image_path, f"{stem}.jpg"))
64 label = data.label
65 mask_filename = f"{stem}.png"
66 label.semantic_mask = SemanticMask(os.path.join(semantic_mask_path, mask_filename))
67 label.instance_mask = InstanceMask(os.path.join(instance_mask_path, mask_filename))
68
69 segment.append(data)
70
71 return dataset
See SemanticMask annotation and InstanceMask annotation for more details.
There are already a number of dataloaders in TensorBay SDK provided by the community. Thus, instead of writing, importing an available dataloader is also feasible.
from tensorbay.opendataset import VOC2012Segmentation
dataset = VOC2012Segmentation("path/to/dataset/directory")
Note
Note that catalogs are automatically loaded in available dataloaders, users do not have to write them again.
Important
See dataloader table for dataloaders with different label types.
Upload Dataset¶
The organized “VOC2012 Segmentation” dataset can be uploaded to tensorBay for sharing, reuse, etc.
dataset_client = gas.upload_dataset(dataset, jobs=8)
dataset_client.commit("initial commit")
Similar with Git, the commit step after uploading can record changes to the dataset as a version. If needed, do the modifications and commit again. Please see Version Control for more details.
See the visualization on TensorBay website.
Read Dataset¶
Now “VOC2012 Segmentation” dataset can be read from TensorBay.
dataset = Dataset("VOC2012Segmentation", gas)
In dataset “VOC2012 Segmentation”, there are two
segments: train
and val
.
Get a segment by passing the required segment name or the index.
segment_names = dataset.keys()
segment = dataset[0]
In the train
segment,
there is a sequence of data,
which can be obtained by index.
data = segment[0]
In each data, there are one SemanticMask annotation and one InstanceMask annotation.
from PIL import Image
label_semantic_mask = data.label.semantic_mask
semantic_all_attributes = label_semantic_mask.all_attributes
semantic_mask = Image.open(label_semantic_mask.open())
semantic_mask.show()
label_instance_mask = data.label.instance_mask
instance_all_attributes = label_instance_mask.all_attributes
instance_mask_url = label_instance_mask.get_url()
There are two label types in “VOC2012 Segmentation” dataset, which are semantic_mask
and instance_mask
. We can
get the mask by Image.open()
or get the mask url by get_url()
.
The information stored in SemanticMask.all_attributes is
attributes for every category in categories
list of SEMANTIC_MASK
.
The information stored in InstanceMask.all_attributes
is attributes for every instance.
See SemanticMask and InstanceMask label formats for more details.
Delete Dataset¶
gas.delete_dataset("VOC2012Segmentation")