一、技术选型
-
OpenCV(Open Source Computer Vision Library)
- 用于视频流捕捉、图像预处理和基本图像处理操作。
-
MediaPipe
- 提供高效的人脸检测与关键点提取功能(Face Mesh)。
-
Python
- 作为后端开发语言,整合上述库进行图像处理和动作识别。
-
Flask/Django(可选)
- 用于构建后端API服务,处理前端请求。
二、整体流程概述
-
视频流或图片获取
- 前端通过摄像头捕捉视频流或图片,并将数据发送至后端。
-
图像预处理
- 对接收到的图像数据进行解码、缩放和颜色空间转换。
-
人脸检测与关键点提取
- 使用 MediaPipe 提取面部关键点(Face Mesh)。
-
动作识别
- 根据关键点数据,分析用户的具体动作(如转头、眨眼、张嘴)。
-
结果返回
- 将识别结果以 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 号关键点)
实现步骤:
- 计算左眼外角与鼻尖的连线向量。
- 计算右眼外角与鼻尖的连线向量。
- 通过向量之间的角度差,判断头部是否向左或向右转动。
示例代码:
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