Пример #1
0
    def _get_patch_for_card(self, card):
        patch = self.patches.get(card, None)
        if patch is None:
            colour, shape, digit = card

            f = os.path.join(os.path.dirname(dps.__file__), "datasets/shapes", "{}.png".format(shape))
            image = imageio.imread(f)
            image = resize_image(image[..., 3], self.patch_shape)
            image = self._colourize(image, colour)

            shape_colour = image[:, :, :3]
            shape_alpha = image[:, :, 3:4] / 255.

            f = os.path.join(os.path.dirname(dps.__file__), "datasets/digits", "{}.png".format(digit))
            digit_image = imageio.imread(f)
            digit_image = resize_image(digit_image[..., 3], self.patch_shape)
            digit_image = self._colourize(digit_image, self.digit_colour)

            digit_colour = digit_image[:, :, :3]
            digit_alpha = digit_image[:, :, 3:4] / 255.

            image_rgb = digit_alpha * digit_colour + (1-digit_alpha) * shape_colour
            image_alpha = (np.clip(digit_alpha + shape_alpha, 0, 1) * 255).astype(np.uint8)

            patch = self.patches[card] = np.concatenate([image_rgb, image_alpha], axis=2)

        return patch
Пример #2
0
    def get_appearance(self):
        key = (self.color, self.h, self.w)
        image = Entity.images.get(key, None)

        if image is None:
            color_array = np.array(to_rgb(self.color))[None, None, :]
            image = Entity.images[key] = np.tile(color_array,
                                                 (self.h, self.w, 1))

        key = (self.appearance, self.h, self.w)
        mask = Entity.masks.get(key, None)

        if mask is None:
            f = os.path.join(os.path.dirname(dps.__file__), "shapes",
                             "{}.png".format(self.appearance))
            mask = imageio.imread(f)
            mask = mask[:, :, 3:]
            mask = resize_image(mask, (self.h, self.w))
            mask = Entity.masks[key] = mask / 255.

        noise_res = getattr(self, "noise_res", None)
        if noise_res is not None:
            noise = generate_perlin_noise_2d(self.shape,
                                             self.noise_res,
                                             normalize=True)
            mask = mask * noise[:, :, None]

        return image, mask
Пример #3
0
    def compute_pixelwise_mode2(files, shape):
        data = []

        for f in files[:10]:
            image = imageio.imread(os.path.join(f))
            image = resize_image(image[:, :, :3], shape)
            data.extend(list(image.reshape(-1, 3)))

        data = np.random.permutation(data)[:10000]

        from sklearn import cluster
        n_clusters = 64
        kmeans = cluster.KMeans(n_clusters=n_clusters)
        print("Clustering...")
        kmeans.fit(data)

        values = kmeans.cluster_centers_.squeeze()[:, None, None, :]

        counters = None

        print("Counting...")
        for f in files:
            image = imageio.imread(os.path.join(f))
            image = resize_image(image[:, :, :3], shape)

            if counters is None:
                counters = np.array([
                    collections.Counter()
                    for i in range(image.shape[0] * image.shape[1])
                ])
                counters = counters.reshape(image.shape[:2])

            distances = np.linalg.norm(values - image[None, :, :, :], axis=3)
            indices = np.argmin(distances, axis=0)

            for i in range(image.shape[0]):
                for j in range(image.shape[1]):
                    counters[i, j].update([indices[i, j]])

        print("Computing mode...")
        mode_image = [[values[c.most_common(1)[0][0], 0, 0, :] for c in row]
                      for row in counters]

        print("Done...")
        return np.array(mode_image).astype(image.dtype)
