使用了Mediapipe库进行面部检测和面部特征点检测,并通过简单的几何计算实现了微笑检测
本文将详细讲解一个利用OpenCV和Mediapipe库实现的实时面部表情识别系统。我们将逐行分析代码,解释其各部分的功能和实现细节。希望通过这篇文章,读者能够深入理解这段代码,并能独立实现类似的项目。
分部详解
导入库
import cv2 import mediapipe as mp import time
首先,我们需要导入所需的库:
cv2
是OpenCV库,用于图像处理和计算机视觉。mediapipe
是一个跨平台的机器学习库,专门用于实时计算机视觉应用。time
用于计算帧率(FPS)。初始化Mediapipe模块
mp_face_detection = mp.solutions.face_detection mp_drawing = mp.solutions.drawing_utils mp_face_mesh = mp.solutions.face_mesh
我们需要初始化Mediapipe的几个模块:
mp_face_detection
用于面部检测。mp_drawing
用于在图像上绘制检测结果。mp_face_mesh
用于面部特征点检测。初始化摄像头
cap = cv2.VideoCapture(0)
cv2.VideoCapture(0)
用于打开默认摄像头(索引为0),以便获取实时视频流。
初始化Face Detection和Face Mesh模型
with mp_face_detection.FaceDetection(min_detection_confidence=0.5) as face_detection, \ mp_face_mesh.FaceMesh(min_detection_confidence=0.1, min_tracking_confidence=0.1) as face_mesh:
我们使用 with
语句来初始化Face Detection和Face Mesh模型:
min_detection_confidence
和 min_tracking_confidence
是两个重要的参数,用于控制模型的检测和追踪信心阈值。初始化FPS计算
start_time = time.time() frame_count = 0
我们使用 start_time
和 frame_count
来计算每秒帧数(FPS),以评估系统的实时性能。
读取和处理视频帧
while cap.isOpened(): ret, frame = cap.read() if not ret: break
进入视频读取和处理的主循环。在每一帧中:
cap.read()
读取视频帧。if not ret: break
检查是否成功读取帧,如果失败则退出循环。图像转换
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
Mediapipe需要RGB格式的图像,因此我们需要将每帧从BGR转换为RGB。
面部检测
results_detection = face_detection.process(rgb_frame)
调用 face_detection.process(rgb_frame)
对帧进行面部检测,并将结果存储在 results_detection
中。
面部特征点检测
results_mesh = face_mesh.process(rgb_frame)
调用 face_mesh.process(rgb_frame)
对帧进行面部特征点检测,并将结果存储在 results_mesh
中。
绘制检测结果
if results_detection and results_detection.detections: for detection in results_detection.detections: mp_drawing.draw_detection(frame, detection)
如果检测到面部,我们使用 mp_drawing.draw_detection(frame, detection)
在帧上绘制面部检测结果。
绘制面部特征点
if results_mesh and results_mesh.multi_face_landmarks: for face_landmarks in results_mesh.multi_face_landmarks: mp_drawing.draw_landmarks(frame, face_landmarks)
如果检测到面部特征点,我们使用 mp_drawing.draw_landmarks(frame, face_landmarks)
在帧上绘制面部特征点。
简单的面部表情识别
left_lip = face_landmarks.landmark[61] right_lip = face_landmarks.landmark[291] upper_lip = face_landmarks.landmark[13] lower_lip = face_landmarks.landmark[14] lip_distance = abs(upper_lip.y - lower_lip.y) lip_width = abs(left_lip.x - right_lip.x) if lip_distance / lip_width > 0.05: expression = "Smiling" else: expression = "Neutral"
这里我们添加了一个简单的面部表情识别功能:
显示面部表情
cv2.putText(frame, f'Expression: {expression}', (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
在帧上显示检测到的面部表情。
计算和显示FPS
frame_count += 1 elapsed_time = time.time() - start_time fps = frame_count / elapsed_time cv2.putText(frame, f'FPS: {fps:.2f}', (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
计算并显示FPS,方便我们评估系统的性能。
显示结果
cv2.imshow('Facial Expression Analysis', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break
使用 cv2.imshow
显示结果,并监听键盘事件,当按下 q
键时退出循环。
释放资源
cap.release() cv2.destroyAllWindows()
释放摄像头资源并关闭所有窗口。
整体代码
import cv2
import mediapipe as mp
import time
# 初始化Mediapipe Face模块
mp_face_detection = mp.solutions.face_detection
mp_drawing = mp.solutions.drawing_utils
mp_face_mesh = mp.solutions.face_mesh
# 初始化摄像头
cap = cv2.VideoCapture(0)
# 初始化Face Detection和Face Mesh模型
with mp_face_detection.FaceDetection(min_detection_confidence=0.5) as face_detection, \
mp_face_mesh.FaceMesh(min_detection_confidence=0.1, min_tracking_confidence=0.1) as face_mesh:
# 初始化FPS计算
start_time = time.time()
frame_count = 0
while cap.isOpened():
# 读取视频帧
ret, frame = cap.read()
if not ret:
break
# 将图像转换为RGB格式
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# 进行Face Detection
results_detection = face_detection.process(rgb_frame)
# 进行Face Mesh
results_mesh = face_mesh.process(rgb_frame)
# 如果检测到面部
if results_detection and results_detection.detections:
for detection in results_detection.detections:
mp_drawing.draw_detection(frame, detection)
# 如果检测到面部并提取到了面部特征点
if results_mesh and results_mesh.multi_face_landmarks:
for face_landmarks in results_mesh.multi_face_landmarks:
mp_drawing.draw_landmarks(frame, face_landmarks)
# 简单的面部表情识别(如微笑检测)
left_lip = face_landmarks.landmark[61]
right_lip = face_landmarks.landmark[291]
upper_lip = face_landmarks.landmark[13]
lower_lip = face_landmarks.landmark[14]
lip_distance = abs(upper_lip.y - lower_lip.y)
lip_width = abs(left_lip.x - right_lip.x)
# 设定一个简单的阈值来判断微笑
if lip_distance / lip_width > 0.05:
expression = "Smiling"
else:
expression = "Neutral"
# 在帧上显示面部表情
cv2.putText(frame, f'Expression: {expression}', (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# 计算FPS
frame_count += 1
elapsed_time = time.time() - start_time
fps = frame_count / elapsed_time
# 在帧上显示FPS
cv2.putText(frame, f'FPS: {fps:.2f}', (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# 显示结果
cv2.imshow('Facial Expression Analysis', frame)
# 检测按键,按 'q' 键退出循环
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 释放资源
cap.release()
cv2.destroyAllWindows()
效果展示
微笑,基本上只要你不哭,一般就判断为微笑了。
这里不微笑的时候,一定要正对摄像头,不然很容易导致识别不灵敏。
当然了,你也可以不绘制脸部的点,这样可能会显著提升一点FPS帧数。
结论
通过这段代码,我们实现了一个实时的面部表情识别系统。我们使用了Mediapipe库进行面部检测和面部特征点检测,并通过简单的几何计算实现了微笑检测。在此希望通过本文的讲解,广大读者能够深入理解每一部分代码的功能,并能够在此基础上扩展和改进系统的功能。
作者:WenJGo