                          "loglevel": self.args.loglevel}
          self.extractor = Extractor(None, extract_args)
          self.extractor.launch_detector()
          self.extractor.launch_aligner()
  
      def load_model(self):
          """ Load the model requested for conversion """
          logger.debug("Loading Model")
          model_dir = get_folder(self.args.model_dir)
          model = PluginLoader.get_model(self.args.trainer)(model_dir, self.args.gpus, predict=True)
          logger.debug("Loaded Model")
          return model
  
      def load_converter(self, model):
          """ Load the requested converter for conversion """
          conv = self.args.converter
          converter = PluginLoader.get_converter(conv)(
              model.converter(self.args.swap_model),
              model=model,
              arguments=self.args)
          return converter
  
      def prepare_images(self):
          """ Prepare the images for conversion """
          filename = ""
          if self.extractor:
              load_queue = queue_manager.get_queue("load")
          for filename, image in tqdm(self.images.load(),
                                      total=self.images.images_found,
                                      file=sys.stdout):
  
              if (self.args.discard_frames and
                      self.opts.check_skipframe(filename) == "discard"):
                  continue
  
              frame = os.path.basename(filename)
              if self.extractor:
                  detected_faces = self.detect_faces(load_queue, filename, image)
 
</s> remove             if not skip:
                for face in faces:
                    image = converter.patch_image(image, face)
                filename = str(self.output_dir / Path(filename).name)
 </s> add     def load_model(self):
        """ Load the model requested for conversion """
        logger.debug("Loading Model")
        model_dir = get_folder(self.args.model_dir, make_folder=False)
        if not model_dir:
            logger.error("%s does not exist.", self.args.model_dir)
            exit(1)
        trainer = self.get_trainer(model_dir)
        model = PluginLoader.get_model(trainer)(model_dir, self.args.gpus, predict=True)
        logger.debug("Loaded Model")
        return model </s> remove             frame = os.path.basename(filename)
            if self.extractor:
                detected_faces = self.detect_faces(load_queue, filename, image)
            else:
                detected_faces = self.alignments_faces(frame, image)

            faces_count = len(detected_faces)
            if faces_count != 0:
                # Post processing requires a dict with "detected_faces" key
                self.post_process.do_actions(
                    {"detected_faces": detected_faces})
                self.faces_count += faces_count

            if faces_count > 1:
                self.verify_output = True
                logger.verbose("Found more than one face in "
                               "an image! '%s'", frame)

            yield filename, image, detected_faces
 </s> add             detected_faces = self.get_detected_faces(filename, image, extract_queue)
            item = dict(filename=filename, image=image, detected_faces=detected_faces)
            self.load_queue.put(item) </s> remove     def convert(self, converter, item):
        """ Apply the conversion transferring faces onto frames """
        try:
            filename, image, faces = item
            skip = self.opts.check_skipframe(filename)
 </s> add     def detect_faces(self, load_queue, filename, image):
        """ Extract the face from a frame (If alignments file not found) """
        inp = {"filename": filename,
               "image": image}
        load_queue.put(inp)
        faces = next(self.extractor.detect_faces())

        landmarks = faces["landmarks"]
        detected_faces = faces["detected_faces"]
        final_faces = list()

        for idx, face in enumerate(detected_faces):
            detected_face = DetectedFace()
            detected_face.from_dlib_rect(face)
            detected_face.landmarksXY = landmarks[idx]
            final_faces.append(detected_face)
        return final_faces

    # Saving tasks
    def save(self, completion_event):
        """ Save the converted images """
        logger.debug("Save Images: Start")
        for _ in tqdm(range(self.total_count), desc="Converting", file=sys.stdout):
            if self.save_queue.shutdown.is_set():
                logger.debug("Save Queue: Stop signal received. Terminating")
                break
            item = self.save_queue.get()
            if item == "EOF":
                break
            filename, image = item
            self.writer.write(filename, image)
        self.writer.close()
        completion_event.set()
        logger.debug("Save Faces: Complete")


