def detect_faces(self, image, conf_threshold: float = 0.7) -> List[List[int]]:
        """Performs facial detection on an image. Uses MTCNN.
        Args:
            image (numpy array):
            conf_threshold (float, optional): Threshold confidence to consider
        Raises:
            InvalidImage: When the image is either None or
            with wrong number of channels.

        Returns:
            List[List[int]]: List of bounding box coordinates
        """
        if not is_valid_img(image):
            raise InvalidImage

        # Do a forward propagation with the blob created from input img
        detections = self.face_detector.detect_faces(image)
        # Bounding box coordinates of faces in image
        bboxes = []
        for _, detection in enumerate(detections):
            conf = detection["confidence"]
            if conf >= conf_threshold:
                x, y, w, h = detection["box"]
                x1, y1, x2, y2 = x, y, x + w, y + h
                # Trim forehead area to match dlib style facial ROI
                if self.crop_forehead:
                    y1 = y1 + int(h * self.shrink_ratio)
                bboxes.append([x1, y1, x2, y2])

        return bboxes
Example #2
0
    def register_face(self,
                      image=None,
                      name: str = None,
                      bbox: List[int] = None):
        """Method to register a face via the facial encoding.
        Siamese neural network is used to generate 128 numbers
        for a given facial region. These encodings can be used to identify a
        facial ROI for identification later.

        Args:
            image (numpy array, optional): Defaults to None.
            name (str, optional): Name to associate with the face. Defaults to None.
            bbox (List[int], optional): Facial ROI bounding box. Defaults to None.

        Raises:
            NoNameProvided:
            NoFaceDetected:

        Returns:
            Dict: Facial encodings along with an unique identifier and name
        """

        if not is_valid_img(image) or name is None:
            raise NoNameProvided if name is None else InvalidImage

        image = image.copy()
        face_encoding = None

        try:
            if bbox is None:
                bboxes = self.face_detector.detect_faces(image=image)
                if len(bboxes) == 0:
                    raise NoFaceDetected
                bbox = bboxes[0]
            face_encoding = self.get_facial_fingerprint(image, bbox)

            # Convert the numpy array to normal python float list
            # to make json serialization simpler
            facial_data = {
                "id": str(uuid.uuid4()),
                "encoding": tuple(face_encoding.tolist()),
                "name": name,
            }
            # save the encoding with the name
            self.save_facial_data(facial_data)
            logger.info("Face registered with name: {}".format(name))
        except Exception as exc:
            raise exc
        return facial_data
Example #3
0
def convert_to_rgb(image):
    """Converts an image to RGB format.

    Args:
        image (numpy array): [description]

    Raises:
        InvalidImage: [description]

    Returns:
        [type]: [description]
    """
    if not is_valid_img(image):
        raise InvalidImage
    return cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    def detect_faces(self,
                     image,
                     conf_threshold: float = 0.7) -> List[List[int]]:
        """Performs facial detection on an image. Uses OpenCV DNN based face detector.
        Args:
            image (numpy array):
            conf_threshold (float, optional): Threshold confidence to consider
        Raises:
            InvalidImage: When the image is either None or
            with wrong number of channels.

        Returns:
            List[List[int]]: List of bounding box coordinates
        """
        if not is_valid_img(image):
            raise InvalidImage
        # To prevent modification of orig img
        image = image.copy()
        height, width = image.shape[:2]

        # Do a forward propagation with the blob created from input img
        detections = self.model_inference(image)
        # Bounding box coordinates of faces in image
        bboxes = []
        for idx in range(detections.shape[2]):
            conf = detections[0, 0, idx, 2]
            if conf >= conf_threshold:
                # Scale the bbox coordinates to suit image
                x1 = int(detections[0, 0, idx, 3] * width)
                y1 = int(detections[0, 0, idx, 4] * height)
                x2 = int(detections[0, 0, idx, 5] * width)
                y2 = int(detections[0, 0, idx, 6] * height)

                if self.crop_forehead:
                    y1 = y1 + int(height * self.shrink_ratio)
                # openCv detector can give a lot of false bboxes
                # when the image is a zoomed in face / cropped face
                # This will get rid of atleast few, still there can be other
                # wrong detections present!
                if self.is_valid_bbox([x1, y1, x2, y2], height, width):
                    bboxes.append([x1, y1, x2, y2])

        return bboxes
    def detect_faces(self, image, num_upscaling: int = 1) -> List[List[int]]:
        """Performs facial detection on an image. Works best with
        RGB image. Uses a dlib based detector either HOG or MMOD.

        Args:
            image (numpy array):
            num_upscaling (int, optional): Number of times to upscale
            while detecting faces. Defaults to 1.

        Raises:
            InvalidImage: When the image is either None or
            with wrong number of channels.

        Returns:
            List[List[int]]: List of bounding box coordinates
        """
        if not is_valid_img(image):
            raise InvalidImage
        return [
            self.dlib_rectangle_to_list(bbox)
            for bbox in self.face_detector(image, num_upscaling)
        ]