【计算机视觉】手势识别
手势识别是计算机视觉领域中的重要方向,通过对摄像机采集的手部相关的图像序列进行分析处理,进而识别其中的手势,手势被识别后用户就可以通过手势来控制设备或者与设备交互。完整的手势识别一般有手的检测和姿态估计、手部跟踪和手势识别等。
一、手掌检测
import cv2
import mediapipe as mp# 初始化 MediaPipe 手部模型
mp_hands = mp.solutions.hands
hands = mp_hands.Hands()# 初始化视频流
cap = cv2.VideoCapture(0)while True:ret, frame = cap.read()if not ret:break# 转换为 RGBrgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)# 获取手部关键点results = hands.process(rgb_frame)# 如果检测到手部if results.multi_hand_landmarks:for landmarks in results.multi_hand_landmarks:# 绘制手部关键点mp.solutions.drawing_utils.draw_landmarks(frame, landmarks, mp_hands.HAND_CONNECTIONS)# 显示图像cv2.imshow('Hand Detection', frame)# 按 'q' 键退出if cv2.waitKey(1) & 0xFF == ord('q'):break# 释放资源
cap.release()
cv2.destroyAllWindows()
这段代码是一个简单的手部检测应用程序,使用了 OpenCV 和 MediaPipe 库来实时检测和绘制手部关键点。下面是对代码的详细解释:
1. 导入必要的库
import cv2
import mediapipe as mp
cv2是 OpenCV 的 Python 接口库,用于图像处理和计算机视觉任务。mediapipe是 Google 提供的一个跨平台框架,用于实现高效的计算机视觉任务,这里用它来做手部关键点检测。
2. 初始化 MediaPipe 手部模型
mp_hands = mp.solutions.hands
hands = mp_hands.Hands()
mp_hands是 MediaPipe 提供的手部检测模块。通过mp.solutions.hands访问。hands = mp_hands.Hands()创建了一个Hands对象,用于进行手部检测。它会自动处理图像中的手部检测、手部关键点识别和跟踪。
3. 初始化视频流
cap = cv2.VideoCapture(0)
cv2.VideoCapture(0)打开了计算机的默认摄像头(0表示第一个摄像头)。返回的cap对象用于读取视频流。
4. 开始处理视频流
while True:ret, frame = cap.read()if not ret:break
cap.read()从摄像头读取一帧图像并返回两个值:ret和frame。ret是布尔值,表示图像是否成功读取,frame是当前帧的图像。- 如果
ret为False,则说明读取图像失败,程序退出循环。
5. 转换图像为 RGB
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
- OpenCV 使用 BGR(蓝绿红)色彩空间,而 MediaPipe 要求输入图像为 RGB(红绿蓝)色彩空间。因此,我们用
cv2.cvtColor将图像从 BGR 转换为 RGB。
6. 处理图像以检测手部关键点
results = hands.process(rgb_frame)
hands.process(rgb_frame)将 RGB 图像传递给 MediaPipe 的Hands模型进行处理。results包含了检测到的手部信息,包括手部关键点的位置。如果图像中没有手部,results.multi_hand_landmarks会是空的。
7. 绘制手部关键点
if results.multi_hand_landmarks:for landmarks in results.multi_hand_landmarks:mp.solutions.drawing_utils.draw_landmarks(frame, landmarks, mp_hands.HAND_CONNECTIONS)
results.multi_hand_landmarks是一个包含所有检测到的手的关键点位置的列表。如果检测到手部,它会返回一个非空列表。landmarks是每个手部的关键点集合,每个关键点是一个(x, y, z)坐标。mp.solutions.drawing_utils.draw_landmarks(frame, landmarks, mp_hands.HAND_CONNECTIONS)将每个手的关键点绘制到frame图像上,并且连接关键点,形成手的骨架结构。mp_hands.HAND_CONNECTIONS用于连接不同的关键点。
8. 显示处理后的图像
cv2.imshow('Hand Detection', frame)
cv2.imshow显示处理后的图像(frame)。窗口的标题是 ‘Hand Detection’。
9. 按键退出
if cv2.waitKey(1) & 0xFF == ord('q'):break
cv2.waitKey(1)等待键盘输入,1表示等待 1 毫秒。返回值是按下键的 ASCII 码。- 如果按下
q键,ord('q')的值与cv2.waitKey(1)返回值相等,程序就会退出循环,停止视频流。
10. 释放资源并关闭窗口
cap.release()
cv2.destroyAllWindows()
cap.release()释放摄像头资源。cv2.destroyAllWindows()关闭所有 OpenCV 显示的窗口。
二、手关键点估计
要进行手关键点估计,可以使用 MediaPipe 库来进行高效的手部检测,结合 OpenCV 来进行图像处理和显示。这里将展示一个基于 MediaPipe 手部模型的手关键点估计的完整代码。
MediaPipe 提供了一个预训练的模型来检测手部的 21 个关键点,包括手指关节和手掌部位。我们将使用 MediaPipe 提供的 Hands 模块来检测手部关键点。
import cv2
import mediapipe as mp# 初始化 MediaPipe 手部检测模型
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(min_detection_confidence=0.7, min_tracking_confidence=0.5)
mp_drawing = mp.solutions.drawing_utils# 打开摄像头
cap = cv2.VideoCapture(0)while True:# 读取每一帧图像ret, frame = cap.read()if not ret:print("无法获取视频帧")break# 将图像转换为 RGB 格式,MediaPipe 需要 RGB 输入rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)# 获取手部关键点检测结果results = hands.process(rgb_frame)# 如果检测到手部if results.multi_hand_landmarks:for landmarks in results.multi_hand_landmarks:# 绘制手部关键点和连接线mp_drawing.draw_landmarks(frame, landmarks, mp_hands.HAND_CONNECTIONS)# 获取并显示每个关键点的坐标for idx, landmark in enumerate(landmarks.landmark):h, w, c = frame.shapecx, cy = int(landmark.x * w), int(landmark.y * h)cv2.putText(frame, str(idx), (cx, cy), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1, cv2.LINE_AA)cv2.circle(frame, (cx, cy), 5, (0, 0, 255), -1) # 绘制红色的关键点# 显示图像cv2.imshow('Hand Keypoint Estimation', frame)# 按 'q' 键退出if cv2.waitKey(1) & 0xFF == ord('q'):break# 释放摄像头资源并关闭窗口
cap.release()
cv2.destroyAllWindows()
1.代码解释
-
初始化 MediaPipe 手部模型:
- 使用
mp.solutions.hands.Hands()创建手部检测模型,min_detection_confidence=0.7和min_tracking_confidence=0.5表示最低的检测和追踪置信度阈值,适用于动态环境中。
- 使用
-
打开摄像头:
- 使用
cv2.VideoCapture(0)打开计算机的默认摄像头,并获取实时视频流。
- 使用
-
图像转换:
- OpenCV 默认使用 BGR 色彩空间,但 MediaPipe 需要 RGB 色彩空间,因此使用
cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)将图像转换为 RGB 格式。
- OpenCV 默认使用 BGR 色彩空间,但 MediaPipe 需要 RGB 色彩空间,因此使用
-
处理图像并获取手部关键点:
hands.process(rgb_frame)用于处理图像并检测手部关键点。results对象包含手部信息,如果检测到手部,results.multi_hand_landmarks将返回手部的 21 个关键点的位置。
-
绘制关键点和连接线:
mp_drawing.draw_landmarks(frame, landmarks, mp_hands.HAND_CONNECTIONS)绘制手的 21 个关键点以及它们之间的连接线(即手指的骨架)。landmarks.landmark包含了每个关键点的(x, y, z)坐标,其中x和y是图像中的像素坐标,z是深度信息(在 3D 空间中的位置,但对于 2D 图像可忽略)。
-
显示关键点坐标:
- 对于每个关键点,通过
cv2.putText在图像上显示关键点的索引。cv2.circle用来在图像上绘制关键点位置。
- 对于每个关键点,通过
-
显示视频流:
- 使用
cv2.imshow()来显示处理过的每一帧图像,展示检测到的手部关键点。
- 使用
-
退出条件:
- 按下
q键退出程序并释放摄像头资源。
- 按下
2.手部关键点索引
MediaPipe 的 Hands 模型检测手部的 21 个关键点,索引如下(从 0 到 20):
- 0: 手腕
- 1: 大拇指根部
- 2: 大拇指第一关节
- 3: 大拇指第二关节
- 4: 大拇指尖端
- 5: 食指根部
- 6: 食指第一关节
- 7: 食指第二关节
- 8: 食指尖端
- 9: 中指根部
- 10: 中指第一关节
- 11: 中指第二关节
- 12: 中指尖端
- 13: 无名指根部
- 14: 无名指第一关节
- 15: 无名指第二关节
- 16: 无名指尖端
- 17: 小指根部
- 18: 小指第一关节
- 19: 小指第二关节
- 20: 小指尖端
三、实例
YOLO(You Only Look Once)是一个非常强大的目标检测算法,特别适用于实时应用。它将目标检测任务转化为一个回归问题,能够快速且准确地检测图像中的目标物体。虽然 YOLO 本身并没有直接针对手部关键点估计的功能,但可以用它来检测手部区域,然后结合其他模型(比如 MediaPipe 或深度学习的关键点检测模型)来进行手关键点估计。
- YOLO 检测手部:首先用 YOLO 模型检测图像中的手部位置,YOLO 会输出手部的边界框。
- 手部关键点估计:然后,我们可以通过一个手部关键点估计模型(如 MediaPipe 或自定义深度学习模型)来进一步估计手部的 21 个关键点。
import cv2
import torch
import mediapipe as mp# 初始化 MediaPipe 手部检测模型
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(min_detection_confidence=0.7, min_tracking_confidence=0.5)
mp_drawing = mp.solutions.drawing_utils# 加载 YOLOv5 模型(选择合适的模型大小)
model = torch.hub.load('ultralytics/yolov5', 'yolov5s') # 'yolov5s' 是一个小型的 YOLOv5 模型# 打开摄像头
cap = cv2.VideoCapture(0)while True:# 读取每一帧图像ret, frame = cap.read()if not ret:print("无法获取视频帧")break# 使用 YOLOv5 检测图像中的物体(包括手部)results = model(frame) # 检测结果,包括边界框、标签、置信度等# 提取 YOLOv5 检测到的手部(通常手部被标记为 0 或其他标签,依赖于训练数据)# 获取所有检测到的物体的边界框hands_detections = results.xyxy[0] # 获取检测结果,xyxy 形式 [x_min, y_min, x_max, y_max, confidence, class]for detection in hands_detections:if detection[5] == 0: # 类别 0 代表手部(具体根据训练数据集而定)x_min, y_min, x_max, y_max = map(int, detection[:4])# 在图像上绘制手部边界框cv2.rectangle(frame, (x_min, y_min), (x_max, y_max), (255, 0, 0), 2)# 提取手部区域并进行手部关键点估计hand_region = frame[y_min:y_max, x_min:x_max]rgb_hand_region = cv2.cvtColor(hand_region, cv2.COLOR_BGR2RGB)# 使用 MediaPipe 估计手部关键点hand_results = hands.process(rgb_hand_region)# 如果检测到手部关键点if hand_results.multi_hand_landmarks:for landmarks in hand_results.multi_hand_landmarks:# 绘制手部关键点和连接线mp_drawing.draw_landmarks(frame, landmarks, mp_hands.HAND_CONNECTIONS)for idx, landmark in enumerate(landmarks.landmark):h, w, c = frame.shapecx, cy = int(landmark.x * w), int(landmark.y * h)cv2.putText(frame, str(idx), (cx, cy), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1, cv2.LINE_AA)cv2.circle(frame, (cx, cy), 5, (0, 0, 255), -1) # 绘制红色的关键点# 显示图像cv2.imshow('Hand Detection and Keypoint Estimation', frame)# 按 'q' 键退出if cv2.waitKey(1) & 0xFF == ord('q'):break# 释放摄像头资源并关闭窗口
cap.release()
cv2.destroyAllWindows()
1.代码解析
- 加载 YOLOv5 模型:
torch.hub.load('ultralytics/yolov5', 'yolov5s')载入 YOLOv5 模型,yolov5s是一个小型的 YOLOv5 模型,适合实时应用。可以根据需求选择yolov5m或yolov5l(更大的模型,精度更高但速度较慢)。
- 读取摄像头视频流:
- 使用
cv2.VideoCapture(0)打开摄像头并读取每一帧图像。
- 使用
- YOLOv5 物体检测:
- 使用
model(frame)进行图像检测,返回一个results对象,其中包含检测到的边界框、类别标签、置信度等信息。
- 使用
- 提取手部区域:
- 如果 YOLO 检测到手部(通过检测类别标号),提取手部的区域并将其转化为 RGB 格式(因为 MediaPipe 需要 RGB 输入)。
- MediaPipe 手部关键点估计:
- 使用
hands.process(rgb_hand_region)进行手部关键点估计,返回手部的关键点信息。 - 使用
mp_drawing.draw_landmarks()绘制手部的 21 个关键点和连接线。
- 使用
- 结果显示:
- 将检测到的手部边界框、关键点及连接线显示在视频流上。
- 退出条件:
- 按下
q键退出程序。
- 按下
相关文章:
【计算机视觉】手势识别
手势识别是计算机视觉领域中的重要方向,通过对摄像机采集的手部相关的图像序列进行分析处理,进而识别其中的手势,手势被识别后用户就可以通过手势来控制设备或者与设备交互。完整的手势识别一般有手的检测和姿态估计、手部跟踪和手势识别等。…...
装饰器模式的C++实现示例
核心思想 装饰器设计模式是一种结构型设计模式,它允许动态地为对象添加额外的行为或职责,而无需修改其原始类。装饰器模式通过创建一个装饰器类来包装原始对象,并在保持原始对象接口一致性的前提下,扩展其功能。 装饰器模式的核…...
Python+DeepSeek:开启AI编程新次元——从自动化到智能创造的实战指南
文章核心价值 技术热点:结合全球最流行的编程语言与国产顶尖AI模型实用场景:覆盖代码开发/数据分析/办公自动化等高频需求流量密码:揭秘大模型在编程中的创造性应用目录结构 环境搭建:5分钟快速接入DeepSeek场景一:AI辅助代码开发(智能补全+调试)场景二:数据分析超级助…...
25.3.12.Linux内核如何和设备树协同工作的?
1.编写设备树 cd arch/riscv/boot/dts/ 再cd到厂商,例如下述内容。 2.编译设备树(dts->dtb)通过dtc命令来转换 3.解析设备树 例如上述内容,都是对设备树的解析。 这里重点说一下内核对设备树的处理吧,因为这个内容是设备树的重点了。 从源代码文件 dts 文件开始...
python中路径操作简介
一、./的基础含义 当前目录 ./表示当前工作目录(Current Working Directory, CWD),即Python脚本运行时所在的目录。例如: open(./data.txt, r) # 打开当前目录下的data.txt文件 作用:避免直接写文件名可能引发的路…...
Flutter 基础组件 Text 详解
目录 1. 引言 2. 基本使用 3. 自定义样式 4. 文本对齐与溢出控制 5. 外边距 5.1 使用 Container 包裹 5.2 使用 Padding 组件 5.3 在 Row/Column 中使用 5.4 动态边距调整 5.5 关键区别说明 5.6 设置 margin 无效 6. 结论 相关推荐 1. 引言 Text 组件是 Flutter 中…...
Torch 模型 model => .onnx => .trt 及利用 TensorTR 在 C++ 下的模型部署教程
一、模型训练环境搭建和模型训练 模型训练环境搭建主要牵扯 Nvidia driver、Cuda、Cudnn、Anaconda、Torch 的安装,相关安装教程可以参考【StarCoder 微调《个人编程助手: 训练你自己的编码助手》】中 5.1 之前的章节。 模型训练的相关知识可以参考 Torch的编程方…...
FreeSWITCH 之 chat
要把 FreeSWITCH 之 chat 完全研究清楚,似乎不容易 发送,路由,接收 跟哪些模块有关 等等 咱一边查资料,一边整理,不着急 先看看 Kamalio 怎么发 MESSAGE loadmodule "uac.so"route[uac_send_message] {…...
如何在Spring Boot中配置和使用MyBatis-Plus
在当今的Java开发中,Spring Boot已经成为了一个非常流行的框架,而MyBatis-Plus则是一个强大的ORM框架,为开发人员提供了更简便的数据库操作方式。很多开发者都在使用Spring Boot和MyBatis-Plus的组合来快速构建高效的应用。今天就来聊聊如何在…...
爱普生可编程晶振SG-8200CJ特性与应用
在高速发展的电子技术领域,时钟源作为电子系统的“心脏”,其性能直接影响设备的稳定性与可靠性。爱普生SG-8200CJ可编程晶振凭借其优秀的频率精度、低抖动性能及广泛的环境适应性,正成为众多领域的得力之选,为各类设备的高效运行与…...
ubuntu中用docker下载opengauss
1.安装docker sudo apt install docker.io2.拉取opengauss镜像 sudo docker pull enmotech/opengauss3.创建容器 sudo docker run --name opengauss --privilegedtrue -d -e GS_PASSWORDEnmo123 enmotech/opengauss:latest3.5.如果容器停止运行(比如关机了&#…...
tslib
使用tslib来读取触摸屏的数据,可以得到原始数据,也可以在原始数据的基础上进行一些处理。比如有些触摸屏比较不稳定,跳动比较大,我们可以将跳动比较大的数据给删除掉 plugins里面的每个文件都会被编译成一个动态库,这些…...
MANUS怎么用
(1)分析方法论我过去说过一个分析模型:供给侧-消费侧。供给侧想做大,得靠生态集成。消费侧想坐大,得靠交互体验。(2)交互体验我先给大家讲一下计算机产业发展70来年,在交互上的变化。…...
Spring Cloud Alibaba 实战:Sentinel 保障微服务的高可用性与流量防护
1.1 Sentinel 作用 Sentinel 是阿里巴巴开源的一款 流量控制和熔断降级 框架,主要用于: 流量控制:限制 QPS,防止流量暴增导致系统崩溃熔断降级:当某个服务不可用时自动降级,避免故障扩散热点参数限流&…...
大数据技术在土地利用规划中的应用分析
大数据技术在土地利用规划中的应用分析 一、引言 土地利用规划是对一定区域内的土地开发、利用、整治和保护所作出的统筹安排与战略部署,对于实现土地资源的优化配置、保障社会经济的可持续发展具有关键意义。在当今数字化时代,大数据技术凭借其海量数据处理、高效信息挖掘等…...
MoonSharp 文档三
MoonSharp 文档一-CSDN博客 MoonSharp 文档二-CSDN博客 MoonSharp 文档四-CSDN博客 MoonSharp 文档五-CSDN博客 7.Proxy objects(代理对象) 如何封装你的实现,同时又为脚本提供一个有意义的对象模型 官方文档:MoonSharp 在实际…...
linux和windows之间的复制
第一步 sudo apt-get autoremove open-vm-tools第二步 sudo apt-get update第三步 sudo apt-get install open-vm-tools-desktop按y 第四步 重启虚拟机,终端下输入 rebootLinux下 按“ CtrlShiftC V ”复制粘贴 Windows下按“ Ctrl C V ”复制粘贴...
在资源有限中逆势突围:从抗战智谋到寒门高考的破局智慧
目录 引言 一、历史中的非对称作战:从李牧到八路军的智谋传承 李牧戍边:古代军事博弈中的资源重构 八路军的游击战:现代战争中的智慧延续 二、创业界的逆袭之道:小米与拼多多的资源重构 从MVP到杠杆解 社交裂变与资源错配 …...
Ubuntu 22.04 无法进入图形界面的解决方法
Ubuntu 22.04 无法进入图形界面,只能进入 tty,可能是由于图形界面相关的配置或驱动程序出现了问题。以下是一些常见的解决方法: 1. 检查图形界面服务状态 首先,检查图形界面服务(通常是 gdm 或 lightdm)的…...
Python中很常用的100个函数整理
Python 内置函数提供了强大的工具,涵盖数据处理、数学运算、迭代控制、类型转换等。本文总结了 100 个常用内置函数,并配备示例代码,提高编程效率。 1. abs() 取绝对值 print(abs(-10)) # 10 2. all() 判断所有元素是否为真 print(all([…...
javascript-es6 (六)
编程思想 面向过程 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次 调用就可以了 就是按照我们分析好了的步骤,按照步骤解决问题 面向对象 面向对象是把事务分解成为一个个对象&…...
大模型微调技术基础(一)
文章目录 GPT与BERT的差异GPT(Decoder架构)优点缺点 BERT(Encoder架构)优点缺点 总结 LoRA低参数大模型与全参数小模型表现对比分析LoRA(Low-Rank Adaptation)技术详解1. LoRA 核心原理2. 应用场景3. 简单代…...
Spring AI 1.0.0 M6新特性MCP
Spring AI 1.0.0 M6新特性MCP 前言一、MCP是什么?(Model Context Protocol)二、它的发展历程三、核心架构四、MCP Java SDK的核心能力Java MCP实现遵循三层架构:MCP客户端MCP服务器总结MCP 的核心能力总结多种传输选项 搭建服务端…...
【时时三省】(C语言基础)赋值表达式和赋值语句和变量赋初值
山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 赋值表达式和赋值语句 在C程序中,赋值语句是用得最多的语句。实际上,C语言的赋值语句属于表达式语句,由一个赋值表达式加一个分号组成。其他一些高级语言…...
Room数据库的使用
一、room的引用导入 1、在app的gradle中引入 plugins {//这个ksp 一定要对应相关的 kotlin 版本,不然会一直报错i的---id("com.google.devtools.ksp") version "1.9.0-1.0.13" apply false } 2、在model的gradle中引入 plugins {id("com.g…...
【性能测试入门_01性能测试jmeter基础实操场景详解】
一、应用项目如何部署在服务器上 可以将项目进行打jar包 双击install,控制台就会打印打包的过程 最终打的包,会存放在打印的那个路径下 这个jar包,就是开发人员开发好,直接可以部署的 可以通过命令,在终端直接启动这…...
SpringBoot加载配置文件的优先级
在 SpringBoot 应用中,配置文件的加载顺序(优先级)决定了不同来源的配置属性如何覆盖彼此,但是,在实践中,也会经常遇到。下面文章将分析 SpringBoot 配置文件加载的优先级,从高到低排列。 文章目…...
跨越时空的对话:图灵与GPT-4聊AI的前世今生
(背景:虚拟咖啡厅,图灵身着1950年代西装,端着一杯热茶,GPT-4以全息投影形态坐在对面) 图灵(喝了口茶):“听说你能写诗?我当年在布莱切利园破解Enigma时&…...
如何通过 Seatunnel 实现 MySQL 到 OceanBase的数据迁移同步
1. 准备传输工具 本方案采用 Apache Seatunnel(简称seatunnel)进行MySQL 到 OceanBase 的数据迁移和同步,出于对方案轻量性的考量,我们采用其内置的Zeta引擎来实现,包括全量同步、离线增量同步,以及CDC方案…...
C++20 新特性总结
简要总结 C20 引入了四项非常大的更新, 分别是: 概念(Concepts). 用来简化模板编程, 强化表达能力. 并且使得出错原因更容易查找.模块(Modules). 这是代码组织方面非常大的更新. 提供了新的方式来组织代码, 并且可以减少编译时间.范围库(Ranges and Views). 轻量级的, 非拥有…...