Пример #4
0
    def _per_ep_callback(self, o, a, r):
        """ process one episode """

        n_frames_per_video = self.n_frames * self.n_batches

        episode_length = len(a)  # o is one step longer than a and r

        # Doesn't support averaging frames.
        n_frames_to_fetch = (n_frames_per_video - 1) * self.frame_skip + 1
        max_start_idx = episode_length - n_frames_to_fetch + 1

        if max_start_idx < 0:
            return

        indices = np.random.choice(max_start_idx + 1,
                                   size=self.n_samples_per_episode,
                                   replace=False)
        print("indices: ", indices)

        step = self.frame_skip

        for start in indices:
            if self._n_examples % 100 == 0:
                print("Processing example {}".format(self._n_examples))

            end = start + n_frames_to_fetch

            _o = np.array(o[start:end:step])
            _a = np.array(a[start:end:step]).flatten()
            _r = np.array(r[start:end:step]).flatten()

            assert len(_o) == n_frames_per_video
            assert len(_a) == n_frames_per_video
            assert len(_r) == n_frames_per_video

            if self.crop is not None:
                top, bot, left, right = self.crop
                _o = _o[:, top:bot, left:right, ...]

            if self.image_shape is not None and _o.shape[
                    1:3] != self.image_shape:
                _o = np.array(
                    [resize_image(img, self.image_shape) for img in _o])

            if self.after_warp:
                _o = np.tile(_o, (1, 1, 1, 3))

            self.fragments['o'].append(_o)
            self.fragments['a'].append(_a)
            self.fragments['r'].append(_r)

            self._n_examples += 1

            if self._n_examples >= self.batch_size:
                print("Found maximum of {} examples, done.".format(
                    self._n_examples))
                return True
Пример #5
0
def make_patch(patch_shape, color, shape, importance):
    f = os.path.join(os.path.dirname(dps.__file__), "datasets/shapes",
                     "{}.png".format(shape))
    image = imageio.imread(f)
    image = resize_image(image[..., 3], patch_shape)
    image = _colorize(image, color)
    image = (image / 255.).astype('f')

    imp = np.maximum(importance * image[..., 3:4], 0.01)

    image = np.concatenate([image, imp], axis=2)
    return image
Пример #6
0
    def _make(self):
        self.patches = {}
        for spec in self.shape_specs:
            shape, colour = spec.split(",")

            f = os.path.join(os.path.dirname(dps.__file__), "datasets/shapes", "{}.png".format(shape))
            image = imageio.imread(f)
            image = resize_image(image[..., 3], self.patch_shape)
            image = self._colourize(image, colour)

            self.patches[spec] = image

        super(ShapesDataset, self)._make()
Пример #7
0
    def compute_pixelwise_mean(files, shape):
        mean = None
        n_points = 0
        for k, f in enumerate(files):
            if k % 100 == 0:
                print("Processing files {}".format(k))
            image = imageio.imread(os.path.join(f))
            image = resize_image(image[:, :, :3], shape)

            if mean is None:
                mean = image
            else:
                mean = (mean * n_points + image) / (n_points + 1)
            n_points += 1

        return mean.astype(image.dtype)
Пример #8
0
def maybe_convert_emnist_shape(path, shape):
    """ Create a version of emnist on disk that is reshaped to the desired shape.

        Images are stored on disk as uint8.

    """
    if shape == (28, 28):
        return

    shape_dir = os.path.join(path, 'emnist_{}_by_{}'.format(*shape))

    if os.path.isdir(shape_dir):
        return

    emnist_dir = os.path.join(path, 'emnist')

    print("Converting (28, 28) EMNIST dataset to {}...".format(shape))

    try:
        shutil.rmtree(shape_dir)
    except FileNotFoundError:
        pass

    os.makedirs(shape_dir, exist_ok=False)

    classes = ''.join([str(i) for i in range(10)] +
                      [chr(i + ord('A')) for i in range(26)] +
                      [chr(i + ord('a')) for i in range(26)])

    for i, cls in enumerate(sorted(classes)):
        with gzip.open(os.path.join(emnist_dir,
                                    str(cls) + '.pklz'), 'rb') as f:
            _x = dill.load(f)

            new_x = []
            for img in _x[:10]:
                img = resize_image(img, shape, preserve_range=True)
                new_x.append(img)

            print(cls)
            print(image_to_string(_x[0]))
            _x = np.array(new_x, dtype=_x.dtype)
            print(image_to_string(_x[0]))

            path_i = os.path.join(shape_dir, cls + '.pklz')
            with gzip.open(path_i, 'wb') as f:
                dill.dump(_x, f, protocol=dill.HIGHEST_PROTOCOL)
