使用MediaPipe Face Mesh 面部动作检测

一、技术选型

  1. OpenCV(Open Source Computer Vision Library)

    • 用于视频流捕捉、图像预处理和基本图像处理操作。
  2. MediaPipe

    • 提供高效的人脸检测与关键点提取功能(Face Mesh)。
  3. Python

    • 作为后端开发语言,整合上述库进行图像处理和动作识别。
  4. Flask/Django(可选)

    • 用于构建后端API服务,处理前端请求。

二、整体流程概述

  1. 视频流或图片获取

    • 前端通过摄像头捕捉视频流或图片,并将数据发送至后端。
  2. 图像预处理

    • 对接收到的图像数据进行解码、缩放和颜色空间转换。
  3. 人脸检测与关键点提取

    • 使用 MediaPipe 提取面部关键点(Face Mesh)。
  4. 动作识别

    • 根据关键点数据,分析用户的具体动作(如转头、眨眼、张嘴)。
  5. 结果返回

    • 将识别结果以 JSON 格式返回前端。

三、详细实现步骤

1. 视频流或图片获取

前端(微信小程序)捕捉到视频帧或图片后,通过 API 将图像数据(通常为 Base64 编码或二进制数据)发送至后端。

前端发送图像数据示例(微信小程序)

wx.chooseImage({
   
  count: 1,
  success: function(res) {
   
    const tempFilePaths = res.tempFilePaths;
    wx.getFileSystemManager().readFile({
   
      filePath: tempFilePaths[0],
      encoding: 'base64',
      success: function(data) {
   
        wx.request({
   
          url: 'https://localhost/api/task/detect',
          method: 'POST',
          data: {
   
            user_id: 'unique_user_id',
            image_data: data.data
          },
          success: function(response) {
   
            // 处理后端返回的检测结果
          }
        });
      }
    });
  }
});
2. 图像预处理

后端接收到图像数据后,进行解码和预处理。

示例代码(Python)

import base64
import cv2
import numpy as np

def decode_image(image_base64):
    # 解码 Base64 图像数据
    img_data = base64.b64decode(image_base64)
    # 转换为 numpy 数组
    np_arr = np.frombuffer(img_data, np.uint8)
    # 使用 OpenCV 解码图像
    img = cv2.imdecode(np_arr, cv2.IMREAD_COLOR)
    return img
3. 人脸检测与关键点提取

使用 MediaPipe 的 Face Mesh 模型提取面部关键点。

安装 MediaPipe

pip install mediapipe

示例代码(Python)

import mediapipe as mp

# 初始化 MediaPipe Face Mesh
mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(
    static_image_mode=False,
    max_num_faces=1,
    refine_landmarks=True,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5
)

def get_face_landmarks(image):
    # 将图像从 BGR 转换为 RGB
    rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    # 获取关键点
    results = face_mesh.process(rgb_image)
    if results.multi_face_landmarks:
        # 返回第一个人脸的关键点
        return results.multi_face_landmarks[0]
    else:
        return None
4. 动作识别

基于提取的关键点数据,分析用户的具体动作。以下分别介绍左右转头、眨眼和张嘴的检测方法。

4.1 左右转头检测

通过分析左右眼和鼻子的关键点位置,计算头部的旋转角度。

关键点选择

  • 鼻尖(例如 MediaPipe Face Mesh 的 1 号关键点)
  • 左眼外角(例如 33 号关键点)
  • 右眼外角(例如 263 号关键点)

实现步骤

  1. 计算左眼外角与鼻尖的连线向量。
  2. 计算右眼外角与鼻尖的连线向量。
  3. 通过向量之间的角度差,判断头部是否向左或向右转动。

示例代码

import math

def calculate_angle(p1, p2):
    # 计算两点连线的角度(相对于水平线)
    delta_y = p2.y - p1.y
    delta_x = p2.x - p1.x
    angle = math.degrees(math.atan2(delta_y, delta_x))
    return angle

def detect_head_turn(landmarks):
    # 关键点索引(根据 MediaPipe Face Mesh)
    nose_tip = landmarks
### 使用MediaPipe Face Mesh实现疲劳监测 #### 安装依赖库 为了使用MediaPipe进行面部特征点检测以及后续的疲劳监测,需安装必要的Python包。 ```bash pip install mediapipe opencv-python streamlit streamlit-webrtc numpy ``` #### 初始化MediaPipe Face Mesh对象 创建一个基于MediaPipeFace Mesh实例来获取面部的关键点数据。 ```python import cv2 import mediapipe as mp mp_face_mesh = mp.solutions.face_mesh face_mesh = mp_face_mesh.FaceMesh(min_detection_confidence=0.5, min_tracking_confidence=0.5) ``` #### 计算眼睛纵横比(EAR) 定义函数计算单只眼的EAR值。该指标有助于判断眼睛闭合程度,从而识别可能存在的打瞌睡情况[^2]。 ```python def eye_aspect_ratio(landmarks, start_index, end_index): points = landmarks[start_index:end_index+1] # 提取垂直方向上的三个关键点坐标差绝对值之和除以水平两个端点间距离作为EAR A = abs(points[1].y - points[5].y) B = abs(points[2].y - points[4].y) C = abs(points[0].x - points[3].x) ear = (A + B) / (2.0 * C) return ear ``` #### 处理视频帧并绘制结果 读取摄像头输入,在每一帧图像上标记出人脸网格,并调用上述`eye_aspect_ratio()`函数评估每侧眼睛的状态。 ```python cap = cv2.VideoCapture(0) while cap.isOpened(): success, image = cap.read() if not success: break # 将BGR转RGB供MediaPipe处理 image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) results = face_mesh.process(image_rgb).multi_face_landmarks if results is None or len(results)==0 : continue for facial_landmarks in results: h, w, _ = image.shape landmark_points = [] for idx in range(len(facial_landmarks.landmark)): pt = facial_landmarks.landmark[idx] x = int(pt.x * w) y = int(pt.y * h) landmark_points.append([idx,x,y]) left_eye_ear = eye_aspect_ratio(landmark_points, 362, 398) right_eye_ear = eye_aspect_ratio(landmark_points, 133, 172) avg_ear = (left_eye_ear + right_eye_ear)/2.0 print('Average EAR:',avg_ear) # 如果平均EAR低于设定阈值,则认为司机处于疲倦状态 THRESHOLD_EAR = 0.25 if avg_ear < THRESHOLD_EAR: cv2.putText(image,"DROWSINESS ALERT!", (30,30),cv2.FONT_HERSHEY_SIMPLEX ,1,(0,0,255),2,cv2.LINE_AA ) # 显示带有标注后的图片窗口 cv2.imshow('Driver Drowsiness Detection',image) key=cv2.waitKey(1)&0xFF if key==ord('q'): break cap.release() cv2.destroyAllWindows() ``` 此段代码展示了如何利用MediaPipe Face Mesh提取眼部区域的信息,并通过简单的算法估算眼睛开合度,进而辅助判定是否存在因过度劳累而导致注意力下降的情况。实际应用场景下还需要考虑更多因素,比如光照条件变化的影响等。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

由数入道

滴水助江海,心灯渡万世。

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

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

打赏作者

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

抵扣说明:

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

余额充值