MediaPipe与YOLO已训练模型实现可视化人脸和手势关键点检测

项目首页 - ZiTai_YOLOV11:基于前沿的 MediaPipe 技术与先进的 YOLOv11 预测试模型,精心打造一款强大的实时检测应用。该应用无缝连接摄像头,精准捕捉画面,能即时实现人脸检测、手势识别以及骨骼关键点检测,将检测结果实时、直观地呈现在屏幕上,为用户带来高效且便捷的视觉分析体验 。 - GitCode

一、技术原理

  1. MediaPipe 原理:MediaPipe 是一款由谷歌开发的跨平台机器学习框架,在人脸和手势关键点检测方面表现出色。它通过一系列的机器学习模型和算法,对输入的图像或视频流进行处理。对于人脸检测,MediaPipe 利用其预训练的人脸检测模型,能够快速准确地定位人脸在图像中的位置。接着,通过人脸关键点检测模型,基于深度学习算法学习人脸图像的特征,从而精确地预测出人脸的各个关键点,如眼睛、鼻子、嘴巴、脸颊等部位的关键点坐标,这些关键点能够完整地描述人脸的形状和姿态。对于手势检测,MediaPipe 同样依赖其预训练模型,分析手部的图像特征,识别出手部的各个关节点,并确定手势的姿态和关键点位置,进而实现对手势的理解和分析。
  2. YOLO 原理:YOLO(You Only Look Once)系列算法是当下流行的实时目标检测算法。其核心在于将输入图像划分为多个网格,每个网格负责预测目标的类别、位置和大小。在人脸和手势检测场景中,YOLO 模型通过在大量包含人脸和手势的图像数据集上进行训练,学习到人脸和手势的特征模式。当输入新的图像时,模型能够快速判断图像中是否存在人脸或手势,并预测出它们的边界框位置。为了进一步实现关键点检测,可结合其他基于深度学习的关键点检测算法,在检测到的人脸和手势区域内,精准预测出关键点的坐标。

二、 实现步骤

1.环境搭建

        1.使用Anaconda创建一个虚拟环境(建议使用Python3.6以上的环境)

conda create -n ZiTai python=3.8

        2.激活刚创建的虚拟环境

conda activate ZiTai

        3.安装PyTorch

pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118

        4.安装必要的库(open-cv,ultralytics,mediapipe)

pip install opencv - python mediapipe ultralytics

        5.在PyCharm中导入虚拟环境

 

        6.到此环境搭建已经结束了 

2.代码实现

        1.导入必要的库

import cv2
import mediapipe as mp
from ultralytics import YOLO
  • cv2:OpenCV 库,用于计算机视觉任务,如读取摄像头帧、绘制图形和显示图像。
  • mediapipe:Google 开发的跨平台框架,用于构建多模式机器学习应用程序,这里用于手部和面部关键点检测。
  • YOLO:来自ultralytics库,用于加载和运行 YOLO(You Only Look Once)目标检测模型。

        2. 定义常量

YOLO_MODEL_PATH = "GesTure.pt"
GESTURE_BASE_DISTANCE = 0.3
HAND_MAX_NUM = 2
HAND_MIN_DETECTION_CONFIDENCE = 0.5
HAND_MIN_TRACKING_CONFIDENCE = 0.5
FACE_MAX_NUM = 1
FACE_MIN_DETECTION_CONFIDENCE = 0.5
FACE_MIN_TRACKING_CONFIDENCE = 0.5
TEXT_FONT = cv2.FONT_HERSHEY_SIMPLEX
TEXT_SCALE = 1
TEXT_COLOR = (0, 0, 255)
TEXT_THICKNESS = 2
TEXT_POSITION = (50, 50)
EXIT_KEY = ord('q')
HAND_DRAWING_SPEC_1 = mp.solutions.drawing_utils.DrawingSpec(color=(255, 0, 0), thickness=2, circle_radius=2)
HAND_DRAWING_SPEC_2 = mp.solutions.drawing_utils.DrawingSpec(color=(0, 255, 0), thickness=2)
FACE_DRAWING_SPEC_1 = mp.solutions.drawing_utils.DrawingSpec(color=(0, 255, 0), thickness=1, circle_radius=1)
FACE_DRAWING_SPEC_2 = mp.solutions.drawing_utils.DrawingSpec(color=(0, 255, 255), thickness=1)
  • 这些常量定义了模型路径、检测参数、文本显示样式、退出键以及绘制手部和面部关键点的样式。

        3. 加载 YOLO 模型

