lsun.py 5.29 KB
Newer Older
soumith's avatar
soumith committed
1
2
3
4
import torch.utils.data as data
from PIL import Image
import os
import os.path
soumith's avatar
soumith committed
5
import six
soumith's avatar
soumith committed
6
7
8
9
10
11
12
import string
import sys
if sys.version_info[0] == 2:
    import cPickle as pickle
else:
    import pickle

13

soumith's avatar
soumith committed
14
class LSUNClass(data.Dataset):
Jason Park's avatar
Jason Park committed
15
    def __init__(self, root, transform=None, target_transform=None):
soumith's avatar
soumith committed
16
        import lmdb
Jason Park's avatar
Jason Park committed
17
18
19
20
21
        self.root = os.path.expanduser(root)
        self.transform = transform
        self.target_transform = target_transform

        self.env = lmdb.open(root, max_readers=1, readonly=True, lock=False,
soumith's avatar
soumith committed
22
                             readahead=False, meminit=False)
soumith's avatar
soumith committed
23
24
        with self.env.begin(write=False) as txn:
            self.length = txn.stat()['entries']
Jason Park's avatar
Jason Park committed
25
        cache_file = '_cache_' + root.replace('/', '_')
soumith's avatar
soumith committed
26
        if os.path.isfile(cache_file):
27
            self.keys = pickle.load(open(cache_file, "rb"))
soumith's avatar
soumith committed
28
29
        else:
            with self.env.begin(write=False) as txn:
30
31
                self.keys = [key for key, _ in txn.cursor()]
            pickle.dump(self.keys, open(cache_file, "wb"))
soumith's avatar
soumith committed
32
33
34
35
36
37
38

    def __getitem__(self, index):
        img, target = None, None
        env = self.env
        with env.begin(write=False) as txn:
            imgbuf = txn.get(self.keys[index])

soumith's avatar
soumith committed
39
        buf = six.BytesIO()
soumith's avatar
soumith committed
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
        buf.write(imgbuf)
        buf.seek(0)
        img = Image.open(buf).convert('RGB')

        if self.transform is not None:
            img = self.transform(img)

        if self.target_transform is not None:
            target = self.target_transform(target)

        return img, target

    def __len__(self):
        return self.length

    def __repr__(self):
        return self.__class__.__name__ + ' (' + self.db_path + ')'

58

soumith's avatar
soumith committed
59
class LSUN(data.Dataset):
soumith's avatar
soumith committed
60
    """
61
62
63
    `LSUN <http://lsun.cs.princeton.edu>`_ dataset.

    Args:
Jason Park's avatar
Jason Park committed
64
        root (string): Root directory for the database files.
65
66
67
68
69
70
        classes (string or list): One of {'train', 'val', 'test'} or a list of
            categories to load. e,g. ['bedroom_train', 'church_train'].
        transform (callable, optional): A function/transform that  takes in an 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.
soumith's avatar
soumith committed
71
    """
72

Jason Park's avatar
Jason Park committed
73
    def __init__(self, root, classes='train',
soumith's avatar
soumith committed
74
75
76
77
78
                 transform=None, target_transform=None):
        categories = ['bedroom', 'bridge', 'church_outdoor', 'classroom',
                      'conference_room', 'dining_room', 'kitchen',
                      'living_room', 'restaurant', 'tower']
        dset_opts = ['train', 'val', 'test']
Jason Park's avatar
Jason Park committed
79
80
81
82
        self.root = os.path.expanduser(root)
        self.transform = transform
        self.target_transform = target_transform

soumith's avatar
soumith committed
83
        if type(classes) == str and classes in dset_opts:
soumith's avatar
soumith committed
84
85
86
87
            if classes == 'test':
                classes = [classes]
            else:
                classes = [c + '_' + classes for c in categories]
soumith's avatar
soumith committed
88
89
90
91
        if type(classes) == list:
            for c in classes:
                c_short = c.split('_')
                c_short.pop(len(c_short) - 1)
Adam Lerer's avatar
Adam Lerer committed
92
                c_short = '_'.join(c_short)
soumith's avatar
soumith committed
93
                if c_short not in categories:
94
95
                    raise(ValueError('Unknown LSUN class: ' + c_short + '.'
                                     'Options are: ' + str(categories)))
soumith's avatar
soumith committed
96
97
98
                c_short = c.split('_')
                c_short = c_short.pop(len(c_short) - 1)
                if c_short not in dset_opts:
99
100
                    raise(ValueError('Unknown postfix: ' + c_short + '.'
                                     'Options are: ' + str(dset_opts)))
soumith's avatar
soumith committed
101
102
103
104
105
106
107
        else:
            raise(ValueError('Unknown option for classes'))
        self.classes = classes

        # for each class, create an LSUNClassDataset
        self.dbs = []
        for c in self.classes:
soumith's avatar
soumith committed
108
            self.dbs.append(LSUNClass(
Jason Park's avatar
Jason Park committed
109
                root=root + '/' + c + '_lmdb',
110
                transform=transform))
soumith's avatar
soumith committed
111
112
113
114
115
116
117
118
119
120

        self.indices = []
        count = 0
        for db in self.dbs:
            count += len(db)
            self.indices.append(count)

        self.length = count

    def __getitem__(self, index):
121
122
123
124
125
126
127
        """
        Args:
            index (int): Index

        Returns:
            tuple: Tuple (image, target) where target is the index of the target category.
        """
soumith's avatar
soumith committed
128
129
130
131
132
133
        target = 0
        sub = 0
        for ind in self.indices:
            if index < ind:
                break
            target += 1
Zhou Le's avatar
Zhou Le committed
134
            sub = ind
soumith's avatar
soumith committed
135
136
137
138
139
140
141

        db = self.dbs[target]
        index = index - sub

        if self.target_transform is not None:
            target = self.target_transform(target)

soumith's avatar
soumith committed
142
143
        img, _ = db[index]
        return img, target
soumith's avatar
soumith committed
144
145
146
147
148

    def __len__(self):
        return self.length

    def __repr__(self):
149
150
151
        fmt_str = 'Dataset ' + self.__class__.__name__ + '\n'
        fmt_str += '    Number of datapoints: {}\n'.format(self.__len__())
        fmt_str += '    Root Location: {}\n'.format(self.root)
Jason Park's avatar
Jason Park committed
152
        fmt_str += '    Classes: {}\n'.format(self.classes)
153
154
155
156
157
        tmp = '    Transforms (if any): '
        fmt_str += '{0}{1}\n'.format(tmp, self.transform.__repr__().replace('\n', '\n' + ' ' * len(tmp)))
        tmp = '    Target Transforms (if any): '
        fmt_str += '{0}{1}'.format(tmp, self.target_transform.__repr__().replace('\n', '\n' + ' ' * len(tmp)))
        return fmt_str