Пример #9
0
    def _per_ep_callback(self, o, a, r):
        """ process one episode """

        episode_length = len(a)  # o is one step longer than a and r

        frame_size = (self.n_frames - 1) * self.frame_skip + 1
        max_start_idx = episode_length - frame_size + 1

        if max_start_idx <= self.max_samples_per_ep:
            indices = np.arange(max_start_idx)
        else:
            indices = np.random.choice(max_start_idx,
                                       size=self.max_samples_per_ep,
                                       replace=False)

        step = self.frame_skip

        for start in indices:
            if self._n_examples % 100 == 0:
                print("Processing example {}".format(self._n_examples))

            end = start + frame_size

            _o = np.array(o[start:end:step])
            _a = np.array(a[start:end:step]).flatten()
            _r = np.array(r[start:end:step]).flatten()
            assert len(_o) == self.n_frames
            assert len(_a) == self.n_frames
            assert len(_r) == self.n_frames

            if self.image_shape is not None and _o.shape[
                    1:3] != self.image_shape:
                _o = np.array(
                    [resize_image(img, self.image_shape) for img in _o])

            if self.after_warp:
                _o = np.tile(_o, (1, 1, 1, 3))

            self._write_example(image=_o, action=_a, reward=_r)
            self._n_examples += 1

            if self._n_examples >= self.max_examples:
                print("Found maximum of {} examples, done.".format(
                    self._n_examples))
                return True
Пример #10
0
def load_backgrounds(background_names, shape=None):
    if isinstance(background_names, str):
        background_names = background_names.split()

    backgrounds_dir = os.path.join(cfg.data_dir, 'backgrounds')
    backgrounds = []
    for name in background_names:
        f = os.path.join(backgrounds_dir, '{}.jpg'.format(name))
        try:
            b = imageio.imread(f)
        except FileNotFoundError:
            f = os.path.join(backgrounds_dir, '{}.png'.format(name))
            b = imageio.imread(f)

        if shape is not None and b.shape != shape:
            b = resize_image(b, shape)
            b = np.uint8(b)

        backgrounds.append(b)
    return backgrounds
Пример #11
0
def convert_emnist_and_store(path, new_image_shape):
    """ Images are stored on disk in float format. """
    if new_image_shape == (28, 28):
        raise Exception("Original shape of EMNIST is (28, 28).")

    print(
        "Converting (28, 28) EMNIST dataset to {}...".format(new_image_shape))

    emnist_dir = os.path.join(path, 'emnist')
    new_dir = os.path.join(path, 'emnist_{}_by_{}'.format(*new_image_shape))
    try:
        shutil.rmtree(str(new_dir))
    except FileNotFoundError:
        pass

    os.mkdir(new_dir)

    classes = ''.join([str(i) for i in range(10)] +
                      [chr(i + ord('A')) for i in range(26)] +
                      [chr(i + ord('a')) for i in range(26)])

    for i, cls in enumerate(sorted(classes)):
        with gzip.open(os.path.join(emnist_dir,
                                    str(cls) + '.pklz'), 'rb') as f:
            _x = dill.load(f)

            new_x = []
            for img in _x:
                img = resize_image(img, new_image_shape, preserve_range=False)
                new_x.append(img)

            print(cls)
            print(image_to_string(_x[0]))
            _x = np.array(new_x, dtype=_x.dtype)
            print(image_to_string(_x[0]))

            path_i = os.path.join(new_dir, cls + '.pklz')
            with gzip.open(path_i, 'wb') as f:
                dill.dump(_x, f, protocol=dill.HIGHEST_PROTOCOL)