def load_yolo_model(model_path):try:return YOLO(model_path)except Exception as e:print(f"Failed to load YOLO model: {e}")raise
  • 该函数尝试加载指定路径的 YOLO 模型,如果加载失败,会打印错误信息并抛出异常。

        4. 摄像头捕获类

class CameraCapture:def __init__(self):self.cap = cv2.VideoCapture(0)if not self.cap.isOpened():print("Failed to open camera")raise Exception("Camera could not be opened.")def __enter__(self):return self.capdef __exit__(self, exc_type, exc_val, exc_tb):if self.cap.isOpened():self.cap.release()
  • __init__:初始化摄像头捕获对象,如果无法打开摄像头,会打印错误信息并抛出异常。
  • __enter__:实现上下文管理器的进入方法,返回摄像头捕获对象。
  • __exit__:实现上下文管理器的退出方法,释放摄像头资源。

        5. 计算两点之间的距离

def distance(m, n):return ((n.x - m.x) ** 2 + (n.y - m.y) ** 2) ** 0.5
  • 该函数接受两个点mn,返回它们之间的欧几里得距离。

        6.  手势检测函数

def detect_gesture(handLms):distance_0_8 = distance(handLms.landmark[0], handLms.landmark[8])distance_0_12 = distance(handLms.landmark[0], handLms.landmark[12])distance_0_16 = distance(handLms.landmark[0], handLms.landmark[16])distance_0_20 = distance(handLms.landmark[0], handLms.landmark[20])gesture = "One"if distance_0_8 >= GESTURE_BASE_DISTANCE and distance_0_12 >= GESTURE_BASE_DISTANCE and \distance_0_16 < GESTURE_BASE_DISTANCE and distance_0_20 < GESTURE_BASE_DISTANCE:gesture = "Scissor"elif distance_0_8 >= GESTURE_BASE_DISTANCE and distance_0_12 >= GESTURE_BASE_DISTANCE and \distance_0_16 >= GESTURE_BASE_DISTANCE and distance_0_20 >= GESTURE_BASE_DISTANCE:gesture = "Paper"elif distance_0_8 < GESTURE_BASE_DISTANCE and distance_0_12 < GESTURE_BASE_DISTANCE and \distance_0_16 < GESTURE_BASE_DISTANCE and distance_0_20 < GESTURE_BASE_DISTANCE:gesture = "Rock"return gesture
  • 该函数根据手部关键点之间的距离判断手势,返回相应的手势名称。

        7. 面部网格检测函数

def face_mesh_detection(image, face_mesh, mp_drawing, mp_face_mesh):results = face_mesh.process(image)if results.multi_face_landmarks:for face_landmarks in results.multi_face_landmarks:mp_drawing.draw_landmarks(image, face_landmarks, mp_face_mesh.FACEMESH_CONTOURS,FACE_DRAWING_SPEC_1,FACE_DRAWING_SPEC_2)return image

        8.主函数

