使用Python进行脸部几何检测
我们将利用MediaPipe的Face Mesh模型来检测脸部的地标,并对其进行一些造型处理。
前提条件
- 要跟上这个教程,你需要有Jupyter Notebook或Google Colab。
本项目使用了Google Colab。
脸部网格模型
MediaPipe是一个强大的开源框架,由谷歌开发。
它被用于建立跨平台的多模式应用ML管道。这个框架中的一个模型是脸部网格模型。
这个模型提供脸部几何解决方案,能够检测人脸上的468个三维地标。
Face Mesh模型使用机器学习来推断人脸的三维表面几何形状。利用面部表面几何形状有助于在AR应用中应用面部效果。
有没有想过为什么你能在Snapchat上戴上假的太阳镜/帽子?正是这样的模型实现了这种基于脸部的AR效果。
建立脸部网格模型
安装并导入所需的依赖项
!pip install opencv-python mediapipe
我们已经导入了OpenCV和MediaPipe库。
OpenCV帮助我们访问我们的图像,而MediaPipe允许我们在笔记本中导入和使用Face Mesh模型。安装完这两个库后,我们需要把它们导入我们的笔记本。
import cv2 #default OpenCV import code
import mediapipe as mp #default mediapipe import code
让我们来设置MediaPipe。
Mediapipe是一个巨大的库,有很多功能。我们只需要选择我们需要的那些。
我们需要导入绘图工具,以帮助绘制面部的所有468个地标。我们还需要导入造型工具,以帮助我们在脸上添加样式。
最后,我们将把主要的脸部网格模型导入我们的笔记本。
mp_drawing = mp.solutions.drawing_utils #helps draw all the 468 landmarks
mp_drawing_styles = mp.solutions.drawing_styles #helps us add styles onto the face
mp_face_mesh = mp.solutions.face_mesh #main model import
加载图像
from google.colab.patches import cv2_imshow
image = cv2.imread("image.png")
cv2_imshow(image)
cv2.waitKey(0)
输出。

在图像上绘制脸部网格的注释
drawing_spec = mp_drawing.DrawingSpec(thickness=2, circle_radius=2)
你可以把厚度和圆圈半径调整到你想要的任何数值。
with mp_face_mesh.FaceMesh(static_image_mode=True, max_num_faces=3, refine_landmarks=True, min_detection_confidence=0.99) as face_mesh:
image = cv2.imread("avatar.png")
默认情况下,要检测的最大面数被设置为只检测一个面。如果要在图像或视频中检测到一个以上的人脸,你需要将max_num_faces 参数改为你需要的数量。我们将我们的参数设置为三个。
为了使检测被认为是成功的,min_detection_confidence 是用来表示所需的信心值。允许的范围是在([0.0, 1.0])之间。
默认情况下,这个值被设置为0.5。任何低于0.99的检测值将不被视为成功。如果高于0.99,将被检测并应用于图像。
接下来,我们需要将图像颜色格式从BGR转换为RGB。这个过程应该在图像处理开始之前完成。这是因为OpenCV默认接受的图像格式是BGR 。但是MediaPipe只适用于RGB 图像。
因此,使用cv2.cvtColor() 函数,我们将图像转换为RGB格式。
results = face_mesh.process(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
现在让我们在图像上打印和绘制脸部网格的地标。
annotated_image = image.copy()
for face_landmarks in results.multi_face_landmarks:
print('facial_landmarks:', face_landmarks)
mp_drawing.draw_landmarks(
image=annotated_image,
landmark_list=face_landmarks,
connections=mp_face_mesh.FACEMESH_TESSELATION,
landmark_drawing_spec=None,
connection_drawing_spec=mp_drawing_styles
下面的代码将脸部网格的镶嵌样式应用到图像上。
.get_default_face_mesh_tesselation_style())
mp_drawing.draw_landmarks(image=annotated_image, landmark_list=face_landmarks, connections=mp_face_mesh.FACEMESH_CONTOURS,
landmark_drawing_spec=None,
connection_drawing_spec=mp_drawing_styles
在下面的代码中,脸部网格的轮廓样式被应用到图像上。
.get_default_face_mesh_contours_style())
mp_drawing.draw_landmarks(image=annotated_image,
landmark_list=face_landmarks,
connections=mp_face_mesh.FACEMESH_IRISES,
landmark_drawing_spec=None,
connection_drawing_spec=mp_drawing_styles
.get_default_face_mesh_iris_connections_style())
cv2.imwrite('/tmp/annotated_image' + '.png', annotated_image)
输出。
face_landmarks: landmark {
x: 0.5070745348930359
y: 0.5069379806518555
z: -0.03871098905801773
}
landmark {
x: 0.4806444048881531
y: 0.46297627687454224
z: -0.06519311666488647
}
landmark {
x: 0.4889220893383026
y: 0.477283775806427
z: -0.03737092390656471
}
.
.
.
.
.
从这些结果中,我们可以看到,每个地标包括三个轴:x ,y ,和z 坐标。
请记住,该模型在脸部几何形状上检测了468个三维地标。这些坐标被归一化为0.0和1.0之间的值。地标的深度由坐标z 来表示。
深度的原点由深度的原点表示。此外,最小的z 值表示地标离摄像机有多近。
最后,我们使用OpenCV的imshow() 方法来查看这些地标在图像上的显示情况。
cv2_imshow(annotated_image)
输出。

只用了几行代码,我们就成功地在图像上画出了人脸网格注释。
本教程中的人脸几何检测是在静态图像上进行的,你可以把这个项目提高一个档次,尝试在网络摄像头视频输出上进行实验。
总结
Face Mesh模型在基于人脸的实时增强现实(AR)效果中至关重要。例如,一旦模型在脸上画出了地标,你就可以在一个人的眼睛上叠加太阳镜,或者让这个人戴上一些鼻环,等等。使用案例是无限的。