Пример #12
0
    def compute_pixelwise_mode(files, shape):
        counters = None

        for k, f in enumerate(files):
            if k % 100 == 0:
                print("Processing files {}".format(k))
            image = imageio.imread(os.path.join(f))
            image = resize_image(image[:, :, :3], shape)

            if counters is None:
                counters = np.array([
                    collections.Counter()
                    for i in range(image.shape[0] * image.shape[1])
                ])
                counters = counters.reshape(image.shape[:2])

            for i in range(image.shape[0]):
                for j in range(image.shape[1]):
                    counters[i, j].update([tuple(image[i, j])])

        mode_image = [[c.most_common(1)[0][0] for c in row]
                      for row in counters]
        return np.array(mode_image).astype(image.dtype)
Пример #13
0
def load_emnist(classes,
                balance=False,
                include_blank=False,
                shape=None,
                n_examples=None,
                example_range=None,
                show=False,
                path=None):
    """ Load emnist data from disk by class.

    Elements of `classes` pick out which emnist classes to load, but different labels
    end up getting returned because most classifiers require that the labels
    be in range(len(classes)). We return a dictionary `class_map` which maps from
    elements of `classes` down to range(len(classes)).

    Pixel values of returned images are integers in the range 0-255, but stored as float32.
    Returned X array has shape (n_images,) + shape.

    Parameters
    ----------
    path: str
        Path to data directory, assumed to contain a sub-directory called `emnist`.
    classes: list of character from the set (0-9, A-Z, a-z)
        Each character is the name of a class to load.
    balance: bool
        If True, will ensure that all classes are balanced by removing elements
        from classes that are larger than the minimu-size class.
    include_blank: bool
        If True, includes an additional class that consists of blank images.
    shape: (int, int)
        Shape of the images.
    n_examples: int
        Maximum number of examples returned. If not supplied, return all available data.
    example_range: pair of floats
        Pair of floats specifying, for each class, the range of examples that should be used.
        Each element of the pair is a number in (0, 1), and the second number should be larger.
    show: bool
        If True, prints out an image from each class.

    """
    if path is None:
        path = cfg.data_dir

    maybe_download_emnist(path, shape=shape)

    emnist_dir = os.path.join(path, 'emnist')

    classes = list(classes) + []

    needs_reshape = False
    if shape and shape != (28, 28):
        resized_dir = os.path.join(path, 'emnist_{}_by_{}'.format(*shape))

        if _validate_emnist(resized_dir):
            emnist_dir = resized_dir
        else:
            needs_reshape = True

    if example_range is not None:
        assert 0.0 <= example_range[0] < example_range[1] <= 1.0

    x, y = [], []
    class_count = []
    classes = sorted([str(s) for s in classes])

    for i, cls in enumerate(classes):
        with gzip.open(os.path.join(emnist_dir,
                                    str(cls) + '.pklz'), 'rb') as f:
            _x = dill.load(f)

        if example_range is not None:
            low = int(example_range[0] * len(_x))
            high = int(example_range[1] * len(_x))
            _x = _x[low:high, ...]

        x.append(_x)
        y.extend([i] * _x.shape[0])

        if show:
            print(cls)
            indices_to_show = np.random.choice(len(_x), size=100)
            for i in indices_to_show:
                print(image_to_string(_x[i]))

        class_count.append(_x.shape[0])

    x = np.concatenate(x, axis=0)

    if include_blank:
        min_class_count = min(class_count)

        blanks = np.zeros((min_class_count, ) + x.shape[1:], dtype=np.uint8)
        x = np.concatenate((x, blanks), axis=0)

        blank_idx = len(classes)

        y.extend([blank_idx] * min_class_count)

        blank_symbol = ' '
        classes.append(blank_symbol)

    y = np.array(y)

    if balance:
        min_class_count = min(class_count)

        keep_x, keep_y = [], []
        for i, cls in enumerate(classes):
            keep_indices = np.nonzero(y == i)[0]
            keep_indices = keep_indices[:min_class_count]
            keep_x.append(x[keep_indices])
            keep_y.append(y[keep_indices])

        x = np.concatenate(keep_x, axis=0)
        y = np.concatenate(keep_y, axis=0)

    order = np.random.permutation(x.shape[0])
    x = x[order]
    y = y[order]

    if n_examples:
        x = x[:n_examples]
        y = y[:n_examples]

    if needs_reshape:
        if x.shape[0] > 10000:
            warnings.warn(
                "Performing an online resize of a large number of images ({}), "
                "consider creating and storing the resized dataset.".format(
                    x.shape[0]))

        x = [resize_image(img, shape) for img in x]
        x = np.uint8(x)

    if show:
        indices_to_show = np.random.choice(len(x), size=200)
        for i in indices_to_show:
            print(y[i])
            print(image_to_string(x[i]))

    return x, y, classes
