mediapipe新版本怎么玩--面部特征检测

文章目录


环境配置

上一篇文章讲了环境问题,其他环境配置交给ai来解决

先说面部特征检测

一、导入包

python 复制代码
import cv2
import numpy as np
from PIL import Image
import mediapipe as mp
from mediapipe.tasks import python
from mediapipe.tasks.python import vision

二、面部图像检测

1.模型路径

python 复制代码
base_options = python.BaseOptions(model_asset_path='./tasks/face_landmarker.task')
# 2. 用 FaceLandmarkerOptions 替代 FaceDetectorOptions
options = vision.FaceLandmarkerOptions(
    base_options=base_options,
    num_faces=1,  # 最大检测人脸
    min_face_detection_confidence=0.7,
    min_tracking_confidence	 = 0.7,
    output_facial_transformation_matrixes = True
    
)
# 3. 创建 FaceLandmarker 替代 FaceDetector
detector = vision.FaceLandmarker.create_from_options(options)

2.人脸网格可视化工具(MediaPipe 0.10+ 官方原版)

代码如下(示例):

python 复制代码
mp_face = mp.tasks.vision.FaceLandmarksConnections
mp_drawing = mp.tasks.vision.drawing_utils
mp_drawing_styles = mp.tasks.vision.drawing_styles

def draw_face_landmarks_on_image(rgb_image, detection_result):
    face_landmarks_list = detection_result.face_landmarks
    annotated_image = np.copy(rgb_image)

    # 遍历每一张人脸
    for face_landmarks in face_landmarks_list:
        # 绘制完整人脸网格(468个点+连线)
        mp_drawing.draw_landmarks(
            image=annotated_image,
            landmark_list=face_landmarks,
            connections=mp_face.FACE_LANDMARKS_TESSELATION,
            landmark_drawing_spec=None,
            connection_drawing_spec=mp_drawing_styles.get_default_face_mesh_tesselation_style()
        )
        # 绘制面部轮廓
        mp_drawing.draw_landmarks(
            image=annotated_image,
            landmark_list=face_landmarks,
            connections=mp_face.FACE_LANDMARKS_CONTOURS,
            landmark_drawing_spec=None,
            connection_drawing_spec=mp_drawing_styles.get_default_face_mesh_contours_style()
        )
        # 绘制左右虹膜(开启refine_landmarks后生效)
        mp_drawing.draw_landmarks(
            image=annotated_image,
            landmark_list=face_landmarks,
            connections=mp_face.FACE_LANDMARKS_LEFT_IRIS,
            landmark_drawing_spec=None,
            connection_drawing_spec=mp_drawing_styles.get_default_face_mesh_iris_connections_style()
        )
        mp_drawing.draw_landmarks(
            image=annotated_image,
            landmark_list=face_landmarks,
            connections=mp_face.FACE_LANDMARKS_RIGHT_IRIS,
            landmark_drawing_spec=None,
            connection_drawing_spec=mp_drawing_styles.get_default_face_mesh_iris_connections_style()
        )

    return annotated_image

3. 加载图片与可视化

python 复制代码
# 加载图片
image_cv = cv2.imread("imgs/girl.jpg") ## 自己搞一个数据集 自拍也行
rgb_image = cv2.cvtColor(image_cv, cv2.COLOR_BGR2RGB)
mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=rgb_image)

# 执行检测(FaceLandmarker)
detection_result = detector.detect(mp_image)

# 可视化(完整468个点)
annotated_image = draw_face_landmarks_on_image(rgb_image, detection_result)

# 显示+保存
cv2.imshow("Face Landmark Result", cv2.cvtColor(annotated_image, cv2.COLOR_RGB2BGR))
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite("imgs/face_landmark_result.jpg", cv2.cvtColor(annotated_image, cv2.COLOR_RGB2BGR))

二、视频的人脸检测

导入包还是那些

python 复制代码
BaseOptions = mp.tasks.BaseOptions
# 1. 模型路径换成 face_landmarker.task(之前给你的模型地址)
base_options = python.BaseOptions(model_asset_path='./tasks/face_landmarker.task')

FaceLandmarker = mp.tasks.vision.FaceLandmarker
FaceLandmarkerOptions = mp.tasks.vision.FaceLandmarkerOptions
VisionRunningMode = mp.tasks.vision.RunningMode

# Create a face landmarker instance with the video mode:
options = FaceLandmarkerOptions(
    base_options = base_options,
    running_mode=VisionRunningMode.VIDEO)
