          if not model.load(self.arguments.swap_model):
              print('Model Not Found! A valid model must be provided to continue!')
              exit(1)
  
          input_aligned_dir = Path(self.arguments.input_dir)/Path('aligned')
          if self.arguments.input_aligned_dir is not None:
              input_aligned_dir = self.arguments.input_aligned_dir
          try:
              self.input_aligned_dir = [Path(path) for path in get_image_paths(input_aligned_dir)]
              if len(self.input_aligned_dir) == 0:
                  print('Aligned directory is empty, no faces will be converted!')
              elif len(self.input_aligned_dir) <= len(self.input_dir)/3:
                  print('Aligned directory contains an amount of images much less than the input, are you sure this is the right directory?')
          except:
              print('Aligned directory not found. All faces listed in the alignments file will be converted.')
  
          converter = PluginLoader.get_converter(conv_name)(model.converter(False),
              trainer=self.arguments.trainer,
              blur_size=self.arguments.blur_size,
              seamless_clone=self.arguments.seamless_clone,
              sharpen_image=self.arguments.sharpen_image,
              mask_type=self.arguments.mask_type,
              erosion_kernel_size=self.arguments.erosion_kernel_size,
              match_histogram=self.arguments.match_histogram,
              smooth_mask=self.arguments.smooth_mask,
              avg_color_adjust=self.arguments.avg_color_adjust
          )
  
          batch = BackgroundGenerator(self.prepare_images(), 1)
  
          # frame ranges stuff...
          self.frame_ranges = None
 
