Mediapipe 人脸特征点侦测 ( 新 )
MediaPipe 的 Face Landmark Detection 可以在检测人脸的特征点,并将特征点应用于识别表情、脸部滤镜特效,以及建立虚拟头像等等,这篇教学会介绍如何使用 Mediapipe 人脸特征点侦测。
快速导览:
因为程序使用 Jupyter 搭配 Tensorflow 进行开发,所以请先阅读“使用 Anaconda”和“使用 MediaPipe”,安装对应的软件包,如果不要使用 Juputer,也可参考“使用 Python 虚拟环境”,建立虚拟环境进行实作。
人脸特征点是什么?
MediaPipe 人脸特征点侦测 ( Face Landmark Detection ) 使用机器学习模型,识别单张图像或连续图像的面部表情,并输出三维的人脸特征点,并将这些特征点应用于识别表情、脸部滤镜特效,以及建立虚拟头像等等,此外,MediaPipe 还提供了不同的设定选项,方便开发者设置运行模式、检测的脸部数量、面部的最小信心分数等。
Face Landmark Detection 提供三种模型来侦测:。
- Face detection model ( 人脸侦测模型 ):侦测是否有人脸。
- Face mesh model ( 脸部网格模型 ):判断人脸的表面和深度,透过 478 个脸部标记 ( 面部姿态变换矩阵、三角形面部网格...等 ) 画出 3D 的人脸网格。
- Blendshape prediction model ( Blendshape 预测模型 ):接收脸部网格模型的输出,预测 52 个 blendshape 分数,透过分数表现不同的脸部表情 ( 目前好像没有提供模型和用法 )。
绘制人脸网格
在开发的文件夹里新增一个 Python 文件和一个名为 model 的文件夹,下载侦测模型 face_landmarker.task 放在 model 的文件夹中,输入下方的程序码,执行后就可以透过摄影机拍摄人脸,并会即时标记出人脸网格。
- 下载模型:face_landmarker.task
import cv2
import numpy as np
import mediapipe as mp
from mediapipe import solutions
from mediapipe.framework.formats import landmark_pb2
# 設定方法
BaseOptions = mp.tasks.BaseOptions
FaceLandmarker = mp.tasks.vision.FaceLandmarker
FaceLandmarkerOptions = mp.tasks.vision.FaceLandmarkerOptions
VisionRunningMode = mp.tasks.vision.RunningMode
# 人臉偵測設定
options = FaceLandmarkerOptions(
base_options=BaseOptions(model_asset_path='model/face_landmarker.task'),
running_mode=VisionRunningMode.IMAGE)
# 執行人臉偵測
with FaceLandmarker.create_from_options(options) as landmarker:
cap = cv2.VideoCapture(0) # 讀取攝影鏡頭
while True:
ret, frame = cap.read() # 讀取影片的每一幀
w = frame.shape[1] # 畫面寬度
h = frame.shape[0] # 畫面高度
mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=frame)
face_landmarker_result = landmarker.detect(mp_image)
face_landmarks_list = face_landmarker_result.face_landmarks
annotated_image = np.copy(frame)
# Loop through the detected faces to visualize.
for idx in range(len(face_landmarks_list)):
face_landmarks = face_landmarks_list[idx]
# Draw the face landmarks.
face_landmarks_proto = landmark_pb2.NormalizedLandmarkList()
face_landmarks_proto.landmark.extend([
landmark_pb2.NormalizedLandmark(x=landmark.x, y=landmark.y, z=landmark.z) for landmark in face_landmarks
])
solutions.drawing_utils.draw_landmarks(
image=annotated_image,
landmark_list=face_landmarks_proto,
connections=mp.solutions.face_mesh.FACEMESH_TESSELATION,
landmark_drawing_spec=None,
connection_drawing_spec=mp.solutions.drawing_styles
.get_default_face_mesh_tesselation_style())
solutions.drawing_utils.draw_landmarks(
image=annotated_image,
landmark_list=face_landmarks_proto,
connections=mp.solutions.face_mesh.FACEMESH_CONTOURS,
landmark_drawing_spec=None,
connection_drawing_spec=mp.solutions.drawing_styles
.get_default_face_mesh_contours_style())
solutions.drawing_utils.draw_landmarks(
image=annotated_image,
landmark_list=face_landmarks_proto,
connections=mp.solutions.face_mesh.FACEMESH_IRISES,
landmark_drawing_spec=None,
connection_drawing_spec=mp.solutions.drawing_styles
.get_default_face_mesh_iris_connections_style())
#print(face_landmarker_result)
if not ret:
print("Cannot receive frame") # 如果讀取錯誤,印出訊息
break
cv2.imshow('oxxostudio', annotated_image) # 如果讀取成功,顯示該幀的畫面
if cv2.waitKey(10) == ord('q'): # 每一毫秒更新一次,直到按下 q 結束
break
cap.release() # 所有作業都完成後,釋放資源
cv2.destroyAllWindows() # 結束所有視窗
绘制只有网格的人脸
如果将原本摄影的画面隐藏,就可以将产生的 3D 人脸网格套用在其他图片里,形成有趣的图像
import cv2
import numpy as np
import mediapipe as mp
from mediapipe import solutions
from mediapipe.framework.formats import landmark_pb2
# 設定方法
BaseOptions = mp.tasks.BaseOptions
FaceLandmarker = mp.tasks.vision.FaceLandmarker
FaceLandmarkerOptions = mp.tasks.vision.FaceLandmarkerOptions
VisionRunningMode = mp.tasks.vision.RunningMode
# 人臉偵測設定
options = FaceLandmarkerOptions(
base_options=BaseOptions(model_asset_path='model/face_landmarker.task'),
running_mode=VisionRunningMode.IMAGE)
# 執行人臉偵測
with FaceLandmarker.create_from_options(options) as landmarker:
cap = cv2.VideoCapture(0) # 讀取攝影鏡頭
while True:
ret, frame = cap.read() # 讀取影片的每一幀
w = frame.shape[1] # 畫面寬度
h = frame.shape[0] # 畫面高度
img = cv2.resize(frame,(480,320)) # 調整影像尺寸為 480x320
output = np.zeros((320,480,3), dtype='uint8') # 繪製 480x320 的黑色畫布
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 轉換顏色
mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=img2) # 換成 img2
face_landmarker_result = landmarker.detect(mp_image)
face_landmarks_list = face_landmarker_result.face_landmarks
annotated_image = np.copy(output) # 換成 output
# Loop through the detected faces to visualize.
for idx in range(len(face_landmarks_list)):
face_landmarks = face_landmarks_list[idx]
# Draw the face landmarks.
face_landmarks_proto = landmark_pb2.NormalizedLandmarkList()
face_landmarks_proto.landmark.extend([
landmark_pb2.NormalizedLandmark(x=landmark.x, y=landmark.y, z=landmark.z) for landmark in face_landmarks
])
solutions.drawing_utils.draw_landmarks(
image=annotated_image,
landmark_list=face_landmarks_proto,
connections=mp.solutions.face_mesh.FACEMESH_TESSELATION,
landmark_drawing_spec=None,
connection_drawing_spec=mp.solutions.drawing_styles
.get_default_face_mesh_tesselation_style())
solutions.drawing_utils.draw_landmarks(
image=annotated_image,
landmark_list=face_landmarks_proto,
connections=mp.solutions.face_mesh.FACEMESH_CONTOURS,
landmark_drawing_spec=None,
connection_drawing_spec=mp.solutions.drawing_styles
.get_default_face_mesh_contours_style())
solutions.drawing_utils.draw_landmarks(
image=annotated_image,
landmark_list=face_landmarks_proto,
connections=mp.solutions.face_mesh.FACEMESH_IRISES,
landmark_drawing_spec=None,
connection_drawing_spec=mp.solutions.drawing_styles
.get_default_face_mesh_iris_connections_style())
#print(face_landmarker_result)
if not ret:
print("Cannot receive frame") # 如果讀取錯誤,印出訊息
break
cv2.imshow('oxxostudio', annotated_image) # 如果讀取成功,顯示該幀的畫面
if cv2.waitKey(10) == ord('q'): # 每一毫秒更新一次,直到按下 q 結束
break
cap.release() # 所有作業都完成後,釋放資源
cv2.destroyAllWindows() # 結束所有視窗
微信扫码关注
抖音扫码关注