python 复制代码
# ----------------------
# 1. 配置参数(按需修改)
# ----------------------
MODEL_PATH = "./tasks/face_landmarker.task"  # 你的模型路径
INPUT_VIDEO_PATH = "./imgs/test.avi"       # 输入视频路径
OUTPUT_VIDEO_PATH = "./imgs/face_landmark_result.avi"  # 输出视频路径
# ----------------------
# 2. 初始化MediaPipe相关工具
# ----------------------
mp_face = mp.tasks.vision.FaceLandmarksConnections
mp_drawing = mp.tasks.vision.drawing_utils
mp_drawing_styles = mp.tasks.vision.drawing_styles
python 复制代码
# ----------------------
# 3. 可视化函数(绘制468个人脸关键点)
# ----------------------
def draw_face_landmarks_on_image(rgb_image, detection_result):
    annotated_image = np.copy(rgb_image)
    face_landmarks_list = detection_result.face_landmarks

    # 遍历每一张检测到的人脸
    for face_landmarks in face_landmarks_list:
        # 绘制人脸网格(468个点的连线)
        mp_drawing.draw_landmarks(
            image=annotated_image,
            landmark_list=face_landmarks,
            connections=mp_face.FACE_LANDMARKS_TESSELATION,
            landmark_drawing_spec=None,
            connection_drawing_spec=mp_drawing_styles.get_default_face_mesh_tesselation_style()
        )
        # 绘制面部轮廓
        mp_drawing.draw_landmarks(
            image=annotated_image,
            landmark_list=face_landmarks,
            connections=mp_face.FACE_LANDMARKS_CONTOURS,
            landmark_drawing_spec=None,
            connection_drawing_spec=mp_drawing_styles.get_default_face_mesh_contours_style()
        )
        # 绘制虹膜(如果开启refine_landmarks)
        mp_drawing.draw_landmarks(
            image=annotated_image,
            landmark_list=face_landmarks,
            connections=mp_face.FACE_LANDMARKS_LEFT_IRIS,
            landmark_drawing_spec=None,
            connection_drawing_spec=mp_drawing_styles.get_default_face_mesh_iris_connections_style()
        )
        mp_drawing.draw_landmarks(
            image=annotated_image,
            landmark_list=face_landmarks,
            connections=mp_face.FACE_LANDMARKS_RIGHT_IRIS,
            landmark_drawing_spec=None,
            connection_drawing_spec=mp_drawing_styles.get_default_face_mesh_iris_connections_style()
        )
    return annotated_image
python 复制代码
# ----------------------
# 4. 核心:视频检测主流程
# ----------------------
def process_video():
    # STEP 1: 创建FaceLandmarker(VIDEO模式)
    base_options = python.BaseOptions(model_asset_path=MODEL_PATH)
    options = vision.FaceLandmarkerOptions(
        base_options=base_options,
        running_mode=vision.RunningMode.VIDEO,  # 关键:设为VIDEO模式
        num_faces=1,
        min_face_detection_confidence=0.5,
        min_tracking_confidence=0.5
    )

    # STEP 2: 打开输入视频
    cap = cv2.VideoCapture(INPUT_VIDEO_PATH)
    if not cap.isOpened():
        raise FileNotFoundError(f"无法打开视频文件:{INPUT_VIDEO_PATH}")
    
    # 获取视频参数
    fps = cap.get(cv2.CAP_PROP_FPS)  # 视频帧率
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))  # 宽度
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))  # 高度
    frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))  # 总帧数

    # STEP 3: 初始化视频写入器(保存结果)
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')  # 编码格式
    out = cv2.VideoWriter(OUTPUT_VIDEO_PATH, fourcc, fps, (width, height))

    # STEP 4: 逐帧处理视频
    with vision.FaceLandmarker.create_from_options(options) as landmarker:
        frame_timestamp_ms = 0  # 初始时间戳(ms)
        while cap.isOpened():
            ret, frame = cap.read()
            if not ret:
                break  # 视频处理完成

            # ----------------------
            # 帧预处理
            # ----------------------
            # OpenCV读入的是BGR,转RGB适配MediaPipe
            rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            # 转MediaPipe Image对象
            mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=rgb_frame)

            # ----------------------
            # 执行视频帧检测(关键:传入时间戳)
            # ----------------------
            detection_result = landmarker.detect_for_video(
                mp_image, 
                frame_timestamp_ms  # 每帧的时间戳(ms)
            )

            # ----------------------
            # 可视化 + 显示
            # ----------------------
            annotated_frame = draw_face_landmarks_on_image(rgb_frame, detection_result)
            # 转BGR用于OpenCV显示/保存
            bgr_annotated_frame = cv2.cvtColor(annotated_frame, cv2.COLOR_RGB2BGR)
            
            # 显示实时结果(按q退出)
            cv2.imshow("Face Landmarker - Video", bgr_annotated_frame)
            # 保存帧到输出视频
            out.write(bgr_annotated_frame)

            # ----------------------
            # 更新时间戳 + 退出逻辑
            # ----------------------
            frame_timestamp_ms += int(1000 / fps)  # 按帧率更新时间戳(ms)
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break  # 按q提前退出
                
    # STEP 5: 释放资源
    cap.release()
    out.release()
    cv2.destroyAllWindows()
    print(f"视频处理完成!结果保存到:{OUTPUT_VIDEO_PATH}")
