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.rhkb.cn/news/11088.html

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

相关文章

学术总结Ai Agent中firecrawl(大模型爬虫平台)的超简单的docker安装方式教程

之前开源了学术总结ai agent&#xff0c;但是对非计算机专业来说&#xff0c;门槛有点高&#xff0c;再加上docker hub镜像被屏蔽&#xff0c;更是不容易上手啊。也有考虑用dify或者扣子去复刻一个&#xff0c;但是从专业用户的角度出发通过界面来拖拽配置实在是不高效&#xf…

交易股指期货有什么技巧吗?

交易股指期货有啥窍门呢&#xff1f;其实啊&#xff0c;追涨杀跌这招&#xff0c;虽然能挣点小钱&#xff0c;但风险也不小&#xff0c;一不小心就可能亏大了。我说的追涨杀跌&#xff0c;不是那种天天追着价格跑的小打小闹&#xff0c;而是要看大趋势&#xff0c;做宏观操作。…

Java线程认识和Object的一些方法ObjectMonitor

专栏系列文章地址&#xff1a;https://blog.csdn.net/qq_26437925/article/details/145290162 本文目标&#xff1a; 要对Java线程有整体了解&#xff0c;深入认识到里面的一些方法和Object对象方法的区别。认识到Java对象的ObjectMonitor&#xff0c;这有助于后面的Synchron…

linux 函数 sem_init () 信号量、sem_destroy()

&#xff08;1&#xff09; &#xff08;2&#xff09; 代码举例&#xff1a; #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> #include <unistd.h>sem_t semaphore;void* thread_function(void* arg) …

ComfyUI中For Loop的使用

研究了半天&#xff0c;终于弄明白了如何使用For Loop。 1、在For中节点&#xff0c;必须有输出连接到For Loop End的initial_value点&#xff0c;才能确保节点执行完毕后才 进入下一轮循环&#xff0c;否则&#xff0c;可能导致节点没执行完&#xff0c;就进入下一个循环了。…

UbuntuWindows双系统安装

做系统盘&#xff1a; Ubuntu20.04双系统安装详解&#xff08;内容详细&#xff0c;一文通关&#xff01;&#xff09;_ubuntu 20.04-CSDN博客 ubuntu系统调整大小&#xff1a; 调整指南&#xff1a; 虚拟机中的Ubuntu扩容及重新分区方法_ubuntu重新分配磁盘空间-CSDN博客 …

ASP.NET Core 启动并提供静态文件

ASP.NET Core 启动并提供静态文件 即是单个可执行文件&#xff0c;它既运行 API 项目&#xff0c;也托管 前端项目&#xff08;通常是前端的发布文件&#xff09;。 这种方式一般是通过将 前端项目 的发布文件&#xff08;例如 HTML、CSS、JavaScript&#xff09;放入 Web AP…

网络原理(3)—— 传输层详解

目录 一. 再谈端口号 二. UDP协议(用户数据报协议) 2.1 UDP协议端格式 2.2 UDP报文长度 2.3 UDP校验和 三. TCP协议(传输控制协议) 3.1 TCP协议段格式 3.2 核心机制 3.2.1 确认应答 —— “感知对方是否收到” 3.2.2 超时重传 3.3.3 连接管理 —— 三次握手与四…

【算法设计与分析】实验7:复杂装载及0/1背包问题的回溯法设计与求解

目录 一、实验目的 二、实验环境 三、实验内容 四、核心代码 五、记录与处理 六、思考与总结 七、完整报告和成果文件提取链接 一、实验目的 针对复杂装载问题、及0/1背包问题开展分析、建模、评价&#xff0c;算法设计与优化&#xff0c;并进行编码实践。 理解复杂装载…

oracle: 多表查询之联合查询[交集intersect, 并集union,差集minus]

把多个查询结果上下合并, 即, 通过操作符将多个 SELECT 语句的结果集合并为一个结果集。虽然联合查询通常用于从多个表中检索数据&#xff0c;但它也可以用于从同一个表中检索不同的数据集。 联合查询: 交集,并集,差集 默认的排序规则通常是基于查询结果集中的列的自然顺序。…

增删改查(CRUD)操作