class Predict():
    """ Predict faces from incoming queue """
    def __init__(self, in_queue, queue_size, arguments):
        logger.debug("Initializing %s: (args: %s, queue_size: %s, in_queue: %s)",
                     self.__class__.__name__, arguments, queue_size, in_queue)
        self.batchsize = min(queue_size, 16)
        self.args = arguments
        self.in_queue = in_queue
        self.out_queue = queue_manager.get_queue("patch")
        self.serializer = Serializer.get_serializer("json")
        self.faces_count = 0
        self.verify_output = False
        self.pre_process = PostProcess(arguments)
        self.model = self.load_model()
        self.predictor = self.model.converter(self.args.swap_model)
        self.queues = dict()

        self.thread = MultiThread(self.predict_faces, thread_count=1)
        self.thread.start()
        logger.debug("Initialized %s: (out_queue: %s)", self.__class__.__name__, self.out_queue)

    @property
    def coverage_ratio(self):
        """ Return coverage ratio from training options """
        return self.model.training_opts["coverage_ratio"]

    @property
    def input_size(self):
        """ Return the model input size """
        return self.model.input_shape[0]

    @property
    def output_size(self):
        """ Return the model output size """
        return self.model.output_shape[0]

    @property
    def input_mask(self):
        """ Return the input mask """
        mask = np.zeros(self.model.state.mask_shapes[0], dtype="float32")
        retval = np.expand_dims(mask, 0)
        return retval

    @property
    def has_predicted_mask(self):
        """ Return whether this model has a predicted mask """
        return bool(self.model.state.mask_shapes) </s> remove             Note: GAN prediction outputs a mask + an image, while other
            predicts only an image. """
        Utils.set_verbosity(self.args.loglevel)
 </s> add         Utils.finalize(self.images.images_found,
                       self.predictor.faces_count,
                       self.predictor.verify_output)
        logger.debug("Completed Conversion")

    def convert_images(self):
        """ Convert the images """
        logger.debug("Converting images")
        save_queue = queue_manager.get_queue("save")
        patch_queue = queue_manager.get_queue("patch")
        pool = PoolProcess(self.converter.process, patch_queue, save_queue,
                           processes=self.pool_processes)
        pool.start()
        while True:
            self.check_thread_error()
            if self.disk_io.completion_event.is_set():
                break
            sleep(1)
        pool.join()

        save_queue.put("EOF")
        logger.debug("Converted images")

    def check_thread_error(self):
        """ Check and raise thread errors """
        for thread in (self.predictor.thread, self.disk_io.load_thread, self.disk_io.save_thread):
            thread.check_and_raise_error()

    def patch_iterator(self, processes):
        """ Prepare the images for conversion """
        out_queue = queue_manager.get_queue("out")
        completed = 0

        while True:
            try:
                item = out_queue.get(True, 1)
            except QueueEmpty:
                self.check_thread_error()
                continue
            self.check_thread_error() </s> remove         for idx, face in enumerate(detected_faces):
            detected_face = DetectedFace()
            detected_face.from_dlib_rect(face)
            detected_face.landmarksXY = landmarks[idx]
            final_faces.append(detected_face)
        return final_faces
 </s> add     def get_detected_faces(self, filename, image, extract_queue):
        """ Return detected faces from alignments or detector """
        logger.trace("Getting faces for: '%s'", filename)
        if not self.extractor:
            detected_faces = self.alignments_faces(os.path.basename(filename), image)
        else:
            detected_faces = self.detect_faces(extract_queue, filename, image)
        logger.trace("Got %s faces for: '%s'", len(detected_faces), filename)
        return detected_faces
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
                          "loglevel": self.args.loglevel}
          self.extractor = Extractor(None, extract_args)
          self.extractor.launch_detector()
          self.extractor.launch_aligner()
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
        logger.debug("Loaded extractor")

    def init_threads(self):
        """ Initialize queues and threads """
        logger.debug("Initializing DiskIO Threads")
        for task in ("load", "save"):
            self.add_queue(task)
            self.start_thread(task)
        logger.debug("Initialized DiskIO Threads")

    def add_queue(self, task):
        """ Add the queue to queue_manager and set queue attribute """
        logger.debug("Adding queue for task: '%s'", task)
        q_name = "convert_in" if task == "load" else task
        setattr(self, "{}_queue".format(task), queue_manager.get_queue(q_name))
        logger.debug("Added queue for task: '%s'", task)

    def start_thread(self, task):
        """ Start the DiskIO thread """
        logger.debug("Starting thread: '%s'", task)
        args = self.completion_event if task == "save" else None
        func = getattr(self, task)
        io_thread = MultiThread(func, args, thread_count=1)
        io_thread.start()
        setattr(self, "{}_thread".format(task), io_thread)
        logger.debug("Started thread: '%s'", task)

    # Loading tasks
    def load(self, *args):  # pylint: disable=unused-argument
        """ Load the images with detected_faces"""
        logger.debug("Load Images: Start")
        extract_queue = queue_manager.get_queue("extract_in") if self.extractor else None
        idx = 0
        for filename, image in self.images.load():
            idx += 1
            if self.load_queue.shutdown.is_set():
                logger.debug("Load Queue: Stop signal received. Terminating")
                break
            if image is None or not image.any():
                logger.warning("Unable to open image. Skipping: '%s'", filename)
                continue
            if self.check_skipframe(filename):
                if self.args.keep_unchanged:
                    logger.trace("Saving unchanged frame: %s", filename)
                    out_file = os.path.join(self.args.output_dir, os.path.basename(filename))
                    self.save_queue.put((out_file, image))
                else:
                    logger.trace("Discarding frame: '%s'", filename)
                  continue
  
              frame = os.path.basename(filename)
              if self.extractor:
                  detected_faces = self.detect_faces(load_queue, filename, image)
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 replace replace replace replace replace replace keep keep keep keep keep
 Convert refactor (#703)

* Separate predict and implement pool

* Add check and raise error to multithreading

Box functions to config. Add crop box option.

* All masks to mask module. Refactor convert masks

Predicted mask passed from model. Cli update

* Intesect box with mask and fixes

* Use raw NN output for convert

Use raw mask for face adjustments. Split adjustments to pre and post warp

* Separate out adjustments. Add unmask sharpen

* Set sensible defaults. Pre PR Testing

* Fix queue sizes. Move masked.py to lib

* Fix Skip Frames. Fix GUI Config popup

* Sensible queue limits. Add a less resource intensive single processing mode

* Fix predicted mask. Amend smooth box defaults

* Deterministic ordering for video output

* Video to Video convert implemented

* Fixups

- Remove defaults from folders across all stages
- Move match-hist and aca into color adjustments selectable
- Handle crashes properly for pooled processes
- Fix output directory does not exist error when creating a new output folder
- Force output to frames if input is not a video

* Add Color Transfer adjustment method

Wrap info text in GUI plugin configure popup

* Refactor image adjustments. Easier to create plugins

Start implementing config options for video encoding

* Add video encoding config options

Allow video encoding for frames input (must pass in a reference video)
Move video and image output writers to plugins

* Image writers config options

Move scaling to cli
Move draw_transparent to images config
Add config options for cv2 writer
Add Pillow image writer

* Add gif filetype to Pillow. Fix draw transparent for Pillow

* Add Animated GIF writer

standardize opencv/pillow defaults

* [speedup] Pre-encode supported writers in the convert pool (opencv, pillow)

Move scaling to convert pool
Remove dfaker mask

* Fix default writer

* Bugfixes

* Better custom argparse formatting 
scripts/convert.py