python 复制代码
# ----------------------
# 运行主函数
# ----------------------
if __name__ == "__main__":
    # 确保输出文件夹存在
    import os
    os.makedirs("./videos", exist_ok=True)
    process_video()

3. 摄像头的模式检测

python 复制代码
# ----------------------
# 2. 全局变量(用于回调函数传值)
# ----------------------
import threading 
MODEL_PATH = "./tasks/face_landmarker.task"  # 你的模型路径
latest_detection_result = None  # 存储最新检测结果
result_lock = threading.Lock()   # 简单锁,保证线程安全
# ----------------------
# 3. 初始化MediaPipe相关工具
# ----------------------
mp_face = mp.tasks.vision.FaceLandmarksConnections
mp_drawing = mp.tasks.vision.drawing_utils
mp_drawing_styles = mp.tasks.vision.drawing_styles
python 复制代码
# ----------------------
# 5. 可视化函数(绘制468个人脸关键点)
# ----------------------
def draw_face_landmarks_on_image(rgb_image, detection_result):
    annotated_image = np.copy(rgb_image)
    if detection_result is None or len(detection_result.face_landmarks) == 0:
        return annotated_image  # 无检测结果时返回原图
    
    # 遍历每一张检测到的人脸
    for face_landmarks in detection_result.face_landmarks:
        # 绘制人脸网格(468个点的连线)
        mp_drawing.draw_landmarks(
            image=annotated_image,
            landmark_list=face_landmarks,
            connections=mp_face.FACE_LANDMARKS_TESSELATION,
            landmark_drawing_spec=None,
            connection_drawing_spec=mp_drawing_styles.get_default_face_mesh_tesselation_style()
        )
        # 绘制面部轮廓
        mp_drawing.draw_landmarks(
            image=annotated_image,
            landmark_list=face_landmarks,
            connections=mp_face.FACE_LANDMARKS_CONTOURS,
            landmark_drawing_spec=None,
            connection_drawing_spec=mp_drawing_styles.get_default_face_mesh_contours_style()
        )
        # 绘制虹膜(开启refine_landmarks后生效)
        mp_drawing.draw_landmarks(
            image=annotated_image,
            landmark_list=face_landmarks,
            connections=mp_face.FACE_LANDMARKS_LEFT_IRIS,
            landmark_drawing_spec=None,
            connection_drawing_spec=mp_drawing_styles.get_default_face_mesh_iris_connections_style()
        )
        mp_drawing.draw_landmarks(
            image=annotated_image,
            landmark_list=face_landmarks,
            connections=mp_face.FACE_LANDMARKS_RIGHT_IRIS,
            landmark_drawing_spec=None,
            connection_drawing_spec=mp_drawing_styles.get_default_face_mesh_iris_connections_style()
        )
    return annotated_image
python 复制代码
# ----------------------
# 6. 回调函数(异步接收检测结果,加锁保证线程安全)
# ----------------------
def result_callback(result, output_image, timestamp_ms):
    """LIVE_STREAM模式必须的回调函数,异步处理检测结果"""
    global latest_detection_result
    # 加锁:避免主线程读取时,子线程修改数据导致冲突
    with result_lock:
        latest_detection_result = result  # 更新最新结果
python 复制代码
# ----------------------
# 7. 核心:摄像头实时检测主流程
# ----------------------
import time
CAMERA_ID = 0 

