                           colorspace="RGB",
                           input_size=128,
                           **kwargs)
          self.vram = 0  # Doesn't use GPU
          self.model = None
  
      def initialize(self, *args, **kwargs):
          """ Initialization tasks to run prior to alignments """
          try:
              super().initialize(*args, **kwargs)
              logger.info("Initializing cv2 DNN Aligner...")
              logger.debug("cv2 DNN initialize: (args: %s kwargs: %s)", args, kwargs)
              logger.verbose("Using CPU for alignment")
  
              self.model = cv2.dnn.readNetFromTensorflow(  # pylint: disable=no-member
                  self.model_path)
              self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member
              self.init.set()
              logger.info("Initialized cv2 DNN Aligner.")
          except Exception as err:
              self.error.set()
              raise err
  
      def align_image(self, detected_face, image):
          """ Align the incoming image for prediction """
          logger.trace("Aligning image around center")
  
          box = (detected_face["left"],
                 detected_face["top"],
 
</s> remove     def initialize(self, *args, **kwargs):
        """ Initialization tasks to run prior to alignments """
        try:
            super().initialize(*args, **kwargs)
            logger.info("Initializing Face Alignment Network...")
            logger.debug("fan initialize: (args: %s kwargs: %s)", args, kwargs)

            _, _, vram_total = self.get_vram_free()

            if vram_total <= self.vram:
                tf_ratio = 1.0
            else:
                tf_ratio = self.vram / vram_total
            logger.verbose("Reserving %sMB for face alignments", self.vram)

            self.model = FAN(self.model_path, ratio=tf_ratio)

            self.init.set()
            logger.info("Initialized Face Alignment Network.")
        except Exception as err:
            self.error.set()
            raise err

    # DETECTED FACE BOUNDING BOX PROCESSING
    def align_image(self, detected_face, image):
        """ Get center and scale, crop and align image around center """
        logger.trace("Aligning image around center")
        center, scale = self.get_center_scale(detected_face)
        image = self.crop(image, center, scale)
 </s> add     def init_model(self):
        """ Initialize FAN model """
        model_kwargs = dict(custom_objects={'TorchBatchNorm2D': TorchBatchNorm2D})
        self.model = KSession(self.name, self.model_path, model_kwargs=model_kwargs)
        self.model.load_model()
        # Feed a placeholder so Aligner is primed for Manual tool
        placeholder = np.zeros((self.batchsize, 3, self.input_size, self.input_size),
                               dtype="float32")
        self.model.predict(placeholder)

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        # TODO Batching
        logger.trace("Aligning faces around center")
        batch["center_scale"] = self.get_center_scale(batch["detected_faces"])
        faces = self.crop(batch) </s> remove         super().__init__(git_model_id=git_model_id,
                         model_filename=model_filename,
                         colorspace="RGB",
                         input_size=128,
                         **kwargs)
 </s> add         super().__init__(git_model_id=git_model_id, model_filename=model_filename, **kwargs)

        self.name = "cv2-DNN Aligner"
        self.input_size = 128
        self.colorformat = "RGB" </s> remove     def initialize(self, *args, **kwargs):
        """ Calculate batch size """
        super().initialize(*args, **kwargs)
        logger.info("Initializing cv2 DNN Detector...")
        logger.verbose("Using CPU for detection")
        self.detector = cv2.dnn.readNetFromCaffe(self.model_path[1],  # pylint: disable=no-member
                                                 self.model_path[0])
        self.detector.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member
        self.init.set()
        logger.info("Initialized cv2 DNN Detector.")

    def detect_faces(self, *args, **kwargs):
        """ Detect faces in grayscale image """
        super().detect_faces(*args, **kwargs)
        while True:
            item = self.get_item()
            if item == "EOF":
                break
            logger.trace("Detecting faces: %s", item["filename"])
            [detect_image, scale] = self.compile_detection_image(item["image"],
                                                                 is_square=True,
                                                                 scale_up=True)
            height, width = detect_image.shape[:2]
            for angle in self.rotation:
                current_image, rotmat = self.rotate_image(detect_image, angle)
                logger.trace("Detecting faces")

                blob = cv2.dnn.blobFromImage(current_image,  # pylint: disable=no-member
                                             1.0,
                                             self.target,
                                             [104, 117, 123],
                                             False,
                                             False)
                self.detector.setInput(blob)
                detected = self.detector.forward()
                faces = list()
                for i in range(detected.shape[2]):
                    confidence = detected[0, 0, i, 2]
                    if confidence >= self.confidence:
                        logger.trace("Accepting due to confidence %s >= %s",
                                     confidence, self.confidence)
                        faces.append([(detected[0, 0, i, 3] * width),
                                      (detected[0, 0, i, 4] * height),
                                      (detected[0, 0, i, 5] * width),
                                      (detected[0, 0, i, 6] * height)])

                logger.trace("Detected faces: %s", [face for face in faces])

                if angle != 0 and faces:
                    logger.verbose("found face(s) by rotating image %s degrees", angle)

                if faces:
                    break

            detected_faces = self.process_output(faces, rotmat, scale)
            item["detected_faces"] = detected_faces
            self.finalize(item)

        self.queues["out"].put("EOF")
        logger.debug("Detecting Faces Complete")

    def process_output(self, faces, rotation_matrix, scale):
 </s> add     def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromCaffe(self.model_path[1],  # pylint: disable=no-member
                                              self.model_path[0])
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detection image(s) for prediction """
        batch["feed"] = cv2.dnn.blobFromImages(batch["scaled_image"],  # pylint: disable=no-member
                                               scalefactor=1.0,
                                               size=(self.input_size, self.input_size),
                                               mean=[104, 117, 123],
                                               swapRB=False,
                                               crop=False)
        return batch

    def predict(self, batch):
        """ Run model to get predictions """
        self.model.setInput(batch["feed"])
        predictions = self.model.forward()
        batch["prediction"] = self.finalize_predictions(predictions)
        return batch

    def finalize_predictions(self, predictions):
        """ Filter faces based on confidence level """
        faces = list()
        for i in range(predictions.shape[2]):
            confidence = predictions[0, 0, i, 2]
            if confidence >= self.confidence:
                logger.trace("Accepting due to confidence %s >= %s",
                             confidence, self.confidence)
                faces.append([(predictions[0, 0, i, 3] * self.input_size),
                              (predictions[0, 0, i, 4] * self.input_size),
                              (predictions[0, 0, i, 5] * self.input_size),
                              (predictions[0, 0, i, 6] * self.input_size)])
        logger.trace("faces: %s", faces)
        return [np.array(faces)]

    def process_output(self, batch): </s> remove         self.model = None
 </s> add         self.vram_warnings = 512  # Will run at this with warnings
        self.vram_per_batch = 64
        self.batchsize = self.config["batch-size"] </s> remove     def initialize(self, *args, **kwargs):
        """ Create the mtcnn detector """
        try:
            super().initialize(*args, **kwargs)
            logger.info("Initializing MTCNN Detector...")
            is_gpu = False

            # Must import tensorflow inside the spawned process
            # for Windows machines
            import_tensorflow()
            _, vram_free, _ = self.get_vram_free()
            mtcnn_graph = tf.Graph()

            # Windows machines sometimes misreport available vram, and overuse
            # causing OOM. Allow growth fixes that
            config = tf.ConfigProto()
            config.gpu_options.allow_growth = True  # pylint: disable=no-member

            with mtcnn_graph.as_default():  # pylint: disable=not-context-manager
                sess = tf.Session(config=config)
                with sess.as_default():  # pylint: disable=not-context-manager
                    pnet, rnet, onet = create_mtcnn(sess, self.model_path)

                if any("gpu" in str(device).lower()
                       for device in sess.list_devices()):
                    logger.debug("Using GPU")
                    is_gpu = True
            mtcnn_graph.finalize()

            if not is_gpu:
                alloc = 2048
                logger.warning("Using CPU")
            else:
                alloc = vram_free
            logger.debug("Allocated for Tensorflow: %sMB", alloc)

            self.batch_size = int(alloc / self.vram)

            if self.batch_size < 1:
                self.error.set()
                raise ValueError("Insufficient VRAM available to continue "
                                 "({}MB)".format(int(alloc)))

            logger.verbose("Processing in %s threads", self.batch_size)

            self.kwargs["pnet"] = pnet
            self.kwargs["rnet"] = rnet
            self.kwargs["onet"] = onet

            self.init.set()
            logger.info("Initialized MTCNN Detector.")
        except Exception as err:
            self.error.set()
            raise err

    def detect_faces(self, *args, **kwargs):
        """ Detect faces in Multiple Threads """
        super().detect_faces(*args, **kwargs)
        workers = MultiThread(target=self.detect_thread, thread_count=self.batch_size)
        workers.start()
        workers.join()
        sentinel = self.queues["in"].get()
        self.queues["out"].put(sentinel)
        logger.debug("Detecting Faces complete")

    def detect_thread(self):
        """ Detect faces in rgb image """
        logger.debug("Launching Detect")
        while True:
            item = self.get_item()
            if item == "EOF":
                break
            logger.trace("Detecting faces: '%s'", item["filename"])
            [detect_image, scale] = self.compile_detection_image(item["image"], to_rgb=True)

            for angle in self.rotation:
                current_image, rotmat = self.rotate_image(detect_image, angle)
                faces, points = detect_face(current_image, **self.kwargs)
                if angle != 0 and faces.any():
                    logger.verbose("found face(s) by rotating image %s degrees", angle)
                if faces.any():
                    break

            detected_faces = self.process_output(faces, points, rotmat, scale)
            item["detected_faces"] = detected_faces
            self.finalize(item)

        logger.debug("Thread Completed Detect")

    def process_output(self, faces, points, rotation_matrix, scale):
        """ Compile found faces for output """
        logger.trace("Processing Output: (faces: %s, points: %s, rotation_matrix: %s)",
                     faces, points, rotation_matrix)
        faces = self.recalculate_bounding_box(faces, points)
        faces = [self.to_bounding_box_dict(face[0], face[1], face[2], face[3]) for face in faces]
        if isinstance(rotation_matrix, np.ndarray):
            faces = [self.rotate_rect(face, rotation_matrix)
                     for face in faces]
        detected = [self.to_bounding_box_dict(face["left"] / scale, face["top"] / scale,
                                              face["right"] / scale, face["bottom"] / scale)
                    for face in faces]
        logger.trace("Processed Output: %s", detected)
        return detected
 </s> add     def init_model(self):
        """ Initialize S3FD Model"""
        self.model = MTCNN(self.model_path, **self.kwargs)
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
                           colorspace="RGB",
                           input_size=128,
                           **kwargs)
          self.vram = 0  # Doesn't use GPU
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
        self.batchsize = 1

    def init_model(self):
        """ Initialize CV2 DNN Detector Model"""
        self.model = cv2.dnn.readNetFromTensorflow(self.model_path)  # pylint: disable=no-member
        self.model.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # pylint: disable=no-member

    def process_input(self, batch):
        """ Compile the detected faces for prediction """
        faces, batch["roi"] = self.align_image(batch["detected_faces"])
        faces = self._normalize_faces(faces)
        batch["feed"] = np.array(faces, dtype="float32").transpose((0, 3, 1, 2))
        return batch

    def align_image(self, detected_faces):
          """ Align the incoming image for prediction """
          logger.trace("Aligning image around center")
  
          box = (detected_face["left"],
                 detected_face["top"],
keep keep keep keep 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/align/cv2_dnn.py