def main():try:model = load_yolo_model(YOLO_MODEL_PATH)myDraw = mp.solutions.drawing_utilsmpHands = mp.solutions.handshands = mpHands.Hands(static_image_mode=False,max_num_hands=HAND_MAX_NUM,min_detection_confidence=HAND_MIN_DETECTION_CONFIDENCE,min_tracking_confidence=HAND_MIN_TRACKING_CONFIDENCE)mp_face_mesh = mp.solutions.face_meshface_mesh = mp_face_mesh.FaceMesh(static_image_mode=False,max_num_faces=FACE_MAX_NUM,min_detection_confidence=FACE_MIN_DETECTION_CONFIDENCE,min_tracking_confidence=FACE_MIN_TRACKING_CONFIDENCE)mp_drawing = mp.solutions.drawing_utilswith CameraCapture() as cap:while True:success, frame = cap.read()if not success:print("Failed to read frame from camera.")breakresults = model.predict(source=frame, device=0)annotated_frame = results[0].plot(line_width=2)for result in results:boxes = result.boxesfor box in boxes:cls = int(box.cls[0])conf = float(box.conf[0])x1, y1, x2, y2 = map(int, box.xyxy[0])label = f"{result.names[cls]} {conf:.2f}"cv2.putText(annotated_frame, label, (x1, y1 - 10), TEXT_FONT, 0.5, TEXT_COLOR, 1)results_hands = hands.process(frame)if results_hands.multi_hand_landmarks:for handLms in results_hands.multi_hand_landmarks:gesture = detect_gesture(handLms)cv2.putText(annotated_frame, gesture, TEXT_POSITION, TEXT_FONT, TEXT_SCALE, TEXT_COLOR, TEXT_THICKNESS)myDraw.draw_landmarks(annotated_frame, handLms, mpHands.HAND_CONNECTIONS,HAND_DRAWING_SPEC_1,HAND_DRAWING_SPEC_2)annotated_frame = face_mesh_detection(annotated_frame, face_mesh, mp_drawing, mp_face_mesh)cv2.imshow('Combined Detection', annotated_frame)# 通过按下指定键退出循环if cv2.waitKey(1) & 0xFF == EXIT_KEY:breakexcept Exception as e:import tracebackprint(f"An error occurred: {e}")traceback.print_exc()finally:cv2.destroyAllWindows()if 'hands' in locals():hands.close()if 'face_mesh' in locals():face_mesh.close()
  • 加载 YOLO 模型、初始化手部和面部检测对象。
  • 使用CameraCapture上下文管理器打开摄像头。
  • 循环读取摄像头帧,进行目标检测、手势检测和面部网格检测。
  • 在帧上绘制检测结果,并显示处理后的帧。
  • 按下指定键(q)退出循环。
  • 捕获并处理异常,最后释放资源,关闭窗口。

        9.  程序入口

if __name__ == "__main__":main()
  • 确保代码作为脚本运行时,调用main函数

3.完整代码

