"docs/en_US/NAS/SPOS.rst" did not exist on "d165905d0ba24cfba414b8e0c20fa8d7c8ab6a6e"
cityscapes.py 9.96 KB
Newer Older
Michael Kösel's avatar
Michael Kösel committed
1
2
import json
import os
3
from collections import namedtuple
4
import zipfile
Michael Kösel's avatar
Michael Kösel committed
5

6
from .vision import VisionDataset
Michael Kösel's avatar
Michael Kösel committed
7
8
9
from PIL import Image


10
class Cityscapes(VisionDataset):
Michael Kösel's avatar
Michael Kösel committed
11
    """`Cityscapes <http://www.cityscapes-dataset.com/>`_ Dataset.
12

Michael Kösel's avatar
Michael Kösel committed
13
14
15
16
17
18
    Args:
        root (string): Root directory of dataset where directory ``leftImg8bit``
            and ``gtFine`` or ``gtCoarse`` are located.
        split (string, optional): The image split to use, ``train``, ``test`` or ``val`` if mode="gtFine"
            otherwise ``train``, ``train_extra`` or ``val``
        mode (string, optional): The quality mode to use, ``gtFine`` or ``gtCoarse``
19
20
        target_type (string or list, optional): Type of target to use, ``instance``, ``semantic``, ``polygon``
            or ``color``. Can also be a list to output a tuple with all specified target types.
Michael Kösel's avatar
Michael Kösel committed
21
22
23
24
        transform (callable, optional): A function/transform that takes in a PIL image
            and returns a transformed version. E.g, ``transforms.RandomCrop``
        target_transform (callable, optional): A function/transform that takes in the
            target and transforms it.
25
26
        transforms (callable, optional): A function/transform that takes input sample and its target as entry
            and returns a transformed version.
27
28
29
30
31
32

    Examples:

        Get semantic segmentation target

        .. code-block:: python
33

34
            dataset = Cityscapes('./data/cityscapes', split='train', mode='fine',
35
36
37
38
39
40
41
                                 target_type='semantic')

            img, smnt = dataset[0]

        Get multiple targets

        .. code-block:: python
42

43
            dataset = Cityscapes('./data/cityscapes', split='train', mode='fine',
44
45
46
47
                                 target_type=['instance', 'color', 'polygon'])

            img, (inst, col, poly) = dataset[0]

48
        Validate on the "coarse" set
49
50

        .. code-block:: python
51

52
            dataset = Cityscapes('./data/cityscapes', split='val', mode='coarse',
53
54
55
                                 target_type='semantic')

            img, smnt = dataset[0]
Michael Kösel's avatar
Michael Kösel committed
56
57
    """

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
    # Based on https://github.com/mcordts/cityscapesScripts
    CityscapesClass = namedtuple('CityscapesClass', ['name', 'id', 'train_id', 'category', 'category_id',
                                                     'has_instances', 'ignore_in_eval', 'color'])

    classes = [
        CityscapesClass('unlabeled', 0, 255, 'void', 0, False, True, (0, 0, 0)),
        CityscapesClass('ego vehicle', 1, 255, 'void', 0, False, True, (0, 0, 0)),
        CityscapesClass('rectification border', 2, 255, 'void', 0, False, True, (0, 0, 0)),
        CityscapesClass('out of roi', 3, 255, 'void', 0, False, True, (0, 0, 0)),
        CityscapesClass('static', 4, 255, 'void', 0, False, True, (0, 0, 0)),
        CityscapesClass('dynamic', 5, 255, 'void', 0, False, True, (111, 74, 0)),
        CityscapesClass('ground', 6, 255, 'void', 0, False, True, (81, 0, 81)),
        CityscapesClass('road', 7, 0, 'flat', 1, False, False, (128, 64, 128)),
        CityscapesClass('sidewalk', 8, 1, 'flat', 1, False, False, (244, 35, 232)),
        CityscapesClass('parking', 9, 255, 'flat', 1, False, True, (250, 170, 160)),
        CityscapesClass('rail track', 10, 255, 'flat', 1, False, True, (230, 150, 140)),
        CityscapesClass('building', 11, 2, 'construction', 2, False, False, (70, 70, 70)),
        CityscapesClass('wall', 12, 3, 'construction', 2, False, False, (102, 102, 156)),
        CityscapesClass('fence', 13, 4, 'construction', 2, False, False, (190, 153, 153)),
        CityscapesClass('guard rail', 14, 255, 'construction', 2, False, True, (180, 165, 180)),
        CityscapesClass('bridge', 15, 255, 'construction', 2, False, True, (150, 100, 100)),
        CityscapesClass('tunnel', 16, 255, 'construction', 2, False, True, (150, 120, 90)),
        CityscapesClass('pole', 17, 5, 'object', 3, False, False, (153, 153, 153)),
        CityscapesClass('polegroup', 18, 255, 'object', 3, False, True, (153, 153, 153)),
        CityscapesClass('traffic light', 19, 6, 'object', 3, False, False, (250, 170, 30)),
        CityscapesClass('traffic sign', 20, 7, 'object', 3, False, False, (220, 220, 0)),
        CityscapesClass('vegetation', 21, 8, 'nature', 4, False, False, (107, 142, 35)),
        CityscapesClass('terrain', 22, 9, 'nature', 4, False, False, (152, 251, 152)),
        CityscapesClass('sky', 23, 10, 'sky', 5, False, False, (70, 130, 180)),
        CityscapesClass('person', 24, 11, 'human', 6, True, False, (220, 20, 60)),
        CityscapesClass('rider', 25, 12, 'human', 6, True, False, (255, 0, 0)),
        CityscapesClass('car', 26, 13, 'vehicle', 7, True, False, (0, 0, 142)),
        CityscapesClass('truck', 27, 14, 'vehicle', 7, True, False, (0, 0, 70)),
        CityscapesClass('bus', 28, 15, 'vehicle', 7, True, False, (0, 60, 100)),
        CityscapesClass('caravan', 29, 255, 'vehicle', 7, True, True, (0, 0, 90)),
        CityscapesClass('trailer', 30, 255, 'vehicle', 7, True, True, (0, 0, 110)),
        CityscapesClass('train', 31, 16, 'vehicle', 7, True, False, (0, 80, 100)),
        CityscapesClass('motorcycle', 32, 17, 'vehicle', 7, True, False, (0, 0, 230)),
        CityscapesClass('bicycle', 33, 18, 'vehicle', 7, True, False, (119, 11, 32)),
        CityscapesClass('license plate', -1, -1, 'vehicle', 7, False, True, (0, 0, 142)),
    ]

