def image_predict(self, X):
        """
        Predicts class label for the entire image.

        Parameters:
        -----------

        X: array, shape = [n_samples, n_pixels_y, n_pixels_x, n_bands]
            Array of training images

        y: array, shape = [n_samples] or [n_samples, n_pixels_y, n_pixels_x]
            Target labels or masks.
        """
        self._check_image(X)

        patches, patches_shape = self._to_patches(X)

        predictions = self.classifier.predict(self._transform_input(patches))

        image_predictions = predictions.reshape(patches_shape[0:3])

        image_results = np.zeros((self._samples,) + self._image_size)

        nx, ny = self.receptive_field
        row_steps = self._image_size[0] // nx
        col_steps = self._image_size[1] // ny

        # how can this be optimised?
        for i, j, k in itertools.product(range(row_steps), range(col_steps), range(self._samples)):
            image_results[k, nx * i:nx * (i + 1), ny * j:ny * (j + 1)] = image_predictions[k, i, j]

        return image_results