</s> remove     def process(self):
        # Original & LowMem models go with Adjust or Masked converter
        # Note: GAN prediction outputs a mask + an image, while other predicts only an image
        model_name = self.arguments.trainer
        conv_name = self.arguments.converter
        self.input_aligned_dir = None

        model = PluginLoader.get_model(model_name)(get_folder(self.arguments.model_dir), self.arguments.gpus)
        if not model.load(self.arguments.swap_model):
            print('Model Not Found! A valid model must be provided to continue!')
            exit(1)
 </s> add         self.images = Images(self.args)
        self.faces = Faces(self.args)
        self.alignments = Alignments(self.args) </s> remove         # frame ranges stuff...
        self.frame_ranges = None
 </s> add         if not self.alignments.have_alignments():
            self.generate_alignments() </s> remove         batch = BackgroundGenerator(self.prepare_images(), 1)
 </s> add     def process(self):
        """ Original & LowMem models go with Adjust or Masked converter
            Note: GAN prediction outputs a mask + an image, while other predicts only an image """
        Utils.set_verbosity(self.args.verbose) </s> remove             if not skip: # process frame as normal
                for idx, face in faces:
                    if self.input_aligned_dir is not None and self.check_skipface(filename, idx):
                        print ('face {} for frame {} was deleted, skipping'.format(idx, os.path.basename(filename)))
                        continue
                    # Check for image rotations and rotate before mapping face
                    if face.r != 0:
                        height, width = image.shape[:2]
                        image = rotate_image(image, face.r)
                        image = converter.patch_image(image, face, 64 if "128" not in self.arguments.trainer else 128)
                        # TODO: This switch between 64 and 128 is a hack for now. We should have a separate cli option for size
                        image = rotate_image(image, face.r * -1, rotated_width=width, rotated_height=height)
                    else:
                        image = converter.patch_image(image, face, 64 if "128" not in self.arguments.trainer else 128)
                        # TODO: This switch between 64 and 128 is a hack for now. We should have a separate cli option for size

            output_file = get_folder(self.output_dir) / Path(filename).name
            cv2.imwrite(str(output_file), image)
        except Exception as e:
            print('Failed to convert image: {}. Reason: {}'.format(filename, e))
 </s> add         if not model.load(self.args.swap_model):
            print("Model Not Found! A valid model must be provided to continue!")
            exit(1)

        return model

    def load_converter(self, model):
        """ Load the requested converter for conversion """
        args = self.args
        conv = args.converter

        converter = PluginLoader.get_converter(conv)(model.converter(False),
                                                     trainer=args.trainer,
                                                     blur_size=args.blur_size,
                                                     seamless_clone=args.seamless_clone,
                                                     sharpen_image=args.sharpen_image,
                                                     mask_type=args.mask_type,
                                                     erosion_kernel_size=args.erosion_kernel_size,
                                                     match_histogram=args.match_histogram,
                                                     smooth_mask=args.smooth_mask,
                                                     avg_color_adjust=args.avg_color_adjust)
        return converter </s> remove     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("Filter: {}".format(self.arguments.filter))
        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))

        try:
            if self.arguments.rotate_images is not None and self.arguments.rotate_images != "off":
                if self.arguments.rotate_images == "on":
                    self.rotation_angles = range(90, 360, 90)
                else:
                    rotation_angles = [int(angle) for angle in self.arguments.rotate_images.split(",")]
                    if len(rotation_angles) == 1:
                        rotation_step_size = rotation_angles[0]
                        self.rotation_angles = range(rotation_step_size, 360, rotation_step_size)
                    elif len(rotation_angles) > 1:
                        self.rotation_angles = rotation_angles
        except AttributeError:
            pass

        print('Starting, this may take a while...')

        try:
            if self.arguments.skip_existing:
                self.already_processed = get_image_paths(self.arguments.output_dir)
        except AttributeError:
            pass
    
        self.output_dir = get_folder(self.arguments.output_dir)

        try:
            try:
                if self.arguments.skip_existing:
                    self.input_dir = get_image_paths(self.arguments.input_dir, self.already_processed)
                    print('Excluding %s files' % len(self.already_processed))
                else:
                    self.input_dir = get_image_paths(self.arguments.input_dir)
            except AttributeError:
                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 read_alignments(self):

        fn = os.path.join(str(self.arguments.input_dir),"alignments.{}".format(self.serializer.ext))
        if self.arguments.alignments_path is not None:
            fn = self.arguments.alignments_path

        try:
            print("Reading alignments from: {}".format(fn))
            with open(fn, self.serializer.roptions) as f:
                self.faces_detected = self.serializer.unmarshal(f.read())
        except Exception as e:
            print("{} not read!".format(fn))
            print(str(e))
            self.faces_detected = dict()

    def write_alignments(self):

        fn = os.path.join(str(self.arguments.input_dir), "alignments.{}".format(self.serializer.ext))
        if self.arguments.alignments_path is not None:
            fn = self.arguments.alignments_path
        print("Alignments filepath: %s" % fn)
        
        if self.arguments.skip_existing:
            if os.path.exists(fn):
                with open(fn, self.serializer.roptions) as inf:
                    data = self.serializer.unmarshal(inf.read())
                    for k, v in data.items():
                        self.faces_detected[k] = v
            else:
                print('Existing alignments file "%s" not found.' % fn)
        try:
            print("Writing alignments to: {}".format(fn))
            with open(fn, self.serializer.woptions) as fh:
                fh.write(self.serializer.marshal(self.faces_detected))
        except Exception as e:
            print("{} not written!".format(fn))
            print(str(e))
            self.faces_detected = dict()

    def read_directory(self):
        self.images_found = len(self.input_dir)
        return self.input_dir

    def have_face(self, filename):
        return os.path.basename(filename) in self.faces_detected

    def have_alignments(self):
        fn = os.path.join(str(self.arguments.input_dir), "alignments.{}".format(self.serializer.ext))
        return os.path.exists(fn)
 </s> add     @staticmethod
    def create_parser(subparser, command, description):
        """ Create the parser for the selected command """
        parser = subparser.add_parser(
            command,
            help=description,
            description=description,
            epilog="Questions and feedback: \
            https://github.com/deepfakes/faceswap-playground")
        return parser
        self.opts = OptionalActions(self.args, self.images.input_images)
          if not model.load(self.arguments.swap_model):
              print('Model Not Found! A valid model must be provided to continue!')
              exit(1)
  
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
        self.opts = OptionalActions(self.args, self.images.input_images)
  
          batch = BackgroundGenerator(self.prepare_images(), 1)
  
          # frame ranges stuff...
          self.frame_ranges = None
keep keep keep keep replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace keep keep keep keep keep
 cli/scripts Refactor (#367)

* Refactor for PEP 8 and split process function

* Remove backwards compatibility for skip frames

* Split optional functions into own class. Make functions more modular

* Conform scripts folder to PEP 8

* train.py - Fix write image bug. Make more modular

* extract.py - Make more modular, Put optional actions into own class

* cli.py - start PEP 8

* cli,py - Pep 8. Refactor and make modular. Bugfixes

* 1st round refactor. Completely untested and probably broken.

* convert.py: Extract alignments from frames if they don't exist

* BugFix: SkipExisting broken since face name refactor

* Extract.py tested

* Minor formatting

* convert.py + train.py amended not tested

* train.py - Semi-fix for hang on reaching target iteration. Now quits on preview mode
Make tensorflow / system warning less verbose

* 2nd pass refactor. Semi tested

bugfixes

* Remove obsolete code. imread/write to Utils

* rename inout.py to fsmedia.py

* Final bugfixes 
scripts/convert.py