100
    def __init__(self, root, split='train', mode='fine', target_type='instance',
101
102
                 transform=None, target_transform=None, transforms=None):
        super(Cityscapes, self).__init__(root, transforms, transform, target_transform)
103
        self.mode = 'gtFine' if mode == 'fine' else 'gtCoarse'
Michael Kösel's avatar
Michael Kösel committed
104
        self.images_dir = os.path.join(self.root, 'leftImg8bit', split)
105
        self.targets_dir = os.path.join(self.root, self.mode, split)
Michael Kösel's avatar
Michael Kösel committed
106
107
108
109
110
        self.target_type = target_type
        self.split = split
        self.images = []
        self.targets = []

111
112
        if mode not in ['fine', 'coarse']:
            raise ValueError('Invalid mode! Please use mode="fine" or mode="coarse"')
Michael Kösel's avatar
Michael Kösel committed
113

114
115
        if mode == 'fine' and split not in ['train', 'test', 'val']:
            raise ValueError('Invalid split for mode "fine"! Please use split="train", split="test"'
Michael Kösel's avatar
Michael Kösel committed
116
                             ' or split="val"')
117
118
        elif mode == 'coarse' and split not in ['train', 'train_extra', 'val']:
            raise ValueError('Invalid split for mode "coarse"! Please use split="train", split="train_extra"'
Michael Kösel's avatar
Michael Kösel committed
119
120
                             ' or split="val"')