Пример #14
0
    def _make(self):
        assert self.clevr_kind in "train val test".split()

        if self.has_annotations:
            sizes = ['large', 'small']
            colors = [
                'gray', 'red', 'blue', 'green', 'brown', 'purple', 'cyan',
                'yellow'
            ]
            materials = ['rubber', 'metal']
            shapes = ['cube', 'sphere', 'cylinder']
            self.class_names = [
                ' '.join(lst)
                for lst in product(sizes, colors, materials, shapes)
            ]

            scene_file = os.path.join(
                cfg.data_dir, "CLEVR_v1.0/scenes/CLEVR_{}_scenes.json".format(
                    self.clevr_kind))
            with open(scene_file, 'r') as f:
                scenes = json.load(f)['scenes']

        directory = os.path.join(cfg.data_dir, "CLEVR_v1.0/images",
                                 self.clevr_kind)
        files = os.listdir(directory)

        if self.example_range is not None:
            assert self.example_range[0] < self.example_range[1]
            files = [(f, self.get_idx_from_filename(f)) for f in files]
            files = [
                f for f, idx in files
                if self.example_range[0] <= idx < self.example_range[1]
            ]

        files = np.random.choice(files,
                                 size=int(self.n_examples),
                                 replace=False)
        files = [os.path.join(directory, f) for f in files]

        background = None
        if self.clevr_background_mode == "mean":
            background = self.compute_pixelwise_mean(files[:5000],
                                                     self.image_shape)
        elif self.clevr_background_mode == "median":
            background = self.compute_pixelwise_median(files[:5000],
                                                       self.image_shape)
        elif self.clevr_background_mode == "mode":
            background = self.compute_pixelwise_mode(files[:5000],
                                                     self.image_shape)
            # background = self.compute_pixelwise_mode2(files, self.image_shape)
        if background is not None:
            background = background.astype('uint8')

        for k, f in enumerate(files):
            if k % 100 == 0:
                print("Processing image {}".format(k))
            image = imageio.imread(f)
            image = image[..., :3]  # Get rid of alpha channel.

            if image.shape[:2] != self.image_shape:
                image = resize_image(image, self.image_shape)

            if self.has_annotations:
                idx = self.get_idx_from_filename(f)
                scene = scenes[idx]
                assert scene['image_filename'] == os.path.split(f)[1]
                annotations = self.extract_bounding_boxes(scene)
            else:
                annotations = []

            self._write_example(image=image,
                                annotations=annotations,
                                label=0,
                                background=background)
