Malla Facial (MediaPipe Face Mesh) ? | Python – MediaPipe – OpenCV

Por Administrador

Ya hemos explorado dos de las soluciones que nos ofrece MediaPipe, la primera fue MediaPipe Hands para la detección de manos y dedos. Luego MediaPipe FaceDetection, para la detección de rostros o caras que a su vez se aplica en la solución que veremos hoy. En este tutorial, vamos a hablar de MediaPipe Face Mesh. 

CONTENIDO:

  • MediaPipe Face Mesh
    • Modelos empleados en MediaPipe Face Mesh
      • Face detection model
      • Face landmark model
    • Opciones de configuración
    • Datos de salida que obtenemos al usar MediaPipe Face Mesh
    • ¡Vamos con la programación!
      • Malla Facial con MediaPipe en imágenes
      • Malla Facial con MediaPipe en videos
    • Referencias

MediaPipe Face Mesh

Figura 1: Ejemplo del uso de MediaPipe face mesh, o malla facial.

Según su documentación, esta es una solución de geometría de caras, que nos permite obtener 468 puntos claves 3D, en tiempo real que incluso puede ser aplicada en dispositivos móviles. 

Figura 2: Imagen donde puedes encontrar la disposición de los 468 puntos. (Fuente)

Esta solución emplea machine learning, y usa tan solo una cámara para obtener los puntos 3D de la superficie geométrica, por lo que no es necesario un sensor de profundidad. 

Figura 3: Visualización de cada uno de los puntos distribuidos en el rostro detectado.

Modelos empleados en MediaPipe Face Mesh

Esta solución emplea dos modelos de redes neuronales profundas que trabajan juntas y en tiempo real. Así que vamos a hablar un poco de cada uno de ellos:

FACE DETECTION MODEL 

Figura 4: Ilustración del proceso de detección de rotros con MediaPipe.

Este modelo es el mismo usado por MediaPipe Face Detection, del anterior videotutorial. Este detector de rostros opera sobre toda la imagen para obtener el o los lugares en donde están presentes los rostros.

Una vez que se tiene ubicada esta región de la imagen, se procede al empleo del siguiente modelo.

FACE LANDMARK MODEL 

Figura 5: Ilustración de la obtención de los 468 puntos claves con MediaPipe.

Este modelo opera sobre las ubicaciones de los rostros detectados y genera las posiciones de los puntos 3D. 

Cabe destacar que face mesh, sigue un proceso similar al de mediapipe hands, es decir que los landmarks (puntos claves o puntos de referencia) se van obteniendo basándose en el fotograma anterior, es decir mediante el tracking o seguimiento de ellos. Y se invoca nuevamente al detector de rostros, es decir al anterior modelo, únicamente cuando no se haya podido identificar la presencia de la cara. 

Hemos visto un pequeño resumen del proceso que emplea mediapipe face mesh para la detección de los rostros y de los 468 puntos de referencia, para una explicación más extendida puedes dirigirte a la documentación de mediapipe face mesh. 

OPCIONES DE CONFIGURACION 

STATIC_IMAGE_MODE (Por defecto false) 

Puede tomar valores de True o False. Si especificamos este como False, entonces la solución trata a las imágenes de entrada como un videostream, por lo que intentará detectar el o los rostros en las primeras imágenes de entrada, y cuando se haya realizado una detección exitosa, se localizarán los puntos de referencia. En las imágenes siguientes una vez que se hayan obtenido los puntos de referencia o puntos clave, estos serán rastreados para conseguir la nueva ubicación de los rostros, y solo se invocará nuevamente al detector de rostros una vez que ya no se haya podido identificar la presencia de una cara. Debido a que no se tiene que aplicar una y otra vez el detector de rostros, y simplemente se da seguimiento a los puntos de referencia, se puede reducir la latencia, por lo que es ideal para usarla en videos. 

Por otro lado si especificamos STATIC_IMAGE_MODE como True, se aplica el detector de rostros en cada una de las imágenes de entrada, por lo que es mejor usar esta cuando tenemos imágenes que no se relacionan entre sí. 