121
122
123
124
125
126
        if not isinstance(target_type, list):
            self.target_type = [target_type]

        if not all(t in ['instance', 'semantic', 'polygon', 'color'] for t in self.target_type):
            raise ValueError('Invalid value for "target_type"! Valid values are: "instance", "semantic", "polygon"'
                             ' or "color"')
Michael Kösel's avatar
Michael Kösel committed
127
128

        if not os.path.isdir(self.images_dir) or not os.path.isdir(self.targets_dir):
129
130
131
132
133
134
135
136
137
138
139
140
141
            image_dir_zip = os.path.join(self.root, 'leftImg8bit') + '_trainvaltest.zip'

            if self.mode == 'gtFine':
                target_dir_zip = os.path.join(self.root, self.mode) + '_trainvaltest.zip'
            elif self.mode == 'gtCoarse':
                target_dir_zip = os.path.join(self.root, self.mode)

            if os.path.isfile(image_dir_zip) and os.path.isfile(target_dir_zip):
                extract_cityscapes_zip(zip_location=image_dir_zip, root=self.root)
                extract_cityscapes_zip(zip_location=target_dir_zip, root=self.root)
            else:
                raise RuntimeError('Dataset not found or incomplete. Please make sure all required folders for the'
                                   ' specified "split" and "mode" are inside the "root" directory')
Michael Kösel's avatar
Michael Kösel committed
142
143
144
145
146

        for city in os.listdir(self.images_dir):
            img_dir = os.path.join(self.images_dir, city)
            target_dir = os.path.join(self.targets_dir, city)
            for file_name in os.listdir(img_dir):
147
148
149
150
151
                target_types = []
                for t in self.target_type:
                    target_name = '{}_{}'.format(file_name.split('_leftImg8bit')[0],
                                                 self._get_target_suffix(self.mode, t))
                    target_types.append(os.path.join(target_dir, target_name))
Michael Kösel's avatar
Michael Kösel committed
152
153

                self.images.append(os.path.join(img_dir, file_name))
154
                self.targets.append(target_types)
Michael Kösel's avatar
Michael Kösel committed
155
156
157
158
159
160

    def __getitem__(self, index):
        """
        Args:
            index (int): Index
        Returns:
161
162
            tuple: (image, target) where target is a tuple of all target types if target_type is a list with more
            than one item. Otherwise target is a json object if target_type="polygon", else the image segmentation.
Michael Kösel's avatar
Michael Kösel committed
163
164
165
166
        """

        image = Image.open(self.images[index]).convert('RGB')

167
168
169
170
171
172
173
174
175
176
        targets = []
        for i, t in enumerate(self.target_type):
            if t == 'polygon':
                target = self._load_json(self.targets[index][i])
            else:
                target = Image.open(self.targets[index][i])

            targets.append(target)

        target = tuple(targets) if len(targets) > 1 else targets[0]
Michael Kösel's avatar
Michael Kösel committed
177

178
179
        if self.transforms is not None:
            image, target = self.transforms(image, target)
Michael Kösel's avatar
Michael Kösel committed
180
181
182
183
184
185

        return image, target

    def __len__(self):
        return len(self.images)

186
187
188
    def extra_repr(self):
        lines = ["Split: {split}", "Mode: {mode}", "Type: {target_type}"]
        return '\n'.join(lines).format(**self.__dict__)
Michael Kösel's avatar
Michael Kösel committed
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203

    def _load_json(self, path):
        with open(path, 'r') as file:
            data = json.load(file)
        return data

    def _get_target_suffix(self, mode, target_type):
        if target_type == 'instance':
            return '{}_instanceIds.png'.format(mode)
        elif target_type == 'semantic':
            return '{}_labelIds.png'.format(mode)
        elif target_type == 'color':
            return '{}_color.png'.format(mode)
        else:
            return '{}_polygons.json'.format(mode)
204
205
206
207
208
209


def extract_cityscapes_zip(zip_location, root):
    zip_file = zipfile.ZipFile(zip_location, 'r')
    zip_file.extractall(root)
    zip_file.close()