  
      def launch_aligner(self):
          """ Launch the face aligner """
          logger.debug("Launching Aligner")
          kwargs = {"in_queue": self.queues["extract_align_in"],
                    "out_queue": self.queues["extract_align_out"]}
  
          process = SpawnProcess(self.aligner.run, **kwargs)
          event = process.event
          error = process.error
          process.start()
          self.processes.append(process)
  
          # Wait for Aligner to take it's VRAM
          # The first ever load of the model for FAN has reportedly taken
          # up to 3-4 minutes, hence high timeout.
          # TODO investigate why this is and fix if possible
          for mins in reversed(range(5)):
              for seconds in range(60):
                  event.wait(seconds)
                  if event.is_set():
                      break
                  if error.is_set():
                      break
              if event.is_set():
                  break
              if mins == 0 or error.is_set():
                  raise ValueError("Error initializing Aligner")
              logger.info("Waiting for Aligner... Time out in %s minutes", mins)
  
          logger.debug("Launched Aligner")
  
      def launch_detector(self):
          """ Launch the face detector """
          logger.debug("Launching Detector")
 
</s> remove         kwargs = {"in_queue": self.queues["extract_detect_in"],
                  "out_queue": self.queues["extract_align_in"]}
        mp_func = PoolProcess if self.detector.parent_is_pool else SpawnProcess
        process = mp_func(self.detector.run, **kwargs)

        event = process.event if hasattr(process, "event") else None
        error = process.error if hasattr(process, "error") else None
        process.start()
        self.processes.append(process)

        if event is None:
            logger.debug("Launched Detector")
            return

        for mins in reversed(range(5)):
            for seconds in range(60):
                event.wait(seconds)
                if event.is_set():
                    break
                if error and error.is_set():
                    break
            if event.is_set():
                break
            if mins == 0 or (error and error.is_set()):
                raise ValueError("Error initializing Detector")
            logger.info("Waiting for Detector... Time out in %s minutes", mins)

 </s> add         kwargs = dict(in_queue=self._queues["extract_detect_in"],
                      out_queue=self._queues["extract_align_in"],
                      queue_size=self._queue_size)
        self._detector.initialize(**kwargs)
        self._detector.start() </s> remove         out_queue = queue_manager.get_queue("out")
        kwargs = {"in_queue": queue_manager.get_queue("in"),
                  "out_queue": out_queue}

        for plugin in ("fan", "cv2_dnn"):
            aligner = PluginLoader.get_aligner(plugin)(loglevel=self.args.loglevel)
            process = SpawnProcess(aligner.run, **kwargs)
            event = process.event
            process.start()
            # Wait for Aligner to take init
            # The first ever load of the model for FAN has reportedly taken
            # up to 3-4 minutes, hence high timeout.
            event.wait(300)

            if not event.is_set():
                if plugin == "fan":
                    process.join()
                    logger.error("Error initializing FAN. Trying CV2-DNN")
                    continue
                else:
                    raise ValueError("Error inititalizing Aligner")
            if plugin == "cv2_dnn":
                return

            try:
                err = None
                err = out_queue.get(True, 1)
            except QueueEmpty:
                pass
            if not err:
                break
            process.join()
            logger.error("Error initializing FAN. Trying CV2-DNN")
 </s> add         kwargs = dict(in_queue=queue_manager.get_queue("in"),
                      out_queue=queue_manager.get_queue("out"),
                      queue_size=8)
        aligner = PluginLoader.get_aligner("fan")(normalize_method="hist")
        aligner.batchsize = 1
        aligner.initialize(**kwargs)
        aligner.start() </s> remove     def launch_detector(self):
 </s> add     def _launch_detector(self): </s> remove         out_queue = queue_manager.get_queue("out")

        d_kwargs = {"in_queue": queue_manager.get_queue("in"),
                    "out_queue": queue_manager.get_queue("align")}
        a_kwargs = {"in_queue": queue_manager.get_queue("align"),
                    "out_queue": out_queue}

        detector = PluginLoader.get_detector("manual")(loglevel=loglevel)
        detect_process = SpawnProcess(detector.run, **d_kwargs)
        d_event = detect_process.event
        detect_process.start()

        plugins = ["fan_amd"] if get_backend() == "amd" else ["fan"]
        plugins.append("cv2_dnn")
        for plugin in plugins:
            aligner = PluginLoader.get_aligner(plugin)(loglevel=loglevel,
                                                       normalize_method="hist")
            align_process = SpawnProcess(aligner.run, **a_kwargs)
            a_event = align_process.event
            align_process.start()

            # Wait for Aligner to initialize
            # The first ever load of the model for FAN has reportedly taken
            # up to 3-4 minutes, hence high timeout.
            a_event.wait(300)
            if not a_event.is_set():
                if plugin.startswith("fan"):
                    align_process.join()
                    logger.error("Error initializing FAN. Trying CV2-DNN")
                    continue
                else:
                    raise ValueError("Error inititalizing Aligner")
            if plugin == "cv2_dnn":
                break

            try:
                err = None
                err = out_queue.get(True, 1)
            except QueueEmpty:
                pass
            if not err:
                break
            align_process.join()
            logger.error("Error initializing FAN. Trying CV2-DNN")

        d_event.wait(10)
        if not d_event.is_set():
            raise ValueError("Error inititalizing Detector")

        self.extractor["detect"] = detector
        self.extractor["align"] = aligner
 </s> add         extractor = Extractor("manual", "fan", multiprocess=True, normalize_method="hist")
        self.queues["in"] = extractor.input_queue
        # Set the batchsizes to 1
        extractor.set_batchsize("detector", 1)
        extractor.set_batchsize("aligner", 1)
        extractor.launch() </s> remove     def launch_aligner(self):
 </s> add     def _launch_aligner(self):
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
  
      def launch_aligner(self):
          """ Launch the face aligner """
          logger.debug("Launching Aligner")
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
        kwargs = dict(in_queue=self._queues["extract_align_in"],
                      out_queue=self._queues["extract_align_out"],
                      queue_size=self._queue_size)
        self._aligner.initialize(**kwargs)
        self._aligner.start()
          logger.debug("Launched Aligner")
  
      def launch_detector(self):
          """ Launch the face detector """
          logger.debug("Launching Detector")
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 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