def process_camera():
    global latest_detection_result
    
    # STEP 1: 创建FaceLandmarker(LIVE_STREAM模式)
    base_options = python.BaseOptions(model_asset_path=MODEL_PATH)
    options = vision.FaceLandmarkerOptions(
        base_options=base_options,
        running_mode=vision.RunningMode.LIVE_STREAM,  # 实时流模式
        num_faces=1,
        min_face_detection_confidence=0.5,
        min_tracking_confidence=0.5,
        #refine_landmarks=True,  # 开启虹膜检测(468→478个点)
        result_callback=result_callback  # 必须:设置结果回调函数
    )

    # STEP 2: 打开摄像头
    cap = cv2.VideoCapture(CAMERA_ID)
    if not cap.isOpened():
        raise RuntimeError(f"无法打开摄像头(ID:{CAMERA_ID}),请检查摄像头是否被占用")
    
    # 设置摄像头分辨率(降低分辨率提升帧率)
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)

    # STEP 3: 初始化检测器并处理实时流
    with vision.FaceLandmarker.create_from_options(options) as landmarker:
        print("摄像头已启动!按 'q' 退出,按 's' 保存当前帧")
        
        while cap.isOpened():
            ret, frame = cap.read()
            if not ret:
                print("无法读取摄像头帧")
                break

            # ----------------------
            # 帧预处理
            # ----------------------
            rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)  # BGR→RGB
            mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=rgb_frame)
            
            # ----------------------
            # 异步检测(LIVE_STREAM核心)
            # ----------------------
            frame_timestamp_ms = int(time.time() * 1000)  # 当前时间戳(ms)
            landmarker.detect_async(mp_image, frame_timestamp_ms)  # 异步提交检测

            # ----------------------
            # 可视化 + 显示(加锁读取结果)
            # ----------------------
            with result_lock:
                current_result = latest_detection_result  # 安全读取结果
            
            annotated_frame = draw_face_landmarks_on_image(rgb_frame, current_result)
            bgr_annotated_frame = cv2.cvtColor(annotated_frame, cv2.COLOR_RGB2BGR)  # RGB→BGR
            
             # 添加醒目提示文字
            cv2.putText(
                bgr_annotated_frame,
                " 先点击窗口再按按键!",
                (10, 30),
                cv2.FONT_HERSHEY_SIMPLEX,
                0.8,
                (0, 0, 255),  # 红色醒目
                2
            )
            cv2.putText(
                bgr_annotated_frame,
                "q:退出 | s:保存帧",
                (10, 70),
                cv2.FONT_HERSHEY_SIMPLEX,
                0.8,
                (255, 0, 0),  # 蓝色
                2
            )
            
            # 显示画面(强制置顶,确保焦点)
            cv2.imshow("MediaPipe Face Landmarker - Camera", bgr_annotated_frame)
            cv2.setWindowProperty("MediaPipe Face Landmarker - Camera", cv2.WND_PROP_TOPMOST, 1)  # 窗口置顶


            # ----------------------
            # 按键控制
            # ----------------------
            key = cv2.waitKey(1) & 0xFF
            if key == ord('q'):
                break  # 按q退出
            elif key == ord('s'):
                # 按s保存当前帧
                save_path = f"face_camera_frame_{int(time.time())}.jpg"
                cv2.imwrite(save_path, bgr_annotated_frame)
                print(f"📸 帧已保存:{save_path}")

    # STEP 4: 释放资源
    cap.release()
    cv2.destroyAllWindows()
    print("摄像头已关闭")
python 复制代码
# ----------------------
# 运行主函数
# ----------------------
if __name__ == "__main__":
    process_camera()

总结

好玩

相关推荐
weixin_4597539423 分钟前
golang如何实现Trace上下文传播_golang Trace上下文传播实现思路
jvm·数据库·python
weixin_4440129333 分钟前
PHP 中逻辑或(--)运算符的正确使用与条件逻辑重构指南
jvm·数据库·python
iAm_Ike7 小时前
Go 中自定义类型与基础类型间的显式类型转换详解
jvm·数据库·python
iuvtsrt7 小时前
Golang怎么实现方法集与接口的匹配_Golang如何理解值类型和指针类型实现接口的区别【详解】
jvm·数据库·python
牧子川7 小时前
009-Transformer-Architecture
人工智能·深度学习·transformer
covco7 小时前
矩阵管理系统指南:拆解星链引擎的架构设计与全链路落地实践
大数据·人工智能·矩阵
沪漂阿龙7 小时前
AI大模型面试题:支持向量机是什么?间隔最大化、软间隔、核函数、LinearSVC 全面拆解
人工智能·算法·支持向量机
lifewange7 小时前
AI编写测试用例工具介绍
人工智能·测试用例
陕西字符7 小时前
2026 西安 豆包获客优化技术深度解析:企来客科技 AI 全域获客系统测评
大数据·人工智能
掘金安东尼7 小时前
GGUF、GPTQ、AWQ、EXL2、MLX、VMLX...运行大模型,为什么会有这么多格式?
人工智能