def _execute(self, augmentor_image, save_to_disk=True, multi_threaded=True): """ Modification so that saved images also follow our naming convention. ------ Private method. Used to pass an image through the current pipeline, and return the augmented image. The returned image can then either be saved to disk or simply passed back to the user. Currently this is fixed to True, as Augmentor has only been implemented to save to disk at present. :param augmentor_image: The image to pass through the pipeline. :param save_to_disk: Whether to save the image to disk. Currently fixed to true. :type augmentor_image: :class:`ImageUtilities.AugmentorImage` :type save_to_disk: Boolean :return: The augmented image. """ images = [] if augmentor_image.image_path is not None: images.append(Image.open(augmentor_image.image_path)) if augmentor_image.ground_truth is not None: images.append(Image.open(augmentor_image.ground_truth)) for operation in self.operations: r = round(random.uniform(0, 1), 1) if r <= operation.probability: images = operation.perform_operation(images) if save_to_disk: file_id = str(uuid.uuid4()) basename_split = os.path.basename( augmentor_image.image_path).split('.')[0].split('_') basename_split[1] = file_id filename = '_'.join(basename_split) try: for i in range(len(images)): if i == 0: save_name = filename + "." + \ (self.save_format if self.save_format else augmentor_image.file_format) images[i].save( os.path.join(augmentor_image.output_directory, save_name)) else: save_name = get_mask_fn(filename) images[i].save( os.path.join(augmentor_image.output_directory, save_name)) except IOError as e: logging.error("Error writing {}, {}".format( file_id, e.message)) return images[0], images[1]
def ground_truth(self, ground_truth_directory): """ Modification of the original method to conform to our mask naming convention. ------ Specifies a directory containing corresponding images that constitute respective ground truth images for the images in the current pipeline. This function will search the directory specified by :attr:`ground_truth_directory` and will associate each ground truth image with the images in the pipeline by file name. The relationship between image and ground truth filenames is the following: img filename: '<img_dir>/tulip_<PATCH_ID>_wms_<DATE>_<SENTINELHUB_LAYER>.png' ground truth filename: '<mask_dir>/tulip_<PATCH_ID>_geopedia_<GEOPEDIA_LAYER>.png' Typically used to specify a set of ground truth or gold standard images that should be augmented alongside the original images of a dataset, such as image masks or semantic segmentation ground truth images. :param ground_truth_directory: A directory containing the ground truth images that correspond to the images in the current pipeline. :type ground_truth_directory: String :return: None. """ num_of_ground_truth_images_added = 0 # Progress bar progress_bar = tqdm(total=len(self.augmentor_images), desc="Processing", unit=' Images', leave=False) for augmentor_image_idx in range(len(self.augmentor_images)): filename = os.path.basename( self.augmentor_images[augmentor_image_idx].image_file_name) mask_fn = get_mask_fn(filename) ground_truth_image = os.path.join(ground_truth_directory, mask_fn) if os.path.isfile(ground_truth_image): self.augmentor_images[ augmentor_image_idx].ground_truth = ground_truth_image num_of_ground_truth_images_added += 1 progress_bar.update(1) progress_bar.close() # May not be required after all, check later. if num_of_ground_truth_images_added != 0: self.process_ground_truth_images = True logging.info("{} ground truth image(s) found.".format( num_of_ground_truth_images_added))
def _list_images(self, root): images = collections.defaultdict(dict) for filename in sorted(os.listdir(root)): name, ext = os.path.splitext(filename) mask_flag = "geopedia" in name if ext.lower() not in self._exts: continue if not mask_flag: mask_fn = get_mask_fn(filename) images[name]["base"] = filename images[name]["mask"] = mask_fn self._image_list = list(images.values())
def plot_predictions(imgs, preds, filenames, mask_dir, multispectral): if mask_dir is not None: labels = [ os.path.join(mask_dir, imgutils.get_mask_fn(fn)) for fn in filenames ] labels = [transform_mask(mx.image.imread(fn, flag=0)) for fn in labels] for img, pred, label in zip(imgs, preds, labels): imgutils.plot_images(img, pred, label=label, multisp=multispectral) else: for img, pred in zip(imgs, preds): imgutils.plot_images(img, pred, multisp=multispectral)
def _execute(self, augmentor_image, save_to_disk=True, multi_threaded=True): """ Modification to handle multispectral images. """ images = [] # Data is saved with the shape (bands, width, height) img = np.load(augmentor_image.image_path) # npad is a tuple of (n_before, n_after) for each dimension m = (3 - img.shape[0] % 3) % 3 npad = ((0, m), (0, 0), (0, 0)) padded_img = np.pad(img, pad_width=npad, mode='constant', constant_values=0) # PIL's fromarray needs the images to be in uint8 padded_img = (np.transpose(padded_img, (1, 2, 0)) * 255).astype(np.uint8) images.extend([ Image.fromarray(a, mode='RGB') for a in np.dsplit(padded_img, padded_img.shape[2] / 3) ]) if augmentor_image.ground_truth is not None: images.append(Image.open(augmentor_image.ground_truth)) for operation in self.operations: r = round(random.uniform(0, 1), 1) if r <= operation.probability: images = operation.perform_operation(images) # Reconstruct the original numpy array arrays = [np.array(img) for img in images[:-1]] augmented = np.transpose(np.dstack(arrays), (2, 0, 1)) augmented = (augmented[:img.shape[0], :, :]).astype( np.float32) / 255 # Convert back to float mask = images[-1] if save_to_disk: file_id = str(uuid.uuid4()) basename_split = os.path.basename( augmentor_image.image_path).split('.')[0].split('_') basename_split[1] = file_id filename = '_'.join(basename_split) try: # Save image imgname = filename + "." \ + (self.save_format if self.save_format else augmentor_image.file_format) np.save( os.path.join(augmentor_image.output_directory, imgname), augmented) # Save ground truth if augmentor_image.ground_truth is not None: maskname = get_mask_fn(filename) mask.save( os.path.join(augmentor_image.output_directory, maskname)) except IOError as e: logging.error("Error writing {}, {}".format( file_id, e.message)) return augmented, mask