Mediapipe人脸关键点检测
Mediapipe介绍
MediaPipe是由google制作的开源的、跨平台的机器学习框架,可以将一些模型部署到不同的平台和设备上使用的同时,也能保住检测速度。
从图中可以发现,能在Python上实现的功能包括人脸检测(Face Detection)、人脸关键点(Face Mesh),手部关键点(Hands)等。利用C++能实现更丰富的功能,我们可以后续探索。
环境部署
- Python环境:建议3.6版本以上
- Python主要模块:opencv-contrib-python;numpy; pandas; matplotlib
- MediaPipe模块:mediapipe
安装方法:使用以下pip命令安装
pip install mediapipe
测试环境:导入如下库,如果不报错说明导入成功
import cv2
import mediapipe as mp
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
人脸关键点检测
模型调用与配置
# 调用关键点检测模型
mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(static_image_mode=True,
max_num_faces=3,
refine_landmarks=True,
min_detection_confidence=0.5,
min_tracking_confidence=0.5)
FaceMesh参数说明
- static_image_mode=True, 检测静态图片设置为False,检测视频设置为True,默认为False
- max_num_faces=3, 能检测的最大人脸数,默认为1
- refine_landmarks=True, 定位嘴唇、眼睛、瞳孔的关键点,设置为True,否则设置为False
- min_detection_confidence=0.5, 人脸检测的置信度
- min_tracking_confidence=0.5) 人脸追踪的置信度(检测图像时可以忽略)
输出结果解析
# 读取图像
img1 = cv2.imread("./images/img1.jpg")
# 将BGR图像转为RGB图像
_img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)
# 使用模型获取关键点
results = face_mesh.process(_img1)
- 利用opencv读取图像的颜色通道为BGR,需要利用cv2.cvtColor方法将颜色通道转换为RGB
- 使用FaceMesh模型的process方法检测图像中的关键点
# 输出关键点
landmarks = results.multi_face_landmarks
print(landmarks)
# 提取关键点坐标
print(landmarks[0].landmark)
landmarks中以类似列表的结构(可迭代对象)存储了关键点,结构中每个“landmark”关键字段存储了关键点的坐标,包含x
,y
,z
,x
和y
分别通过图像宽度和高度归一化为[0.0,1.0].z
表示关键点深度,以头部中心的深度为原点,该值越小,关键点距离相机越近.
# 获取每个人脸的关键点的数量
print(len(landmarks[0].landmark))
当模型配置refine_landmarks=True
,获得478个人脸关键点;当模型配置refine_landmarks=False
,获得468个人脸关键点,缺少瞳孔的关键点。
关键点位置可以查看该图像:https://github.com/google/mediapipe/blob/master/mediapipe/modules/face_geometry/data/canonical_face_model_uv_visualization.png
绘制面网
利用mediapipe提供的绘制模块直接绘制
# mediapipe提供的绘制模块
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
# 利用mp_drawing绘制面网
annotated_image = img1.copy()
# 循环获取每一个人脸的关键点
for face_landmarks in results.multi_face_landmarks:
mp_drawing.draw_landmarks(image=annotated_image, landmark_list=face_landmarks,
# 选取关键点
connections=mp_face_mesh.FACEMESH_TESSELATION,
# 绘制关键点,若为None,表示不绘制关键点,也可以指定点的颜色、粗细、半径
landmark_drawing_spec=mp_drawing.DrawingSpec(color=(0,0,255),thickness=2,circle_radius=2),
# 绘制连接线的格式
connection_drawing_spec=mp_drawing_styles.get_default_face_mesh_tesselation_style())
# # 利用opencv显示图像,在jupyter中显示效果一般
# cv2.imshow("image",annotated_image)
# if cv2.waitKey(0) == ord("q"):
# cv2.destroyAllWindows()
# 利用matplotlib展示
plt.figure(figsize=(50, 20))
plt.imshow(annotated_image[:, :, ::-1])
下图中关键点包括瞳孔关键点
使用mp_face_mesh.FACEMESH_TESSELATION
可以选取所需关键点位置,将这些点进行连接,绘制面网。 使用 mp_drawing_styles.get_default_face_mesh_tesselation_style()
可以设置连接线的格式
使用mp_face_mesh.FACEMESH_CONTOURS
可以选取轮廓点,将其连接成线,使用mp_drawing_styles.get_default_face_mesh_contours_style()
可以设置连接线的格式
视频演示
调用摄像头画面进行人脸关键点检测
import time
# 获取摄像头,0/1为摄像头编号
cap = cv2.VideoCapture(0)
# 循环读取视频每一帧
while True:
success,frame = cap.read()
if success:
start = time.time()
results = face_mesh.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
# 复制图像
annotated_image = frame.copy()
# 解封此行代码,可以将关键点绘制在黑色图像上,该代码能生成一张黑色图像
# annotated_image = np.zeros(annotated_image.shape, dtype='uint8')
# 如果检测到关键点
if results.multi_face_landmarks:
for face_landmarks in results.multi_face_landmarks:
# 利用mp_drawing绘制图像
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_IRISES,
landmark_drawing_spec=None,
connection_drawing_spec=mp_drawing_styles.get_default_face_mesh_iris_connections_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())
end = time.time()
fps = 1/(end-start)
annotated_image = cv2.putText(annotated_image,str(int(fps)),(30,50),cv2.FONT_HERSHEY_SIMPLEX,2,(0,0,255),1)
# 如果没有检测到关键点,在黑色背景上显示“NO FACE TO DETECT”
else:
annotated_image = np.zeros(annotated_image.shape, dtype='uint8')
annotated_image = cv2.putText(annotated_image,str("NO FACE TO DETECT"),(300,400),cv2.FONT_HERSHEY_SIMPLEX,2,(0,0,255),1)
cv2.imshow("image",annotated_image)
if cv2.waitKey(30) == ord("q"):
cv2.destroyAllWindows()
break
# 释放摄像头
cap.release()
np.zeros(shape,dtype)
可以创建一个给定维度(shape)的全零数组
- shape:创建的新数组的(维度),如(4,7,3),表示创建一个三维数组,第一个维度有4个元素,第二个维度有7个元素,第三个维度有3个元素.annotated_image.shape可以获取图像的维度(height,width,channel)
- dtype:创建新数组的数据类型,当dtype =unit8时为图像数据类型,其取值范围在0~255.
检测效果
面部关键点检测
可通过下方链接下载程序
源程序下载
更多推荐
所有评论(0)