          logger.info("Extracting and aligning face for Face Filter...")
          self.filter = self.load_face_filter(**kwargs)
          logger.debug("Initialized %s", self.__class__.__name__)
  
      def load_face_filter(self, filter_lists, ref_threshold, aligner, detector, loglevel,
                           multiprocess):
          """ Load faces to filter out of images """
          if not any(val for val in filter_lists.values()):
              return None
  
 
</s> remove     def align_faces(self, detector_name, aligner_name, loglevel, multiprocess):
 </s> add     def align_faces(self, detector_name, aligner_name, multiprocess):
 </s> remove     def __init__(self, reference_file_paths, nreference_file_paths, detector, aligner, loglevel,
 </s> add     def __init__(self, reference_file_paths, nreference_file_paths, detector, aligner,
 </s> remove         extractor = Extractor(detector_name, aligner_name, loglevel, multiprocess=multiprocess)
 </s> add         extractor = Extractor(detector_name, aligner_name, multiprocess=multiprocess)
 </s> remove         self.detector = self.load_detector(detector, loglevel, rotate_images, min_size, configfile)
        self.aligner = self.load_aligner(aligner, loglevel, configfile, normalize_method)
        self.is_parallel = self.set_parallel_processing(multiprocess)
        self.processes = list()
        self.queues = self.add_queues()
 </s> add         self._queue_size = 32
        self._vram_buffer = 320  # Leave a buffer for VRAM allocation
        self._detector = self._load_detector(detector, rotate_images, min_size, configfile)
        self._aligner = self._load_aligner(aligner, configfile, normalize_method)
        self._is_parallel = self._set_parallel_processing(multiprocess)
        self._queues = self._add_queues() </s> remove 
    # <<< FINALIZE METHODS >>> #
    def finalize(self, output):
        """ This should be called as the final task of each plugin
            aligns faces and puts to the out queue """
        if output == "EOF":
            logger.trace("Item out: %s", output)
            self.queues["out"].put("EOF")
            return
        logger.trace("Item out: %s", {key: val
                                      for key, val in output.items()
                                      if key != "image"})
        self.queues["out"].put((output))

    # <<< MISC METHODS >>> #
    def get_vram_free(self):
        """ Return free and total VRAM on card with most VRAM free"""
        stats = GPUStats()
        vram = stats.get_card_most_free(supports_plaidml=self.supports_plaidml)
        logger.verbose("Using device %s with %sMB free of %sMB",
                       vram["device"],
                       int(vram["free"]),
                       int(vram["total"]))
        return int(vram["card_id"]), int(vram["free"]), int(vram["total"])

    def get_item(self):
        """ Yield one item from the queue """
        while True:
            item = self.queues["in"].get()
            if isinstance(item, dict):
                logger.trace("Item in: %s", {key: val
                                             for key, val in item.items()
                                             if key != "image"})
                # Pass Detector failures straight out and quit
                if item.get("exception", None):
                    self.queues["out"].put(item)
                    exit(1)
            else:
                logger.trace("Item in: %s", item)
            yield item
            if item == "EOF":
                break
 </s> add 
    def load_face_filter(self, filter_lists, ref_threshold, aligner, detector,
          logger.info("Extracting and aligning face for Face Filter...")
          self.filter = self.load_face_filter(**kwargs)
          logger.debug("Initialized %s", self.__class__.__name__)
  
    def load_face_filter(self, filter_lists, ref_threshold, aligner, detector,
                           multiprocess):
          """ Load faces to filter out of images """
          if not any(val for val in filter_lists.values()):
              return None
  
keep keep keep keep replace keep keep keep keep keep
 De-Multiprocess Extract (#871)

* requirements.txt: - Pin opencv to 4.1.1 (fixes cv2-dnn error)

* lib.face_detect.DetectedFace: change LandmarksXY to landmarks_xy. Add left, right, top, bottom attributes

* lib.model.session: Session manager for loading models into different graphs (for Nvidia + CPU)

* plugins.extract._base: New parent class for all extract plugins

* plugins.extract.pipeline. Remove MultiProcessing. Dynamically limit batchsize for Nvidia cards. Remove loglevel input

* S3FD + FAN plugins. Standardise to Keras version for all backends

* Standardize all extract plugins to new threaded codebase

* Documentation. Start implementing Numpy style docstrings for Sphinx Documentation

* Remove s3fd_amd. Change convert OTF to expect DetectedFace object

* faces_detect - clean up and documentation

* Remove PoolProcess

* Migrate manual tool to new extract workflow

* Remove AMD specific extractor code from cli and plugins

* Sort tool to new extract workflow

* Remove multiprocessing from project

* Remove multiprocessing queues from QueueManager

* Remove multiprocessing support from logger

* Move face_filter to new extraction pipeline

* Alignments landmarksXY > landmarks_xy and legacy handling

* Intercept get_backend for sphinx doc build

# Add Sphinx documentation 
scripts/fsmedia.py