def processThread(self): variant = "Original" # TODO Pass as argument print('Loading data, this may take a while...') model = PluginLoader.get_model(variant)(self.arguments.model_dir) model.load(swapped=False) images_A = get_image_paths(self.arguments.input_A) images_B = get_image_paths(self.arguments.input_B) trainer = PluginLoader.get_trainer(variant)(model, images_A, images_B) try: print('Starting. Press "Enter" to stop training and save model') for epoch in range(0, 1000000): save_iteration = epoch % self.arguments.save_interval == 0 trainer.train_one_step(epoch, self.show if save_iteration else None) if save_iteration: model.save_weights() if self.stop: model.save_weights() exit() except KeyboardInterrupt: try: model.save_weights() except KeyboardInterrupt: print('Saving model weights has been cancelled!') exit(0)
def process(self): images_A = get_image_paths(self.arguments.input_A) images_B = get_image_paths(self.arguments.input_B) images_A = load_images(images_A) / 255.0 images_B = load_images(images_B) / 255.0 images_A += images_B.mean(axis=(0, 1, 2)) - \ images_A.mean(axis=(0, 1, 2)) print('press "q" to stop training and save model') BATCH_SIZE = 64 for epoch in range(1000000): warped_A, target_A = get_training_data(images_A, BATCH_SIZE) warped_B, target_B = get_training_data(images_B, BATCH_SIZE) loss_A = autoencoder_A.train_on_batch(warped_A, target_A) loss_B = autoencoder_B.train_on_batch(warped_B, target_B) print(loss_A, loss_B) if epoch % 100 == 0: self.save_model_weights() self.show_sample(target_A[0:14], target_B[0:14]) key = cv2.waitKey(1) if key == ord('q'): self.save_model_weights() exit()
def get_images(path_a, path_b): """ Check the image folders exist and contains images and obtain image paths. Returns ------- list_a: The image paths for side a. list_b: The image paths for side b. """ # return images list_a = get_image_paths(path_a) list_b = get_image_paths(path_b) return list_a, list_b
def processThread(self): try: if self.arguments.allow_growth: self.set_tf_allow_growth() print('Loading data, this may take a while...') # this is so that you can enter case insensitive values for trainer trainer = self.arguments.trainer trainer = "LowMem" if trainer.lower() == "lowmem" else trainer model = PluginLoader.get_model(trainer)(get_folder( self.arguments.model_dir)) model.load(swapped=False) images_A = get_image_paths(self.arguments.input_A) images_B = get_image_paths(self.arguments.input_B) trainer = PluginLoader.get_trainer(trainer) trainer = trainer(model, images_A, images_B, self.arguments.batch_size, self.arguments.perceptual_loss) print('Starting. Press "Enter" to stop training and save model') for epoch in range(0, self.arguments.epochs): save_iteration = epoch % self.arguments.save_interval == 0 trainer.train_one_step( epoch, self.show if (save_iteration or self.save_now) else None, self.arguments.save_interval) if save_iteration: model.save_weights() if self.stop: model.save_weights() exit() if self.save_now: model.save_weights() self.save_now = False except KeyboardInterrupt: try: model.save_weights() except KeyboardInterrupt: print('Saving model weights has been cancelled!') exit(0) except Exception as e: print(e) exit(1)
def get_input_images(self): """ Return the list of images that are to be processed """ if not os.path.exists(self.args.input_dir): print("Input directory {} not found.".format(self.args.input_dir)) exit(1) print("Input Directory: {}".format(self.args.input_dir)) if hasattr(self.args, 'skip_existing') and self.args.skip_existing: input_images = get_image_paths(self.args.input_dir, self.already_processed) print("Excluding %s files" % len(self.already_processed)) else: input_images = get_image_paths(self.args.input_dir) return input_images
def __init__(self, description='default'): print('Initializing') self.parse_arguments(description) print("Input Directory: {}".format(self.arguments.input_dir)) print("Output Directory: {}".format(self.arguments.output_dir)) print('Starting, this may take a while...') self.output_dir = get_folder(self.arguments.output_dir) try: self.input_dir = get_image_paths(self.arguments.input_dir) except: print('Input directory not found. Please ensure it exists.') exit(1) self.images_found = len(self.input_dir) for filename in self.input_dir: if self.arguments.verbose: print('Processing: {}'.format(os.path.basename(filename))) self.process_image(filename) self.images_processed = self.images_processed + 1 self.finalize()
def _get_count_and_filelist(self, fast_count): """ Set the count of images to be processed and set the file list If the input is a video, a dummy file list is created for checking against an alignments file, otherwise it will be a list of full filenames. Parameters ---------- fast_count: bool When loading from video, the video needs to be parsed frame by frame to get an accurate count. This can be done quite quickly without guaranteed accuracy, or slower with guaranteed accuracy. Set to ``True`` to count quickly, or ``False`` to count slower but accurately. """ if self._is_video: self._count = int(count_frames(self.location, fast=fast_count)) self._file_list = [self._dummy_video_framename(i) for i in range(self.count)] else: if isinstance(self.location, (list, tuple)): self._file_list = self.location else: self._file_list = get_image_paths(self.location) self._count = len(self.file_list) logger.debug("count: %s", self.count) logger.trace("filelist: %s", self.file_list)
def get_face_hashes(self): """ Check for the existence of an aligned directory for identifying which faces in the target frames should be swapped. If it exists, obtain the hashes of the faces in the folder """ face_hashes = list() input_aligned_dir = self.args.input_aligned_dir if input_aligned_dir is None: logger.verbose("Aligned directory not specified. All faces listed in the " "alignments file will be converted") elif not os.path.isdir(input_aligned_dir): logger.warning("Aligned directory not found. All faces listed in the " "alignments file will be converted") else: file_list = [path for path in get_image_paths(input_aligned_dir)] logger.info("Getting Face Hashes for selected Aligned Images") for face in tqdm(file_list, desc="Hashing Faces"): face_hashes.append(hash_image_file(face)) logger.debug("Face Hashes: %s", (len(face_hashes))) if not face_hashes: logger.error("Aligned directory is empty, no faces will be converted!") exit(1) elif len(face_hashes) <= len(self.input_images) / 3: logger.warning("Aligned directory contains far fewer images than the input " "directory, are you sure this is the right folder?") return face_hashes
def setup(self, input_a=None, input_b=None, output=None): """ Set the timelapse output folder """ logger.debug("Setting up timelapse") if output is None: output = str(get_folder(os.path.join(str(self.model.model_dir), "{}_timelapse".format(self.model.name)))) self.output_file = str(output) logger.debug("Timelapse output set to '%s'", self.output_file) images = {"a": get_image_paths(input_a), "b": get_image_paths(input_b)} batchsize = min(len(images["a"]), len(images["b"]), self.preview_images) for side, image_files in images.items(): self.batchers[side].set_timelapse_feed(image_files, batchsize) logger.debug("Set up timelapse")
def process_arguments(self, arguments): self.arguments = arguments print("Input Directory: {}".format(self.arguments.input_dir)) print("Output Directory: {}".format(self.arguments.output_dir)) self.serializer = None if self.arguments.serializer is None and self.arguments.alignments_path is not None: ext = os.path.splitext(self.arguments.alignments_path)[-1] self.serializer = Serializer.get_serializer_fromext(ext) print(self.serializer, self.arguments.alignments_path) else: self.serializer = Serializer.get_serializer(self.arguments.serializer or "json") print("Using {} serializer".format(self.serializer.ext)) print('Starting, this may take a while...') self.output_dir = get_folder(self.arguments.output_dir) try: self.input_dir = get_image_paths(self.arguments.input_dir) except: print('Input directory not found. Please ensure it exists.') exit(1) self.filter = self.load_filter() self.process() self.finalize()
def _get_images(self): """ Check the image folders exist and contains images and obtain image paths. Returns ------- dict The image paths for each side. The key is the side, the value is the list of paths for that side. """ logger.debug("Getting image paths") images = dict() for side in ("a", "b"): image_dir = getattr(self._args, "input_{}".format(side)) if not os.path.isdir(image_dir): logger.error("Error: '%s' does not exist", image_dir) sys.exit(1) images[side] = get_image_paths(image_dir) if not images[side]: logger.error("Error: '%s' contains no images", image_dir) sys.exit(1) logger.info("Model A Directory: %s", self._args.input_a) logger.info("Model B Directory: %s", self._args.input_b) logger.debug("Got image paths: %s", [(key, str(len(val)) + " images") for key, val in images.items()]) return images
def _setup(self, input_a=None, input_b=None, output=None): """ Setup the time-lapse folder locations and the time-lapse feed. Parameters ---------- input_a: str The full path to the time-lapse input folder containing faces for the "a" side input_b: str The full path to the time-lapse input folder containing faces for the "b" side output: str, optional The full path to the time-lapse output folder. If ``None`` is provided this will default to the model folder """ logger.debug("Setting up time-lapse") if output is None: output = get_folder( os.path.join(str(self._model.model_dir), f"{self._model.name}_timelapse")) self._output_file = str(output) logger.debug("Time-lapse output set to '%s'", self._output_file) # Rewrite paths to pull from the training images so mask and face data can be accessed images = {} for side, input_ in zip(("a", "b"), (input_a, input_b)): training_path = os.path.dirname(self._image_paths[side][0]) images[side] = [ os.path.join(training_path, os.path.basename(pth)) for pth in get_image_paths(input_) ] batchsize = min(len(images["a"]), len(images["b"]), self._num_images) self._feeder.set_timelapse_feed(images, batchsize) logger.debug("Set up time-lapse")
def get_face_hashes(self): """ Check for the existence of an aligned directory for identifying which faces in the target frames should be swapped. If it exists, obtain the hashes of the faces in the folder """ face_hashes = list() input_aligned_dir = self.args.input_aligned_dir if input_aligned_dir is None: logger.verbose( "Aligned directory not specified. All faces listed in the " "alignments file will be converted") elif not os.path.isdir(input_aligned_dir): logger.warning( "Aligned directory not found. All faces listed in the " "alignments file will be converted") else: file_list = [path for path in get_image_paths(input_aligned_dir)] logger.info("Getting Face Hashes for selected Aligned Images") for face in tqdm(file_list, desc="Hashing Faces"): face_hashes.append(read_image_hash(face)) logger.debug("Face Hashes: %s", (len(face_hashes))) if not face_hashes: raise FaceswapError( "Aligned directory is empty, no faces will be converted!") if len(face_hashes) <= len(self.input_images) / 3: logger.warning( "Aligned directory contains far fewer images than the input " "directory, are you sure this is the right folder?") return face_hashes
def get_input_images(self): """ Return the list of images or video file that is to be processed """ if self.is_video: input_images = self.args.input_dir else: input_images = get_image_paths(self.args.input_dir) return input_images
def processThread(self): print("Loading Data..! This may take a while") trainer = self.arguments.trainer trainer = "LowMem" if trainer.lower() == "lowmem" else trainer model = PluginLoader.get_model(trainer)(get_folder( self.arguments.model_dir)) model.load(swapped=False) images_A = get_image_paths(self.arguments.input_A) images_B = get_image_paths(self.arguments.input_B) trainer = PluginLoader.get_trainer(trainer) trainer = trainer(model, images_A, images_B, batch_size=self.arguments.batch_size) try: print("Starting. Press Enter to stop Training and Save model") for epoch in range(0, 100000): save_iteration = epoch % self.arguments.save_interval == 0 trainer.train_one_step( epoch, self.show if (save_iteration or self.save_now) else None) if save_iteration: model.save_weights() if self.stop: model.save_weights() exit() if self.save_now: model.save_weights() self.save_now = False except KeyboardInterrupt: try: model.save_weights() except KeyboardInterrupt: print("Saving model weights has been cancelled...!") exit(0)
def get_already_processed(self): """ Return the images that already exist in the output directory """ print("Output Directory: {}".format(self.args.output_dir)) if not hasattr(self.args, 'skip_existing') or not self.args.skip_existing: return None return get_image_paths(self.args.output_dir)
def read_directory(self): img_file = get_image_paths(self.input_A_path) for filename in tqdm(img_file): # if self.arguments.verbose: # print('Processing: {}'.format(os.path.basename(filename))) yield filename self.images_processed = self.images_processed + 1
def processThread(self): if self.arguments.allow_growth: self.set_tf_allow_growth() print('Loading data, this may take a while...') # this is so that you can enter case insensitive values for trainer trainer = self.arguments.trainer trainer = "LowMem" if trainer.lower() == "lowmem" else trainer model = PluginLoader.get_model(trainer)(get_folder(self.arguments.model_dir)) model.load(swapped=False) images_A = get_image_paths(self.arguments.input_A) images_B = get_image_paths(self.arguments.input_B) trainer = PluginLoader.get_trainer(trainer) trainer = trainer(model, images_A, images_B, batch_size=self.arguments.batch_size) try: print('Starting. Press "Enter" to stop training and save model') for epoch in range(0, self.arguments.epochs): save_iteration = epoch % self.arguments.save_interval == 0 trainer.train_one_step(epoch, self.show if (save_iteration or self.save_now) else None) if save_iteration: model.save_weights() if self.stop: model.save_weights() exit() if self.save_now: model.save_weights() self.save_now = False except KeyboardInterrupt: try: model.save_weights() except KeyboardInterrupt: print('Saving model weights has been cancelled!') exit(0) except Exception as e: print(e) exit(1)
def _get_face_metadata(self): """ Check for the existence of an aligned directory for identifying which faces in the target frames should be swapped. If it exists, scan the folder for face's metadata Returns ------- dict Dictionary of source frame names with a list of associated face indices to be skipped """ retval = dict() input_aligned_dir = self._args.input_aligned_dir if input_aligned_dir is None: logger.verbose( "Aligned directory not specified. All faces listed in the " "alignments file will be converted") return retval if not os.path.isdir(input_aligned_dir): logger.warning( "Aligned directory not found. All faces listed in the " "alignments file will be converted") return retval log_once = False filelist = get_image_paths(input_aligned_dir) for fullpath, metadata in tqdm(read_image_meta_batch(filelist), total=len(filelist), desc="Reading Face Data", leave=False): if "itxt" not in metadata or "source" not in metadata["itxt"]: # UPDATE LEGACY FACES FROM ALIGNMENTS FILE if not log_once: logger.warning( "Legacy faces discovered in '%s'. These faces will be updated", input_aligned_dir) log_once = True data = update_legacy_png_header(fullpath, self._alignments) if not data: raise FaceswapError( "Some of the faces being passed in from '{}' could not be matched to the " "alignments file '{}'\nPlease double check your sources and try " "again.".format(input_aligned_dir, self._alignments.file)) meta = data["source"] else: meta = metadata["itxt"]["source"] retval.setdefault(meta["source_filename"], list()).append(meta["face_index"]) if not retval: raise FaceswapError( "Aligned directory is empty, no faces will be converted!") if len(retval) <= len(self._input_images) / 3: logger.warning( "Aligned directory contains far fewer images than the input " "directory, are you sure this is the right folder?") return retval
def get_input_images(self): """ Return the list of images that are to be processed """ if not os.path.exists(self.args.input_dir): print("Input directory {} not found.".format(self.args.input_dir)) exit(1) print("Input Directory: {}".format(self.args.input_dir)) input_images = get_image_paths(self.args.input_dir) return input_images
def get_input_images(self): """ Return the list of images that are to be processed """ if not os.path.exists(self.args.input_dir): logger.error("Input directory %s not found.", self.args.input_dir) exit(1) logger.info("Input Directory: %s", self.args.input_dir) input_images = get_image_paths(self.args.input_dir) return input_images
def processThread(self): print('Loading data, this may take a while...') # this is so that you can enter case insensitive values for trainer trainer = self.arguments.trainer trainer = trainer if trainer != "Lowmem" else "LowMem" model = PluginLoader.get_model(trainer)(self.arguments.model_dir) model.load(swapped=False) images_A = get_image_paths(self.arguments.input_A) images_B = get_image_paths(self.arguments.input_B) trainer = PluginLoader.get_trainer(trainer)( model, images_A, images_B, batch_size=self.arguments.batch_size) try: print('Starting. Press "Enter" to stop training and save model') for epoch in range(0, 1000000): save_iteration = epoch % self.arguments.save_interval == 0 trainer.train_one_step( epoch, self.show if (save_iteration or self.save_now) else None) if save_iteration: model.save_weights() if self.stop: model.save_weights() exit() if self.save_now: model.save_weights() self.save_now = False except KeyboardInterrupt: try: model.save_weights() except KeyboardInterrupt: print('Saving model weights has been cancelled!') exit(0)
def process(self): print('Starting, this may take a while...') images_A = get_image_paths(self.arguments.input_A) images_B = get_image_paths(self.arguments.input_B) images_A = load_images(images_A) / 255.0 images_B = load_images(images_B) / 255.0 images_A += images_B.mean(axis=(0, 1, 2)) - images_A.mean(axis=(0, 1, 2)) print('press "q" to stop training and save model') BATCH_SIZE = 64 for epoch in range(1000000): if self.arguments.verbose: print("Iteration number {}".format(epoch + 1)) start_time = time.time() warped_A, target_A = get_training_data(images_A, BATCH_SIZE) warped_B, target_B = get_training_data(images_B, BATCH_SIZE) loss_A = autoencoder_A.train_on_batch(warped_A, target_A) loss_B = autoencoder_B.train_on_batch(warped_B, target_B) print(loss_A, loss_B) if epoch % self.arguments.save_interval == 0: self.save_model_weights() self.show_sample(target_A[0:14], target_B[0:14]) key = cv2.waitKey(1) if key == ord('q'): self.save_model_weights() exit() if self.arguments.verbose: end_time = time.time() time_elapsed = int(round((end_time - start_time))) m, s = divmod(time_elapsed, 60) h, m = divmod(m, 60) print("Iteration done in {:02d}h{:02d}m{:02d}s".format( h, m, s))
def scrape_dir(src_dir): image_list = [] for ext in utils.valid_extensions: raw_list = utils.get_image_paths(src_dir, keyword=ext) for raw_im in raw_list: image_list.append(raw_im) # Save only the unique entries image_list = list(set(image_list)) utils.remove_hidden(image_list) return image_list
def _get_input_images(self): """ Return the list of images or path to video file that is to be processed. Returns ------- str or list Path to the video file if the input is a video otherwise list of image paths. """ if self._is_video: input_images = self._args.input_dir else: input_images = get_image_paths(self._args.input_dir) return input_images
def get_images(self): """ Check the image dirs exist, contain images and return the image objects """ images = [] if self.args.pre_training: if not os.path.isdir(self.args.input_P): print('Error: {} does not exist'.format(self.args.input_P)) exit(1) images.append(get_image_paths(self.args.input_P)) print("Model Pre-Training Directory: {}".format(self.args.input_P)) else: for image_dir in [self.args.input_A, self.args.input_B]: if not os.path.isdir(image_dir): print('Error: {} does not exist'.format(image_dir)) exit(1) if not os.listdir(image_dir): print('Error: {} contains no images'.format(image_dir)) exit(1) images.append(get_image_paths(image_dir)) print("Model A Directory: {}".format(self.args.input_A)) print("Model B Directory: {}".format(self.args.input_B)) return images
def process_arguments(self, arguments): self.arguments = arguments print("Input Directory: {}".format(self.arguments.input_dir)) print("Output Directory: {}".format(self.arguments.output_dir)) print('Starting, this may take a while...') self.output_dir = get_folder(self.arguments.output_dir) try: self.input_dir = get_image_paths(self.arguments.input_dir) except: print('Input directory not found. Please ensure it exists.') exit(1) self.images_found = len(self.input_dir) self.process_directory()
def get_images(self): """ Check the image dirs exist, contain images and return the image objects """ images = [] for image_dir in [self.args.input_A, self.args.input_B]: if not os.path.isdir(image_dir): print('Error: {} does not exist'.format(image_dir)) exit(1) if not os.listdir(image_dir): print('Error: {} contains no images'.format(image_dir)) exit(1) images.append(get_image_paths(image_dir)) print("Model A Directory: {}".format(self.args.input_A)) print("Model B Directory: {}".format(self.args.input_B)) return images
def process_arguments(self, arguments): self.arguments = arguments print("Input Directory: {}".format(self.arguments.input_dir)) print("Output Directory: {}".format(self.arguments.output_dir)) print('Starting, this may take a while...') sys.stdout.flush() self.output_dir = get_folder(self.arguments.output_dir) try: self.input_dir = get_image_paths(self.arguments.input_dir) except: print('Input directory not found. Please ensure it exists.') exit(1) self.filter = self.load_filter() self.process() self.finalize()
def __init__(self, path, task, load_with_hash=False, queue_size=16): logger.debug( "Initializing %s: (path: %s, task: %s, load_with_hash: %s, queue_size: %s)", self.__class__.__name__, path, task, load_with_hash, queue_size) self._location = path self._task = task.lower() self._is_video = self._check_input() self._input = self.location if self._is_video else get_image_paths( self.location) self._count = count_frames_and_secs( self._input)[0] if self._is_video else len(self._input) self._queue = queue_manager.get_queue(name="{}_{}".format( self.__class__.__name__, self._task), maxsize=queue_size) self._thread = self._set_thread(io_args=(load_with_hash, )) self._thread.start()
def process_arguments(self, arguments): self.arguments = arguments print("Input Directory: {}".format(self.arguments.input_dir)) print("Output Directory: {}".format(self.arguments.output_dir)) print('Starting, this may take a while...') self.output_dir = get_folder(self.arguments.output_dir) try: self.input_dir = get_image_paths(self.arguments.input_dir) except: print('Input directory not found. Please ensure it exists.') exit(1) self.images_found = len(self.input_dir) self.filter = self.load_filter() self.process() self.finalize()
def get_images(self): """ Check the image dirs exist, contain images and return the image objects """ images = [] for image_dir in [self.args.input_A, self.args.input_B]: if not os.path.isdir(image_dir): logger.error("Error: '%s' does not exist", image_dir) exit(1) if not os.listdir(image_dir): logger.error("Error: '%s' contains no images", image_dir) exit(1) images.append(get_image_paths(image_dir)) logger.info("Model A Directory: %s", self.args.input_A) logger.info("Model B Directory: %s", self.args.input_B) return images
def _get_images(self): """ Check the image folders exist and contains valid extracted faces. Obtain image paths. Returns ------- dict The image paths for each side. The key is the side, the value is the list of paths for that side. """ logger.debug("Getting image paths") images = dict() for side in ("a", "b"): image_dir = getattr(self._args, "input_{}".format(side)) if not os.path.isdir(image_dir): logger.error("Error: '%s' does not exist", image_dir) sys.exit(1) images[side] = get_image_paths(image_dir, ".png") if not images[side]: logger.error("Error: '%s' contains no images", image_dir) sys.exit(1) # Validate the first image is a detected face test_image = next(img for img in images[side]) meta = read_image_meta(test_image) logger.debug("Test file: (filename: %s, metadata: %s)", test_image, meta) if "itxt" not in meta or "alignments" not in meta["itxt"]: logger.error( "The input folder '%s' contains images that are not extracted faces.", image_dir) logger.error( "You can only train a model on faces generated from Faceswap's " "extract process. Please check your sources and try again." ) sys.exit(1) logger.info("Model %s Directory: '%s' (%s images)", side.upper(), image_dir, len(images[side])) logger.debug("Got image paths: %s", [(key, str(len(val)) + " images") for key, val in images.items()]) self._validate_image_counts(images) return images
def get_aligned_directory(self): """ Check for the existence of an aligned directory for identifying which faces in the target frames should be swapped """ faces_to_swap = None input_aligned_dir = self.args.input_aligned_dir if input_aligned_dir is None: print("Aligned directory not specified. All faces listed in the alignments file " "will be converted") elif not os.path.isdir(input_aligned_dir): print("Aligned directory not found. All faces listed in the alignments file " "will be converted") else: faces_to_swap = [Path(path) for path in get_image_paths(input_aligned_dir)] if not faces_to_swap: print("Aligned directory is empty, no faces will be converted!") elif len(faces_to_swap) <= len(self.input_images) / 3: print("Aligned directory contains an amount of images much less than the input, \ are you sure this is the right directory?") return faces_to_swap
def get_aligned_directory(self): """ Check for the existence of an aligned directory for identifying which faces in the target frames should be swapped """ faces_to_swap = None input_aligned_dir = self.args.input_aligned_dir if input_aligned_dir is None: print("Aligned directory not specified. All faces listed in the " "alignments file will be converted") elif not os.path.isdir(input_aligned_dir): print("Aligned directory not found. All faces listed in the " "alignments file will be converted") else: faces_to_swap = [Path(path) for path in get_image_paths(input_aligned_dir)] if not faces_to_swap: print("Aligned directory is empty, no faces will be converted!") elif len(faces_to_swap) <= len(self.input_images) / 3: print("Aligned directory contains an amount of images much " "less than the input, are you sure this is the right " "directory?") return faces_to_swap
def get_images(self): """ Check the image dirs exist, contain images and return the image objects """ logger.debug("Getting image paths") images = dict() for side in ("a", "b"): image_dir = getattr(self.args, "input_{}".format(side)) if not os.path.isdir(image_dir): logger.error("Error: '%s' does not exist", image_dir) exit(1) if not os.listdir(image_dir): logger.error("Error: '%s' contains no images", image_dir) exit(1) images[side] = get_image_paths(image_dir) logger.info("Model A Directory: %s", self.args.input_a) logger.info("Model B Directory: %s", self.args.input_b) logger.debug("Got image paths: %s", [(key, str(len(val)) + " images") for key, val in images.items()]) return images