在计算机视觉领域,人脸关键点检测是许多应用的基础,如表情分析、人脸姿态估计、美颜特效等。本文将基于两份实际代码,详细讲解如何使用 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
处理流程解析:
- 图像格式转换(BGR→RGB)
- 模型推理获取关键点
- 绘制检测结果(关键点、轮廓、索引)
- 添加状态提示(是否检测到人脸)
- 计算并显示处理帧率
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()
关键技术点总结
- 坐标转换:MediaPipe 返回的是相对坐标(0-1 之间),需要乘以图像宽高得到实际像素坐标
cx = int(coord.x * w)
cy = int(coord.y * h)
- 颜色空间转换:OpenCV 默认读取的是 BGR 格式,而 MediaPipe 需要 RGB 格式,因此需要转换
img_RGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
- 帧率计算:通过记录每一帧的处理时间来计算 FPS
FPS = 1/(end_time - start_time)
- 可视化选项:MediaPipe 提供了多种可视化连接方式
-
- mp_face_mesh.FACEMESH_TESSELATION:显示完整的人脸网格
-
- mp_face_mesh.FACEMESH_CONTOURS:只显示面部轮廓
实际应用场景
- 表情识别与分析
- 人脸姿态估计
- 实时美颜与特效
- 驾驶员注意力监测
- 人机交互中的面部指令识别
通过这两份代码,我们可以快速实现人脸关键点检测功能,并根据实际需求进行二次开发和优化。
731

被折叠的 条评论
为什么被折叠?