import cv2
import mediapipe as mp
from ultralytics import YOLOYOLO_MODEL_PATH = "GesTure.pt"
GESTURE_BASE_DISTANCE = 0.3
HAND_MAX_NUM = 2
HAND_MIN_DETECTION_CONFIDENCE = 0.5
HAND_MIN_TRACKING_CONFIDENCE = 0.5
FACE_MAX_NUM = 1
FACE_MIN_DETECTION_CONFIDENCE = 0.5
FACE_MIN_TRACKING_CONFIDENCE = 0.5
TEXT_FONT = cv2.FONT_HERSHEY_SIMPLEX
TEXT_SCALE = 1
TEXT_COLOR = (0, 0, 255)
TEXT_THICKNESS = 2
TEXT_POSITION = (50, 50)
EXIT_KEY = ord('q')
HAND_DRAWING_SPEC_1 = mp.solutions.drawing_utils.DrawingSpec(color=(255, 0, 0), thickness=2, circle_radius=2)
HAND_DRAWING_SPEC_2 = mp.solutions.drawing_utils.DrawingSpec(color=(0, 255, 0), thickness=2)
FACE_DRAWING_SPEC_1 = mp.solutions.drawing_utils.DrawingSpec(color=(0, 255, 0), thickness=1, circle_radius=1)
FACE_DRAWING_SPEC_2 = mp.solutions.drawing_utils.DrawingSpec(color=(0, 255, 255), thickness=1)def load_yolo_model(model_path):try:return YOLO(model_path)except Exception as e:print(f"Failed to load YOLO model: {e}")raiseclass CameraCapture:def __init__(self):self.cap = cv2.VideoCapture(0)if not self.cap.isOpened():print("Failed to open camera")raise Exception("Camera could not be opened.")def __enter__(self):return self.capdef __exit__(self, exc_type, exc_val, exc_tb):if self.cap.isOpened():self.cap.release()def distance(m, n):return ((n.x - m.x) ** 2 + (n.y - m.y) ** 2) ** 0.5def detect_gesture(handLms):distance_0_8 = distance(handLms.landmark[0], handLms.landmark[8])distance_0_12 = distance(handLms.landmark[0], handLms.landmark[12])distance_0_16 = distance(handLms.landmark[0], handLms.landmark[16])distance_0_20 = distance(handLms.landmark[0], handLms.landmark[20])gesture = "One"if distance_0_8 >= GESTURE_BASE_DISTANCE and distance_0_12 >= GESTURE_BASE_DISTANCE and \distance_0_16 < GESTURE_BASE_DISTANCE and distance_0_20 < GESTURE_BASE_DISTANCE:gesture = "Scissor"elif distance_0_8 >= GESTURE_BASE_DISTANCE and distance_0_12 >= GESTURE_BASE_DISTANCE and \distance_0_16 >= GESTURE_BASE_DISTANCE and distance_0_20 >= GESTURE_BASE_DISTANCE:gesture = "Paper"elif distance_0_8 < GESTURE_BASE_DISTANCE and distance_0_12 < GESTURE_BASE_DISTANCE and \distance_0_16 < GESTURE_BASE_DISTANCE and distance_0_20 < GESTURE_BASE_DISTANCE:gesture = "Rock"return gesturedef face_mesh_detection(image, face_mesh, mp_drawing, mp_face_mesh):results = face_mesh.process(image)if results.multi_face_landmarks:for face_landmarks in results.multi_face_landmarks:mp_drawing.draw_landmarks(image, face_landmarks, mp_face_mesh.FACEMESH_CONTOURS,FACE_DRAWING_SPEC_1,FACE_DRAWING_SPEC_2)return imagedef main():try:model = load_yolo_model(YOLO_MODEL_PATH)myDraw = mp.solutions.drawing_utilsmpHands = mp.solutions.handshands = mpHands.Hands(static_image_mode=False,max_num_hands=HAND_MAX_NUM,min_detection_confidence=HAND_MIN_DETECTION_CONFIDENCE,min_tracking_confidence=HAND_MIN_TRACKING_CONFIDENCE)mp_face_mesh = mp.solutions.face_meshface_mesh = mp_face_mesh.FaceMesh(static_image_mode=False,max_num_faces=FACE_MAX_NUM,min_detection_confidence=FACE_MIN_DETECTION_CONFIDENCE,min_tracking_confidence=FACE_MIN_TRACKING_CONFIDENCE)mp_drawing = mp.solutions.drawing_utilswith CameraCapture() as cap:while True:success, frame = cap.read()if not success:print("Failed to read frame from camera.")breakresults = model.predict(source=frame, device=0)annotated_frame = results[0].plot(line_width=2)for result in results:boxes = result.boxesfor box in boxes:cls = int(box.cls[0])conf = float(box.conf[0])x1, y1, x2, y2 = map(int, box.xyxy[0])label = f"{result.names[cls]} {conf:.2f}"cv2.putText(annotated_frame, label, (x1, y1 - 10), TEXT_FONT, 0.5, TEXT_COLOR, 1)results_hands = hands.process(frame)if results_hands.multi_hand_landmarks:for handLms in results_hands.multi_hand_landmarks:gesture = detect_gesture(handLms)cv2.putText(annotated_frame, gesture, TEXT_POSITION, TEXT_FONT, TEXT_SCALE, TEXT_COLOR, TEXT_THICKNESS)myDraw.draw_landmarks(annotated_frame, handLms, mpHands.HAND_CONNECTIONS,HAND_DRAWING_SPEC_1,HAND_DRAWING_SPEC_2)annotated_frame = face_mesh_detection(annotated_frame, face_mesh, mp_drawing, mp_face_mesh)cv2.imshow('Combined Detection', annotated_frame)# 通过按下指定键退出循环if cv2.waitKey(1) & 0xFF == EXIT_KEY:breakexcept Exception as e:import tracebackprint(f"An error occurred: {e}")traceback.print_exc()finally:cv2.destroyAllWindows()if 'hands' in locals():hands.close()if 'face_mesh' in locals():face_mesh.close()if __name__ == "__main__":main()

