利用机器学习进行人脸468点的3D坐标检测,并生成3D模型

上期文章,我们分享了,MediaPipe Face Mesh是一种脸部几何解决方案,即使在移动设备上,也可以实时估计468个3D脸部界标(dlib才能检测出68点)。它采用机器学习(ML)来推断3D表面几何形状,只需要单个摄像机输入,而无需专用的深度传感器。该解决方案利用轻量级的模型架构以及整个管线中的GPU加速,可提供对实时体验至关重要的实时性能。本期我们介绍一下代码如何实现

MediaPipe Face Mesh

import cv2
import mediapipe as mp
mp_drawing = mp.solutions.drawing_utils
mp_face_mesh = mp.solutions.face_mesh

# 静态图片
face_mesh = mp_face_mesh.FaceMesh(
static_image_mode=True,
max_num_faces=1,
min_detection_confidence=0.5)

drawing_spec = mp_drawing.DrawingSpec(thickness=2, circle_radius=1)
drawing_spec1 = mp_drawing.DrawingSpec(thickness=2, circle_radius=1,color=(255,255,255))

代码截图

首先导入需要的第三方库,mediapipe的安装,直接在cmd命令框中输入

python –m pip install mediapipe 安装即可

然后我们定义了一个绘图方法,此方法定义了我们需要画图的线的粗细,颜色等信息,还记得我们前期分享holistic检测时,哪里由于没有配置线的粗细,导致我们的人脸识别的468个点密密麻麻的铺满了整个人脸,这里便可以修改一下

我们使用
mp.solutions.drawing_utils下的DrawingSpec方法来定义线的粗细,颜色信息等,此方法接受三个参数,分别是color,thickness,circle_radius,我们可以利用此方法定义我们连接线的粗细已经颜色,定义468点的圆心大小,颜色等

代码截图

然后使用mp_face_mesh.FaceMesh方法定义一个人脸检测器与人脸mesh器,此方法接受4个参数

代码截图

STATIC_IMAGE_MODE

如果设置为false,则解决方案会将输入图像视为视频流。它将尝试检测第一个输入图像中的人脸,并在成功检测后进一步定位人脸地标。在随后的图像中,一旦检测到所有面孔并定位了相应的面孔地标,它便会简单地跟踪这些地标,而无需调用另一次检测,直到失去对任何面孔的跟踪为止。这减少了等待时间,是处理视频帧的理想选择。如果设置为true,则脸部检测在每个输入图像上运行,非常适合处理一批静态的,可能不相关的图像。默认为false。

MAX_NUM_FACES

要检测的最大脸数。默认为1。这里也解释了为什么我们分享holistic时 ,检测多人时,只检测了一个人脸,这里需要设置一下

MIN_DETECTION_CONFIDENCE

[0.0, 1.0]来自人脸检测模型的最小置信度值()被认为是成功检测。默认为0.5。

MIN_TRACKING_CONFIDENCE

[0.0, 1.0]来自地标跟踪模型的最小置信度值()将被视为已成功跟踪的人脸地标,否则将在下一个输入图像上自动调用人脸检测。将其设置为较高的值可以提高解决方案的健壮性,但代价是要增加延迟。如果为true,则忽略该,其中人脸检测仅在每个图像上运行。默认为0.5。

最后函数返回一个MULTI_FACE_LANDMARKS参数

检测/跟踪的面,其中,每个面被表示为468米的地标列表以及每个界标由收集x,y和z。x和y分别[0.0, 1.0]通过图像的宽度和高度进行归一化。z代表地标深度,以头部中央的深度为原点,值越小,地标越靠近相机。的z使用量级与大致相同x。

image = cv2.imread('2.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
results = face_mesh.process(image)
annotated_image = image.copy()

代码截图

随后,我们打开一张需要检测的图片,并把图片转换到RGB空间,然后使用process方法对图片进行检测,此方法返回所有的人脸468个点的坐标,有了这468个点的坐标,我们便可以遍历所有点,然后进行人脸mesh的绘制

for face_landmarks in results.multi_face_landmarks:
  print('face_landmarks:', face_landmarks)
  mp_drawing.draw_landmarks(
    image=annotated_image,
    landmark_list=face_landmarks,
    connections=mp_face_mesh.FACE_CONNECTIONS,
    landmark_drawing_spec=drawing_spec,
    connection_drawing_spec=drawing_spec1)
cv2.imshow('annotated_image',annotated_image)
cv2.waitKey(0)
cv2.imwrite('111.png', annotated_image)
face_mesh.close()

代码截图

我们使用for循环遍历所有的468个点,然后使用draw_landmarks方法画图,此方法接受5个参数

  • 1、 image,需要画图的原始图片
  • 2、 landmark_list 检测到的人脸坐标
  • 3、 connections,连接线,需要把那些坐标连接起来
  • 4、 landmark_drawing_spec,坐标的颜色,粗细
  • 5、 connection_drawing_spec连接线的粗细,颜色等

代码截图

遍历完成后,便可以生成人脸的mesh网络了

Mesh人脸468点网络的视频实现

import cv2
import mediapipe as mp
mp_drawing = mp.solutions.drawing_utils
mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(
min_detection_confidence=0.5, min_tracking_confidence=0.5)
drawing_spec = mp_drawing.DrawingSpec(thickness=2, circle_radius=1)
drawing_spec1 = mp_drawing.DrawingSpec(thickness=2, circle_radius=1,color=(255,255,255))
cap = cv2.VideoCapture(0)

代码截图

对于实时视频,代码跟图片检测几乎一致,这里我们需要设置STATIC_IMAGE_MODE检测模型为视频,而不是图片,然后打开我们电脑的默认摄像头,进行视频帧的抓取

 while cap.isOpened():
  success, image = cap.read()
  if not success:
    print("Ignoring empty camera frame.")
    continue
  image = cv2.cvtColor(cv2.flip(image, 1), cv2.COLOR_BGR2RGB)
  image.flags.writeable = False
  results = face_mesh.process(image)
  image.flags.writeable = True
  image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
  if results.multi_face_landmarks:
    for face_landmarks in results.multi_face_landmarks:
      mp_drawing.draw_landmarks(
      image=image,
      landmark_list=face_landmarks,
      connections=mp_face_mesh.FACE_CONNECTIONS,
      landmark_drawing_spec=drawing_spec,
      connection_drawing_spec=drawing_spec1)
  cv2.imshow('MediaPipe FaceMesh', image)
  if cv2.waitKey(5) & 0xFF == ord('q'):
    break
face_mesh.close()
cap.release()

代码截图

待视频帧的图片抓取后,就可以使用图片识别的方法进行图片的检测,并实时把检测结果显示在视频里面了

https://m.toutiao.com/is/iLjn9d26/ 人工智能研究所: 视频动画详解Transformer模型–Attention is all you need.