          "gui_radio": False,
          "fixed": True,
      }
  }
 
</s> remove     }
 </s> add     }, </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         Pass in a DetectedFace object, Alignments dict or bounding box dict
        (as defined in lib/plugins/extract/detect/_base.py) """
 </s> add         Pass in a DetectedFace object or Alignments dict """
    },
    "batch-size": {
        "default": 8,
        "info": "The batch size to use. To a point, higher batch sizes equal better performance, "
                "but setting it too high can harm performance.\n"
                "\n\tNvidia users: If the batchsize is set higher than the your GPU can "
                "accomodate then this will automatically be lowered."
                "\n\tAMD users: A batchsize of 8 requires about 2 GB vram.",
        "datatype": int,
        "rounding": 1,
        "min_max": (1, 64),
        "choices": [],
        "gui_radio": False,
        "fixed": True,
          "gui_radio": False,
          "fixed": True,
    },
    "batch-size": {
        "default": 8,
        "info": "The batch size to use. To a point, higher batch sizes equal better performance, "
                "but setting it too high can harm performance.\n"
                "\n\tNvidia users: If the batchsize is set higher than the your GPU can "
                "accomodate then this will automatically be lowered."
                "\n\tAMD users: A batchsize of 8 requires about 2 GB vram.",
        "datatype": int,
        "rounding": 1,
        "min_max": (1, 64),
        "choices": [],
        "gui_radio": False,
        "fixed": True,
      }
  }
keep add 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/detect/s3fd_defaults.py