Пример #15
0
def load_omniglot(
        path, classes, include_blank=False, shape=None, one_hot=False, indices=None, show=False):
    """ Load omniglot data from disk by class.

    Elements of `classes` pick out which omniglot classes to load, but different labels
    end up getting returned because most classifiers require that the labels
    be in range(len(classes)). We return a dictionary `class_map` which maps from
    elements of `classes` down to range(len(classes)).

    Returned images are arrays of floats in the range 0-255. White text on black background
    (with 0 corresponding to black). Returned X array has shape (n_images,) + shape.

    Parameters
    ----------
    path: str
        Path to data directory, assumed to contain a sub-directory called `omniglot`.
    classes: list of strings, each giving a class label
        Each character is the name of a class to load.
    balance: bool
        If True, will ensure that all classes are balanced by removing elements
        from classes that are larger than the minimu-size class.
    include_blank: bool
        If True, includes an additional class that consists of blank images.
    shape: (int, int)
        Shape of returned images.
    one_hot: bool
        If True, labels are one-hot vectors instead of integers.
    indices: list of int
        The image indices within the classes to include. For each class there are 20 images.
    show: bool
        If True, prints out an image from each class.

    """
    omniglot_dir = os.path.join(path, 'omniglot')
    classes = list(classes)[:]

    if not indices:
        indices = list(range(20))

    for idx in indices:
        assert 0 <= idx < 20

    x, y = [], []
    class_map, class_count = {}, {}

    for i, cls in enumerate(sorted(list(classes))):
        alphabet, character = cls.split(',')
        char_dir = os.path.join(omniglot_dir, alphabet, "character{:02d}".format(int(character)))
        files = os.listdir(char_dir)
        class_id = files[0].split("_")[0]

        for idx in indices:
            f = os.path.join(char_dir, "{}_{:02d}.png".format(class_id, idx + 1))
            _x = imageio.imread(f)

            # Convert to white-on-black
            _x = 255. - _x

            if shape:
                _x = resize_image(_x, shape)

            x.append(_x)
            y.append(i)

        if show:
            print(cls)
            print(image_to_string(x[-1]))

        class_map[cls] = i
        class_count[cls] = len(indices)

    x = np.array(x, dtype=np.uint8)

    if include_blank:
        min_class_count = min(class_count.values())
        blanks = np.zeros((min_class_count,) + shape, dtype=np.uint8)
        x = np.concatenate((x, blanks), axis=0)

        blank_idx = len(class_map)

        y.extend([blank_idx] * min_class_count)

        blank_symbol = ' '
        class_map[blank_symbol] = blank_idx
        classes.append(blank_symbol)

    y = np.array(y)

    order = np.random.permutation(x.shape[0])
    x = x[order]
    y = y[order]

    if one_hot:
        _y = np.zeros((y.shape[0], len(classes))).astype('f')
        _y[np.arange(y.shape[0]), y] = 1.0
        y = _y

    return x, y, class_map
Пример #16
0
    def _per_ep_callback(self, o, a, r):
        """ process one episode """

        episode_length = len(a)  # o is one step longer than a and r

        n_frames_to_fetch = (self.n_frames - 1) * self.frame_skip + 1 + int(
            self.average_frames)
        max_start_idx = episode_length - n_frames_to_fetch + 1

        n_samples = int(np.ceil(self.sample_density * max_start_idx))

        indices = np.random.choice(max_start_idx,
                                   size=n_samples,
                                   replace=False)

        step = self.frame_skip

        for start in indices:
            if self._n_examples % 100 == 0:
                print("Processing example {}".format(self._n_examples))

            end = start + n_frames_to_fetch

            if self.average_frames:
                _o = np.array(o[start:end])
                _o = np.maximum(_o[:-1], _o[1:])
                # _o = (_o[:-1] + _o[1:]) / 2
                _o = _o[::step].astype(o[0].dtype)

                _a = np.array(a[start + 1:end:step]).flatten()
                _r = np.array(r[start + 1:end:step]).flatten()
            else:
                _o = np.array(o[start:end:step])
                _a = np.array(a[start:end:step]).flatten()
                _r = np.array(r[start:end:step]).flatten()

            assert len(_o) == self.n_frames
            assert len(_a) == self.n_frames
            assert len(_r) == self.n_frames

            if self.crop is not None:
                top, bot, left, right = self.crop
                _o = _o[:, top:bot, left:right, ...]

            if self.image_shape is not None and _o.shape[
                    1:3] != self.image_shape:
                _o = np.array(
                    [resize_image(img, self.image_shape) for img in _o])

            if self.after_warp:
                _o = np.tile(_o, (1, 1, 1, 3))

            if self.get_annotations:
                annotations = self._get_annotations(_o)
            else:
                annotations = [[] for i in range(self.n_frames)]

            self._write_example(image=_o,
                                action=_a,
                                reward=_r,
                                annotations=annotations)
            self._n_examples += 1

            if self._n_examples >= self.max_examples:
                print("Found maximum of {} examples, done.".format(
                    self._n_examples))
                return True
