          retval = self.is_parallel or self.phase == "align"
          logger.trace(retval)
          return retval
  
      @staticmethod
      def load_detector(detector, loglevel, rotation, min_size, configfile):
          """ Set global arguments and load detector plugin """
          detector_name = detector.replace("-", "_").lower()
          logger.debug("Loading Detector: '%s'", detector_name)
          detector = PluginLoader.get_detector(detector_name)(loglevel=loglevel,
                                                              rotation=rotation,
                                                              min_size=min_size,
                                                              configfile=configfile)
          return detector
  
      @staticmethod
      def load_aligner(aligner, loglevel, configfile, normalize_method):
          """ Set global arguments and load aligner plugin """
          aligner_name = aligner.replace("-", "_").lower()
 
</s> remove     @staticmethod
    def load_aligner(aligner, loglevel, configfile, normalize_method):
        """ Set global arguments and load aligner plugin """
        aligner_name = aligner.replace("-", "_").lower()
        logger.debug("Loading Aligner: '%s'", aligner_name)
        aligner = PluginLoader.get_aligner(aligner_name)(loglevel=loglevel,
                                                         configfile=configfile,
                                                         normalize_method=normalize_method)
        return aligner
 </s> add         This should be set prior to :func:`launch` if the batchsize is to be manually overriden </s> remove     def add_queues(self):
        """ Add the required processing queues to Queue Manager """
        queues = dict()
        for task in ("extract_detect_in", "extract_align_in", "extract_align_out"):
            # Limit queue size to avoid stacking ram
            size = 32
            if task == "extract_detect_in" or (not self.is_parallel
                                               and task == "extract_align_in"):
                size = 64
            queue_manager.add_queue(task, maxsize=size)
            queues[task] = queue_manager.get_queue(task)
        logger.debug("Queues: %s", queues)
        return queues
 </s> add     # << INTERNAL PLUGIN HANDLING >> #
    @staticmethod
    def _load_detector(detector, rotation, min_size, configfile):
        """ Set global arguments and load detector plugin """
        detector_name = detector.replace("-", "_").lower()
        logger.debug("Loading Detector: '%s'", detector_name)
        detector = PluginLoader.get_detector(detector_name)(rotation=rotation,
                                                            min_size=min_size,
                                                            configfile=configfile)
        return detector </s> remove     def launch(self):
        """ Launches the plugins
            This can be called multiple times depending on the phase/whether multiprocessing
            is enabled.

            If multiprocessing:
                launches both plugins, but aligner first so that it's VRAM can be allocated
                prior to giving the remaining to the detector
            If not multiprocessing:
                Launches the relevant plugin for the current phase """
        if self.is_parallel:
            logger.debug("Launching aligner and detector")
            self.launch_aligner()
            self.launch_detector()
        elif self.phase == "detect":
            logger.debug("Launching detector")
            self.launch_detector()
        else:
            logger.debug("Launching aligner")
            self.launch_aligner()
 </s> add     @staticmethod
    def _load_aligner(aligner, configfile, normalize_method):
        """ Set global arguments and load aligner plugin """
        aligner_name = aligner.replace("-", "_").lower()
        logger.debug("Loading Aligner: '%s'", aligner_name)
        aligner = PluginLoader.get_aligner(aligner_name)(configfile=configfile,
                                                         normalize_method=normalize_method)
        return aligner </s> remove         """ Return true if this is the final extractor pass """
        retval = self.is_parallel or self.phase == "align"
 </s> add         """ bool, Return ``True`` if this is the final extractor pass otherwise ``False``

        Useful for iterating over the pipeline :attr:`passes` or :func:`detected_faces` and
        handling accordingly.

        Example
        -------
        >>> for face in extractor.detected_faces():
        >>>     if extractor.final_pass:
        >>>         <do final processing>
        >>>     else:
        >>>         <do intermediate processing>
        >>>         extractor.input_queue.put({"filename": "path/to/image/file",
        >>>                                    "image": np.array(image),
        >>>                                    "detected_faces": [<DetectedFace objects]})
        """
        retval = self._is_parallel or self.phase == "align" </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()
    def set_batchsize(self, plugin_type, batchsize):
        """ Set the batchsize of a given :attr:`plugin_type` to the given :attr:`batchsize`.
          retval = self.is_parallel or self.phase == "align"
          logger.trace(retval)
          return retval
  
    def set_batchsize(self, plugin_type, batchsize):
        """ Set the batchsize of a given :attr:`plugin_type` to the given :attr:`batchsize`.
    def set_batchsize(self, plugin_type, batchsize):
        """ Set the batchsize of a given :attr:`plugin_type` to the given :attr:`batchsize`.
    def set_batchsize(self, plugin_type, batchsize):
        """ Set the batchsize of a given :attr:`plugin_type` to the given :attr:`batchsize`.
    def set_batchsize(self, plugin_type, batchsize):
        """ Set the batchsize of a given :attr:`plugin_type` to the given :attr:`batchsize`.
    def set_batchsize(self, plugin_type, batchsize):
        """ Set the batchsize of a given :attr:`plugin_type` to the given :attr:`batchsize`.
    def set_batchsize(self, plugin_type, batchsize):
        """ Set the batchsize of a given :attr:`plugin_type` to the given :attr:`batchsize`.
    def set_batchsize(self, plugin_type, batchsize):
        """ Set the batchsize of a given :attr:`plugin_type` to the given :attr:`batchsize`.
    def set_batchsize(self, plugin_type, batchsize):
        """ Set the batchsize of a given :attr:`plugin_type` to the given :attr:`batchsize`.
    def set_batchsize(self, plugin_type, batchsize):
        """ Set the batchsize of a given :attr:`plugin_type` to the given :attr:`batchsize`.
    def set_batchsize(self, plugin_type, batchsize):
        """ Set the batchsize of a given :attr:`plugin_type` to the given :attr:`batchsize`.
  
      @staticmethod
      def load_aligner(aligner, loglevel, configfile, normalize_method):
          """ Set global arguments and load aligner plugin """
          aligner_name = aligner.replace("-", "_").lower()
keep keep keep keep replace replace replace replace replace replace replace replace replace 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 
plugins/extract/pipeline.py