基于 MediaPipe 的人脸 468 关键点检测:视频与摄像头实时实现

在计算机视觉领域,人脸关键点检测是许多应用的基础,如表情分析、人脸姿态估计、美颜特效等。本文将基于两份实际代码,详细讲解如何使用 MediaPipe 库实现人脸 468 个关键点的检测,并分别应用于视频文件处理和摄像头实时检测。

recognized_video

核心库介绍

实现人脸关键点检测主要依赖以下几个 Python 库:

  • OpenCV(cv2):用于图像读取、处理和显示,以及视频 / 摄像头的捕获
  • MediaPipe:谷歌开源的多媒体处理框架,提供了预训练的人脸关键点检测模型
  • time:用于计算处理帧率 (FPS)
  • tqdm:用于显示视频处理的进度条

核心代码解析

1. 模型初始化

首先需要导入 MediaPipe 的人脸网格模型并进行初始化:

import mediapipe as mp

# 导入三维人脸关键点检测模型

mp_face_mesh = mp.solutions.face_mesh

model = mp_face_mesh.FaceMesh(

static_image_mode=False, # 连续视频帧模式

refine_landmarks=True, # 精细化嘴唇、眼睛等区域的关键点

max_num_faces=5, # 最多检测5张脸

min_detection_confidence=0.5, # 检测置信度阈值

min_tracking_confidence=0.5, # 追踪置信度阈值

)

参数说明:

  • static_image_mode:False 表示处理连续视频帧,True 用于静态图片
  • refine_landmarks:开启后能更精确地定位嘴唇、眼睛和瞳孔周围的关键点
  • 两个置信度阈值用于过滤低质量的检测结果

2. 可视化配置

为了直观展示检测结果,需要配置关键点和连接线条的样式:

# 导入可视化函数和可视化样式

mp_drawing = mp.solutions.drawing_utils

# 关键点可视化样式

landmark_drawing_spec = mp_drawing.DrawingSpec(

thickness=1,

circle_radius=2,

color=[66,77,229]

)

# 轮廓可视化样式

connection_drawing_spec = mp_drawing.DrawingSpec(

thickness=2,

circle_radius=1,

color=[223,155,6]

)

3. 帧处理核心函数

process_frame函数是整个实现的核心,负责对单帧图像进行处理:

 
def process_frame(img):

# 记录处理开始时间

start_time = time.time()

scaler = 1 # 文字大小缩放因子

# 获取图像宽高

h, w = img.shape[0], img.shape[1]

# BGR转RGB(MediaPipe需要RGB格式输入)

img_RGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 模型推理

results = model.process(img_RGB)

if results.multi_face_landmarks: # 如果检测到人脸

for face_landmarks in results.multi_face_landmarks: # 遍历每张脸

# 绘制关键点和轮廓

mp_drawing.draw_landmarks(

image=img,

landmark_list=face_landmarks,

connections=mp_face_mesh.FACEMESH_CONTOURS, # 绘制面部轮廓

landmark_drawing_spec=landmark_drawing_spec,

connection_drawing_spec=connection_drawing_spec

)

# 为每个关键点添加索引标签

for idx, coord in enumerate(face_landmarks.landmark):

cx = int(coord.x * w) # 将相对坐标转换为像素坐标

cy = int(coord.y * h)

img = cv2.putText(img, 'Face Detected',

(25 * scaler, 50 * scaler),

cv2.FONT_HERSHEY_SIMPLEX,

1.25 * scaler, (255, 0, 255), 2 * scaler)

img = cv2.putText(img, str(idx), (cx, cy),

cv2.FONT_HERSHEY_SIMPLEX,

0.3*scaler, (0, 255, 0), 1)

else:

# 未检测到人脸时显示提示

img = cv2.putText(img, 'No Face Detected',

(25 * scaler, 50 * scaler),

cv2.FONT_HERSHEY_SIMPLEX,

1.25 * scaler, (255, 0, 255), 2 * scaler)

# 计算并显示FPS

end_time = time.time()

FPS = 1/(end_time - start_time)

img = cv2.putText(img, 'FPS '+str(int(FPS)),

(25 * scaler, 100 * scaler),

cv2.FONT_HERSHEY_SIMPLEX,

1.25 * scaler, (255, 0, 255), 2 * scaler)

return img

处理流程解析:

  1. 图像格式转换(BGR→RGB)
  1. 模型推理获取关键点
  1. 绘制检测结果(关键点、轮廓、索引)
  1. 添加状态提示(是否检测到人脸)
  1. 计算并显示处理帧率

4. 视频文件处理实现

generate_video函数用于处理本地视频文件:


def generate_video(input_path='video.mp4'):

filehead = input_path.split('/')[-1]

output_path = "out-" + filehead

print('视频开始处理', input_path)

# 获取视频总帧数(用于进度条)

cap = cv2.VideoCapture(input_path)

frame_count = 0

while(cap.isOpened()):

success, frame = cap.read()

frame_count += 1

if not success:

break

cap.release()

print('视频总帧数为', frame_count)

# 初始化视频读取和写入对象

cap = cv2.VideoCapture(input_path)

frame_size = (cap.get(cv2.CAP_PROP_FRAME_WIDTH), cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 视频编码格式

fps = cap.get(cv2.CAP_PROP_FPS)

out = cv2.VideoWriter(output_path, fourcc, fps,

(int(frame_size[0]), int(frame_size[1])))

# 带进度条处理视频

with tqdm(total=frame_count-1) as pbar:

try:

while(cap.isOpened()):

success, frame = cap.read()

if not success:

break

# 处理每一帧

try:

frame = process_frame(frame)

except:

print('处理出错')

pass

if success:

out.write(frame) # 写入处理后的帧

pbar.update(1) # 更新进度条

except:

print('中途中断')

pass

# 释放资源

cv2.destroyAllWindows()

out.release()

cap.release()

print('视频已保存', output_path)

5. 摄像头实时检测实现

摄像头实时检测相对简单,主要是循环读取摄像头帧并处理:

# 获取摄像头,0表示默认摄像头

cap = cv2.VideoCapture(0)

# 打开摄像头

cap.open(0)

# 循环读取帧

while cap.isOpened():

success, frame = cap.read()

if not success:

print('读取失败')

break

# 处理帧

frame = process_frame(frame)

# 显示处理后的画面

cv2.imshow('Face Landmarks Detection', frame)

# 按q或esc退出

if cv2.waitKey(1) in [ord('q'), 27]:

break

# 释放资源

cap.release()

cv2.destroyAllWindows()

关键技术点总结

  1. 坐标转换:MediaPipe 返回的是相对坐标(0-1 之间),需要乘以图像宽高得到实际像素坐标
cx = int(coord.x * w)

cy = int(coord.y * h)
  1. 颜色空间转换:OpenCV 默认读取的是 BGR 格式,而 MediaPipe 需要 RGB 格式,因此需要转换
img_RGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  1. 帧率计算:通过记录每一帧的处理时间来计算 FPS
FPS = 1/(end_time - start_time)
  1. 可视化选项:MediaPipe 提供了多种可视化连接方式
    • mp_face_mesh.FACEMESH_TESSELATION:显示完整的人脸网格
    • mp_face_mesh.FACEMESH_CONTOURS:只显示面部轮廓

实际应用场景

  • 表情识别与分析
  • 人脸姿态估计
  • 实时美颜与特效
  • 驾驶员注意力监测
  • 人机交互中的面部指令识别

通过这两份代码,我们可以快速实现人脸关键点检测功能,并根据实际需求进行二次开发和优化。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

遗憾是什么.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值