SPPAS 4.22

https://sppas.org/

Module sppas.src.annotations

Class ImageFaceLandmark

Description

Estimate the 68 sights on one face of an image with several detectors.

Constructor

Create a new ImageFaceLandmark instance.

View Source
def __init__(self):
    """Create a new ImageFaceLandmark instance.

    """
    super(ImageFaceLandmark, self).__init__()
    self.__basic = None
    self.__mediapipe = MediaPipeFaceMesh()
    self.__markers = list()

Public functions

get_nb_recognizers

Return the number of initialized landmark recognizers.

View Source
def get_nb_recognizers(self) -> int:
    """Return the number of initialized landmark recognizers."""
    nb = 2
    if self.__basic is None:
        nb = 1
    return nb + len(self.__markers)

add_model

Append an OpenCV recognizer into the list and load the model.

Parameters
  • filename: (str) A recognizer model (Kazemi, LBF, AAM).
Raises

IOError, IOExtensionError, Exception

View Source
def add_model(self, filename: str) -> None:
    """Append an OpenCV recognizer into the list and load the model.

        :param filename: (str) A recognizer model (Kazemi, LBF, AAM).
        :raise: IOError, IOExtensionError, Exception

        """
    predictor = OpenCVFaceMark(filename)
    self.__markers.append(predictor)

enable_empirical_predictor

Enable the basic predictor with empirically fixed sights.

Parameters
  • value: (bool) True to enable
View Source
def enable_empirical_predictor(self, value: str=True) -> None:
    """Enable the basic predictor with empirically fixed sights.

        :param value: (bool) True to enable

        """
    if bool(value) is True:
        self.__basic = BasicFaceMark()
    else:
        self.__basic = None

Private functions

_detect

Detect sights on an image with the coords of the face.

Parameters
  • image: (sppasImage or numpy.ndarray) The image to be processed.
  • coords: (sppasCoords) Coordinates of the face in the image or None for the full image
View Source
def _detect(self, image, coords=None):
    """Detect sights on an image with the coords of the face.

        :param image: (sppasImage or numpy.ndarray) The image to be processed.
        :param coords: (sppasCoords) Coordinates of the face in the image or None for the full image

        """
    success, all_points = self.__detect_with_markers(image, coords)
    if success is True:
        for i in range(len(self._sights)):
            x, y, score = self.__points_to_coords(image, coords, all_points[i])
            self._sights.set_sight(i, x, y, None, score)
    return success

Protected functions

__points_to_coords

Convert a list of estimated points into coordinates of a sight.

The confidence score of each sight depends on the area covered by the points. The image and the coords are used only to estimate the score.

Parameters
  • image: (numpy.ndarray) The image.
  • coords: (sppasCoords) Coordinates of the face in the image.
  • points: (list of (x,y) values) A sight detected by each method
Returns
  • Estimated(x,y,c) values
View Source
def __points_to_coords(self, image, coords, points):
    """Convert a list of estimated points into coordinates of a sight.

        The confidence score of each sight depends on the area covered by the
        points. The image and the coords are used only to estimate the score.

        :param image: (numpy.ndarray) The image.
        :param coords: (sppasCoords) Coordinates of the face in the image.
        :param points: (list of (x,y) values) A sight detected by each method
        :return: Estimated (x,y,c) values

        """
    if coords is not None:
        img = image.icrop(coords)
    else:
        img = image.copy()
    h, w = img.shape[:2]
    face_area = h * w
    min_x = min((result[0] for result in points))
    min_y = min((result[1] for result in points))
    max_x = max((result[0] for result in points))
    max_y = max((result[1] for result in points))
    points_area = (max_x - min_x) * (max_y - min_y)
    if face_area > 0.0:
        ratio = float(points_area) / float(face_area)
    else:
        ratio = 1.0
    coeff = max(1.0, min(5.0, 100.0 * ratio))
    score = min(1.0, max(0.0, 1.0 - coeff * ratio))
    avg_points = [p for p in points]
    for i in range(4):
        avg_points.append(points[0])
    sum_x = sum((result[0] for result in avg_points))
    sum_y = sum((result[1] for result in avg_points))
    x = round(float(sum_x) / float(len(avg_points)))
    y = round(float(sum_y) / float(len(avg_points)))
    return (x, y, score)

__detect_with_markers

Estimate all the 68 points by each instantiated face-marker.

The returned result is a list of 68 lists of tuples with (x,y) values because it's the data structure OpenCV is returning when invoking the method 'fit()' of each recognizer.

Parameters
  • image
  • coords
View Source
def __detect_with_markers(self, image, coords):
    """Estimate all the 68 points by each instantiated face-marker.

        The returned result is a list of 68 lists of tuples with (x,y) values
        because it's the data structure OpenCV is returning when invoking
        the method 'fit()' of each recognizer.

        """
    all_points = {i: list() for i in range(len(self._sights))}
    if coords is not None:
        c = coords.portrait()
    else:
        w, h = image.get_size()
        c = sppasCoords(0, 0, w, h)
    success = self.__mediapipe.detect_sights(image.icrop(c))
    if success is True:
        for i, sight in enumerate(self.__mediapipe):
            x, y, z, s = sight
            all_points[i].append((x + c.x, y + c.y))
    for cv_marker in self.__markers:
        s = cv_marker.detect_sights(image, coords)
        if s is True:
            success = True
            for i, sight in enumerate(cv_marker):
                x, y, z, s = sight
                all_points[i].append((x, y))
    if self.__basic is not None:
        self.__basic.detect_sights(image, coords)
        for i, sight in enumerate(self.__basic):
            x, y, z, s = sight
            all_points[i].append((x, y))
    return (success, all_points)