三、总结

        作者已将源码和预测试模型文件上传至GitCode仓库,链接在文章顶端,有何问题可以发在评论区,感谢各读者阅读。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/69829.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA篇12 —— 泛型的使用

​ 欢迎来到我的主页&#xff1a;【Echo-Nie】 本篇文章收录于专栏【JAVA学习】 如果这篇文章对你有帮助&#xff0c;希望点赞收藏加关注啦~ 1 泛型介绍 先对集合进行说明&#xff0c;不能对加入到集合中的元素类型进行约束&#xff08;不安全&#xff09;。遍历的时候需要…

JavaScript 数据类型

基本概念 什么是数据类型 JavaScript是一种 灵活的动态类型语言 &#xff0c;其数据类型构成了程序的基础构建块。它主要包括两类数据类型&#xff1a; 原始数据类型 &#xff1a;包括String、Number、Boolean、Undefined、Null和Symbol。 复杂数据类型 &#xff1a;以Object…

被裁与人生的意义--春节随想

还有两个月就要被迫离开工作了十多年的公司了&#xff0c;不过有幸安安稳稳的过了一个春节&#xff0c;很知足! 我是最后一批要离开的&#xff0c;一百多号同事都没“活到”蛇年。看着一批批仁人志士被“秋后斩首”&#xff0c;马上轮到我们十来个&#xff0c;个中滋味很难言清…

【multi-agent-system】ubuntu24.04 安装uv python包管理器及安装依赖

uv包管理器是跨平台的 参考sudo apt-get update sudo apt-get install -y build-essential我的开发环境是ubuntu24.04 (base) root@k8s-master-pfsrv:/home/zhangbin/perfwork/01_ai/08_multi-agent-system# uv venv 找不到命令 “uv”,但可以通过以下软件

Redis代金卷(优惠卷)秒杀案例-多应用版

Redis代金卷(优惠卷)秒杀案例-单应用版-CSDN博客 上面这种方案,在多应用时候会出现问题,原因是你通过用户ID加锁 但是在多应用情况下,会出现两个应用的用户都有机会进去 让多个JVM使用同一把锁 这样就需要使用分布式锁 每个JVM都会有一个锁监视器,多个JVM就会有多个锁监视器…

Makefile 教程(一)——基础

本文裁剪汇总自Makefile教程和示例指南。 Makefile 意义 Makefile 用于帮助决定大型程序的哪些部分需要重新编译。在绝大多数情况下&#xff0c;都会编译 C 或 C 文件。其他语言通常有自己的与 Make 功能类似的工具。Make 也可以在编译之外使用&#xff0c;即当需要根据已更改…

绘制决策树尝试3

目录 代码解读AI 随机状态 种子 定义决策树回归模型 tree的decision regressor fit 还可用来预测 export 效果图 我的X只有一个特征 为何这么多分支 &#xff1f;&#xff1f;&#xff1f; 这是CART回归 CART回归 为什么说代码是CART回归&#xff1f; 不是所有的决…

为大模型提供webui界面的利器:Open WebUI 完全本地离线部署deepseek r1

为大模型提供webui界面的利器&#xff1a;Open WebUI Open WebUI的官网&#xff1a;&#x1f3e1; Home | Open WebUI 开源代码&#xff1a;WeTab 新标签页 Open WebUI是一个可扩展、功能丰富、用户友好的自托管AI平台&#xff0c;旨在完全离线运行。它支持各种LLM运行程序&am…

分布式微服务系统架构第87集:kafka

Kafka 就是为了解决上述问题而设计的一款基于发布与订阅的消息系统。它一般被称为 “分布式提交日志”或者“分布式流平台”。文件系统或数据库提交日志用来提供所有事务 的持久记录&#xff0c;通过重放这些日志可以重建系统的状态。同样地&#xff0c;Kafka 的数据是按照一定…

k均值聚类将数据分成多个簇

人工智能例子汇总&#xff1a;AI常见的算法和例子-CSDN博客 K-Means 聚类并将数据分成多个簇&#xff0c;可以使用以下方法&#xff1a; 实现思路 随机初始化 K 个聚类中心计算每个点到聚类中心的距离将点分配到最近的簇更新聚类中心重复上述过程直到收敛 完整代码&#x…