文章目录 MySQL系列&#xff1a;1.CRUD简介2.Create(创建)2.1单行数据全列插入2.2 单行数据指定插入2.3 多⾏数据指定列插⼊ 3.Retrieve(读取)3.1 Select查询3.1.1 全列查询3.1.2 指定列查询3.1.3 查询字段为表达式&#xff08;都是临时表不会对原有表数据产生影响&#xff09;…

早期车主告诉后来者,很后悔买电车,一辈子都被车企拿捏了

从2015年开始大力发展电车&#xff0c;至今已有快10年了&#xff0c;头几批车主或是已换车&#xff0c;或是准备换车&#xff0c;他们用车这么多年的困扰以及换车的麻烦&#xff0c;却告诉准备买电车的消费者&#xff0c;电车没有媒体宣传的那么好&#xff0c;买了电车基本上一…

架构技能(四):需求分析

需求分析&#xff0c;即分析需求&#xff0c;分析软件用户需要解决的问题。 需求分析的下一环节是软件的整体架构设计&#xff0c;需求是输入&#xff0c;架构是输出&#xff0c;需求决定了架构。 决定架构的是软件的所有需求吗&#xff1f;肯定不是&#xff0c;真正决定架构…

H264原始码流格式分析

1.H264码流结构组成 H.264裸码流&#xff08;Raw Bitstream&#xff09;数据主要由一系列的NALU&#xff08;网络抽象层单元&#xff09;组成。每个NALU包含一个NAL头和一个RBSP&#xff08;原始字节序列载荷&#xff09;。 1.1 H.264码流层次 H.264码流的结构可以分为两个层…

pytorch生成对抗网络

人工智能例子汇总&#xff1a;AI常见的算法和例子-CSDN博客 生成对抗网络&#xff08;GAN&#xff0c;Generative Adversarial Network&#xff09;是一种深度学习模型&#xff0c;由两个神经网络组成&#xff1a;生成器&#xff08;Generator&#xff09;和判别器&#xff0…

AIGC技术中常提到的 “嵌入转换到同一个向量空间中”该如何理解

在AIGC&#xff08;人工智能生成内容&#xff09;技术中&#xff0c;“嵌入转换到同一个向量空间中”是一个核心概念&#xff0c;其主要目的是将不同类型的输入数据&#xff08;如文本、图像、音频等&#xff09;映射到一个统一的连续向量空间中&#xff0c;从而实现数据之间的…

芯片AI深度实战:给vim装上AI

系列文章&#xff1a; 芯片AI深度实战&#xff1a;私有模型deep seek r1&#xff0c;必会ollama-CSDN博客 芯片AI深度实战&#xff1a;自己的AI&#xff0c;必会LangChain-CSDN博客 芯片AI深度实战&#xff1a;给vim装上AI-CSDN博客 芯片AI深度实战&#xff1a;火的编程AI&…

汽车中控屏HMI界面,安全和便捷是设计的两大准则。

在汽车智能化的浪潮中&#xff0c;汽车中控屏 HMI&#xff08;Human - Machine Interface&#xff0c;人机交互界面&#xff09;界面已成为车辆与驾驶者沟通的关键桥梁。它不仅集成了众多车辆功能的控制&#xff0c;还承担着信息展示与交互的重任。而在其设计过程中&#xff0c…

书生大模型实战营3

文章目录 L0——入门岛git基础Git 是什么&#xff1f;Git 中的一些基本概念工作区、暂存区和 Git 仓库区文件状态分支主要功能 Git 平台介绍GitHubGitLabGitee Git 下载配置验证下载 Git配置 Git验证 Git配置 Git常用操作Git简易入门四部曲Git其他指令 闯关任务任务1: 破冰活动…

(9)下:学习与验证 linux 里的 epoll 对象里的 EPOLLIN、 EPOLLHUP 与 EPOLLRDHUP 的不同。小例子的实验

&#xff08;4&#xff09;本实验代码的蓝本&#xff0c;是伊圣雨老师里的课本里的代码&#xff0c;略加改动而来的。 以下是 服务器端的代码&#xff1a; 每当收到客户端的报文时&#xff0c;就测试一下对应的 epoll 事件里的事件标志&#xff0c;不读取报文内容&#xff0c;…