Пример #17
0
    def _make(self):
        """
        To handle both images and videos:

        * for each example, sample patch locations as well as velocities
        *    want to make it so they they don't have to return velocities. can use *rest
        *    in case velocities not return, use a velocity of 0.
        * go through all frames for the example, using an identical process to render each frame
        * if n_frames == 0, remove the frame dimension, so they really are just images.
        * assume a fixed background for the entire video, for now.
        """
        if self.n_examples == 0:
            return np.zeros((0, ) +
                            self.image_shape).astype('uint8'), np.zeros(
                                (0, 1)).astype('i')

        # --- prepare colours ---

        colours = self.colours
        if colours is None:
            colours = []
        if isinstance(colours, str):
            colours = colours.split()

        colour_map = mpl.colors.get_named_colors_mapping()

        self._colours = []
        for c in colours:
            c = mpl.colors.to_rgb(colour_map[c])
            c = np.array(c)[None, None, :]
            c = np.uint8(255. * c)
            self._colours.append(c)

        # --- prepare shapes ---

        self.draw_shape = self.draw_shape or self.image_shape
        self.draw_offset = self.draw_offset or (0, 0)

        draw_shape = self.draw_shape
        if self.depth is not None:
            draw_shape = draw_shape + (self.depth, )

        # --- prepare backgrounds ---

        if self.backgrounds == "all":
            backgrounds = background_names()
        elif isinstance(self.backgrounds, str):
            backgrounds = self.backgrounds.split()
        else:
            backgrounds = self.backgrounds

        if backgrounds:
            if self.backgrounds_resize:
                backgrounds = load_backgrounds(backgrounds, draw_shape)
            else:
                backgrounds = load_backgrounds(backgrounds)

        background_colours = self.background_colours
        if isinstance(self.background_colours, str):
            background_colours = background_colours.split()
        _background_colours = []
        for bc in background_colours:
            color = mpl.colors.to_rgb(bc)
            color = np.array(color)[None, None, :]
            color = np.uint8(255. * color)
            _background_colours.append(color)
        background_colours = _background_colours

        # --- start dataset creation ---

        for j in range(int(self.n_examples)):
            if j % 1000 == 0:
                print("Working on datapoint {}...".format(j))

            # --- populate background ---

            if backgrounds:
                b_idx = np.random.randint(len(backgrounds))
                background = backgrounds[b_idx]
                top = np.random.randint(background.shape[0] - draw_shape[0] +
                                        1)
                left = np.random.randint(background.shape[1] - draw_shape[1] +
                                         1)
                base_image = background[top:top + draw_shape[0],
                                        left:left + draw_shape[1], ...] + 0

            elif background_colours:
                color = background_colours[np.random.randint(
                    len(background_colours))]
                base_image = color * np.ones(draw_shape, 'uint8')

            else:
                base_image = np.zeros(draw_shape, 'uint8')

            # --- sample and populate patches ---

            locs, patches, patch_labels, image_label = self._sample_image()

            draw_offset = self.draw_offset

            images = []
            annotations = []
            for frame in range(max(self.n_frames, 1)):
                image = base_image.copy()

                for patch, loc in zip(patches, locs):
                    if patch.shape[:2] != (loc.h, loc.w):
                        patch = resize_image(patch, (loc.h, loc.w))

                    top = int(np.clip(loc.top, 0, image.shape[0]))
                    bottom = int(np.clip(loc.bottom, 0, image.shape[0]))
                    left = int(np.clip(loc.left, 0, image.shape[1]))
                    right = int(np.clip(loc.right, 0, image.shape[1]))

                    patch_top = top - int(loc.top)
                    patch_bottom = bottom - int(loc.top)
                    patch_left = left - int(loc.left)
                    patch_right = right - int(loc.left)

                    intensity = patch[patch_top:patch_bottom,
                                      patch_left:patch_right, :-1]
                    alpha = patch[patch_top:patch_bottom,
                                  patch_left:patch_right,
                                  -1:].astype('f') / 255.

                    current = image[top:bottom, left:right, ...]
                    image[top:bottom, left:right,
                          ...] = np.uint8(alpha * intensity +
                                          (1 - alpha) * current)

                # --- add distractors ---

                if self.n_distractors_per_image > 0:
                    distractor_patches = self._sample_distractors()
                    distractor_shapes = [
                        img.shape for img in distractor_patches
                    ]
                    distractor_locs = self._sample_patch_locations(
                        distractor_shapes)

                    for patch, loc in zip(distractor_patches, distractor_locs):
                        if patch.shape[:2] != (loc.h, loc.w):
                            anti_aliasing = patch.shape[
                                0] < loc.h or patch.shape[1] < loc.w
                            patch = resize_image(patch, (loc.h, loc.w))

                        intensity = patch[:, :, :-1]
                        alpha = patch[:, :, -1:].astype('f') / 255.

                        current = image[loc.top:loc.bottom, loc.left:loc.right,
                                        ...]
                        image[loc.top:loc.bottom, loc.left:loc.right,
                              ...] = (np.uint8(alpha * intensity +
                                               (1 - alpha) * current))

                # --- possibly crop entire image ---

                if self.draw_shape != self.image_shape or draw_offset != (0,
                                                                          0):
                    image_shape = self.image_shape
                    if self.depth is not None:
                        image_shape = image_shape + (self.depth, )

                    draw_top = np.maximum(-draw_offset[0], 0)
                    draw_left = np.maximum(-draw_offset[1], 0)

                    draw_bottom = np.minimum(
                        -draw_offset[0] + self.image_shape[0],
                        self.draw_shape[0])
                    draw_right = np.minimum(
                        -draw_offset[1] + self.image_shape[1],
                        self.draw_shape[1])

                    image_top = np.maximum(draw_offset[0], 0)
                    image_left = np.maximum(draw_offset[1], 0)

                    image_bottom = np.minimum(
                        draw_offset[0] + self.draw_shape[0],
                        self.image_shape[0])
                    image_right = np.minimum(
                        draw_offset[1] + self.draw_shape[1],
                        self.image_shape[1])

                    _image = np.zeros(image_shape, 'uint8')
                    _image[image_top:image_bottom, image_left:image_right, ...] = \
                        image[draw_top:draw_bottom, draw_left:draw_right, ...]

                    image = _image

                _annotations = self._get_annotations(draw_offset, patches,
                                                     locs, patch_labels)

                images.append(image)
                annotations.append(_annotations)

                for loc in locs:
                    loc.update(image.shape)

            if self.n_frames == 0:
                images = images[0]
                annotations = annotations[0]

            self._write_example(image=images,
                                annotations=annotations,
                                label=image_label)