NUM_MAX_FACES (Por defecto 1) 

Número máximo de rostro a detectar 

MIN_DETECTION_CONFIDENCE (Por defecto 0.5) 

Valor mínimo de confianza del modelo de detección facial, para que la detección sea considerada como exitosa. 

MIN_TRACKING_CONFIDENCE (Por defecto 0.5) 

Valor mínimo de confianza del modelo de seguimiento de puntos de referencia (landmark-trancking), para que estos se consideren como seguidos correctamente. De lo contrario se invoca a la detección de rostros en la siguiente imagen.  

Este es ignorado si STATIC_IMAGE_MODE lo especificamos como True, ya que en ese caso el detector de rostros será aplicado en todas las imágenes.  

Datos de salida que obtenemos al usar MediaPipe Face Mesh

MULTI_FACE_LANDMARKS 

Colección de rostros detectados o seguidos, donde cada rostro es representado como una lista de 468 puntos clave y cada punto está compuesto de x, y e z. 

¡Vamos con la programación!

Para una explicación más detallada de los programas que veremos a continuación, por favor dirígete al videotutorial de mi canal.

Malla facial con MediaPipe en imágenes

import cv2
import mediapipe as mp

mp_face_mesh = mp.solutions.face_mesh
mp_drawing = mp.solutions.drawing_utils

index_list = [70, 63, 105, 66, 107, 336, 296, 334, 293, 300,
                122, 196, 3, 51, 281, 248, 419, 351, 37, 0, 267]

with mp_face_mesh.FaceMesh(
    static_image_mode=True,
    max_num_faces=3,
    min_detection_confidence=0.5) as face_mesh:

    image = cv2.imread("imagen_0001.jpg")
    height, width, _ = image.shape
    image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    results = face_mesh.process(image_rgb)

    print("Face landmarks: ", results.multi_face_landmarks)
    
    if results.multi_face_landmarks is not None:
        for face_landmarks in results.multi_face_landmarks:
            for index in index_list:
                x = int(face_landmarks.landmark[index].x * width)
                y = int(face_landmarks.landmark[index].y * height)
                cv2.circle(image, (x, y), 2, (255, 0, 255), 2)
            cv2.imshow("Image", image)
            cv2.waitKey(0)
    '''
    if results.multi_face_landmarks is not None:
            for face_landmarks in results.multi_face_landmarks:
                mp_drawing.draw_landmarks(image, face_landmarks,
                    mp_face_mesh.FACE_CONNECTIONS,
                    mp_drawing.DrawingSpec(color=(0, 255, 255), thickness=-1, circle_radius=1),
                    mp_drawing.DrawingSpec(color=(255, 0, 255), thickness=1))
    '''
    cv2.imshow("Image", image)
    cv2.waitKey(0)
cv2.destroyAllWindows()

Malla facial con MediaPipe en videos

import cv2
import mediapipe as mp

mp_face_mesh = mp.solutions.face_mesh
mp_drawing = mp.solutions.drawing_utils

cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)

with mp_face_mesh.FaceMesh(
    static_image_mode=False,
    max_num_faces=1,
    min_detection_confidence=0.5) as face_mesh:

    while True:
        ret, frame = cap.read()
        if ret == False:
            break
        frame = cv2.flip(frame,1)
        frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        results = face_mesh.process(frame_rgb)

        if results.multi_face_landmarks is not None:
            for face_landmarks in results.multi_face_landmarks:
                mp_drawing.draw_landmarks(frame, face_landmarks,
                    mp_face_mesh.FACE_CONNECTIONS,
                    mp_drawing.DrawingSpec(color=(0, 255, 255), thickness=1, circle_radius=1),
                    mp_drawing.DrawingSpec(color=(255, 0, 255), thickness=1))

        cv2.imshow("Frame", frame)
        k = cv2.waitKey(1) & 0xFF
        if k == 27:
            break

cap.release()
cv2.destroyAllWindows()

Referencias