使用 Docker 部署 pSQL 服务器 的教程

如何使用 Edu 邮箱申请 Azure 订阅并开通免费 VPS 使用 Edu 邮箱不仅可以申请 Azure 的免费订阅来开通 VPS&#xff0c;还可以免费使用 Adobe 和 Notion 等软件&#xff0c;极大地提高学习和工作的效率。如果您还没有 Edu 邮箱&#xff0c;可以参考在线笔记s3.tebi.io/notes-i…

langchain 实现多智能体多轮对话

这里写目录标题 工具定义模型选择graph节点函数定义graph 运行 工具定义 import random from typing import Annotated, Literalfrom langchain_core.tools import tool from langchain_core.tools.base import InjectedToolCallId from langgraph.prebuilt import InjectedSt…

【Block总结】CPCA,通道优先卷积注意力|即插即用

论文信息 标题: Channel Prior Convolutional Attention for Medical Image Segmentation 论文链接: arxiv.org 代码链接: GitHub 创新点 本文提出了一种新的通道优先卷积注意力&#xff08;CPCA&#xff09;机制&#xff0c;旨在解决医学图像分割中存在的低对比度和显著…

Python从零构建macOS状态栏应用(仿ollama)并集成AI同款流式聊天 API 服务(含打包为独立应用)

在本教程中,我们将一步步构建一个 macOS 状态栏应用程序,并集成一个 Flask 服务器,提供流式响应的 API 服务。 如果你手中正好持有一台 MacBook Pro,又怀揣着搭建 AI 聊天服务的想法,却不知从何处迈出第一步,那么这篇文章绝对是你的及时雨。 最终,我们将实现以下功能: …

强化学习、深度学习、深度强化学习的区别是什么?

前言 深度强化学习就是 深度学习 和 强化学习 的结合体。它让计算机程序&#xff08;也就是智能体&#xff09;在特定环境中不断尝试&#xff0c;从错误中学习&#xff0c;最终找到最优的行动策略。 深度学习是AlphaGo从棋谱里学习&#xff0c;强化学些Alphazero 学习规则&am…

string类(详解)

为什么学习string类&#xff1f; 1.1 C语言中的字符串 C语言中&#xff0c;字符串是以\0结尾的一些字符的集合&#xff0c;为了操作方便&#xff0c;C标准库中提供了一些str系列的库函数&#xff0c;但是这些库函数与字符串是分离开的&#xff0c;不太符合OOP的思想&#xf…

工业相机如何获得更好的图像色彩

如何获得更好的图像色彩 大部分的工业自动化检测中对物体的色彩信息并不敏感&#xff0c;因此会使用黑白的相机&#xff0c;但是在显微镜成像、颜色分类识别等领域&#xff0c;相机的色彩还原就显得格外重要&#xff0c;在调节相机色彩方面的参数时&#xff0c;有以下几个方面需…

五.简单函数

五.简单函数 函数是什么&#xff1f; 函数是 一种将输入值映射到唯一输出值的对应关系 1。 在数学中&#xff0c;函数通常表示为 $y f&#xff08;x&#xff09;$&#xff0c;其中 $x$ 是自变量&#xff0c;$y$ 是因变量&#xff0c;$f$ 是对应法则2。 c中&#xff0c;函数是…

SQLite Update 语句详解

SQLite Update 语句详解 SQLite 是一款轻量级的数据库管理系统&#xff0c;以其简单、易用和高效的特点在全球范围内得到了广泛的应用。在 SQLite 中&#xff0c;UPDATE 语句是用于修改数据库表中记录的常用命令。本文将详细解析 SQLite 的 UPDATE 语句&#xff0c;包括其语法…

【Redis】set 和 zset 类型的介绍和常用命令

1. set 1.1 介绍 set 类型和 list 不同的是&#xff0c;存储的元素是无序的&#xff0c;并且元素不允许重复&#xff0c;Redis 除了支持集合内的增删查改操作&#xff0c;还支持多个集合取交集&#xff0c;并集&#xff0c;差集 1.2 常用命令 命令 介绍 时间复杂度 sadd …