当前位置: 首页 > article >正文

【计算机视觉】手势识别

手势识别是计算机视觉领域中的重要方向,通过对摄像机采集的手部相关的图像序列进行分析处理,进而识别其中的手势,手势被识别后用户就可以通过手势来控制设备或者与设备交互。完整的手势识别一般有手的检测和姿态估计、手部跟踪和手势识别等。

一、手掌检测

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() 从摄像头读取一帧图像并返回两个值:retframeret 是布尔值,表示图像是否成功读取,frame 是当前帧的图像。
  • 如果 retFalse,则说明读取图像失败,程序退出循环。
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.代码解释
  1. 初始化 MediaPipe 手部模型

    • 使用 mp.solutions.hands.Hands() 创建手部检测模型,min_detection_confidence=0.7min_tracking_confidence=0.5 表示最低的检测和追踪置信度阈值,适用于动态环境中。
  2. 打开摄像头

    • 使用 cv2.VideoCapture(0) 打开计算机的默认摄像头,并获取实时视频流。
  3. 图像转换

    • OpenCV 默认使用 BGR 色彩空间,但 MediaPipe 需要 RGB 色彩空间,因此使用 cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) 将图像转换为 RGB 格式。
  4. 处理图像并获取手部关键点

    • hands.process(rgb_frame) 用于处理图像并检测手部关键点。results 对象包含手部信息,如果检测到手部,results.multi_hand_landmarks 将返回手部的 21 个关键点的位置。
  5. 绘制关键点和连接线

    • mp_drawing.draw_landmarks(frame, landmarks, mp_hands.HAND_CONNECTIONS) 绘制手的 21 个关键点以及它们之间的连接线(即手指的骨架)。
    • landmarks.landmark 包含了每个关键点的 (x, y, z) 坐标,其中 xy 是图像中的像素坐标,z 是深度信息(在 3D 空间中的位置,但对于 2D 图像可忽略)。
  6. 显示关键点坐标

    • 对于每个关键点,通过 cv2.putText 在图像上显示关键点的索引。cv2.circle 用来在图像上绘制关键点位置。
  7. 显示视频流

    • 使用 cv2.imshow() 来显示处理过的每一帧图像,展示检测到的手部关键点。
  8. 退出条件

    • 按下 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 或深度学习的关键点检测模型)来进行手关键点估计。

  1. YOLO 检测手部:首先用 YOLO 模型检测图像中的手部位置,YOLO 会输出手部的边界框。
  2. 手部关键点估计:然后,我们可以通过一个手部关键点估计模型(如 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.代码解析
  1. 加载 YOLOv5 模型
    • torch.hub.load('ultralytics/yolov5', 'yolov5s') 载入 YOLOv5 模型,yolov5s 是一个小型的 YOLOv5 模型,适合实时应用。可以根据需求选择 yolov5myolov5l(更大的模型,精度更高但速度较慢)。
  2. 读取摄像头视频流
    • 使用 cv2.VideoCapture(0) 打开摄像头并读取每一帧图像。
  3. YOLOv5 物体检测
    • 使用 model(frame) 进行图像检测,返回一个 results 对象,其中包含检测到的边界框、类别标签、置信度等信息。
  4. 提取手部区域
    • 如果 YOLO 检测到手部(通过检测类别标号),提取手部的区域并将其转化为 RGB 格式(因为 MediaPipe 需要 RGB 输入)。
  5. MediaPipe 手部关键点估计
    • 使用 hands.process(rgb_hand_region) 进行手部关键点估计,返回手部的关键点信息。
    • 使用 mp_drawing.draw_landmarks() 绘制手部的 21 个关键点和连接线。
  6. 结果显示
    • 将检测到的手部边界框、关键点及连接线显示在视频流上。
  7. 退出条件
    • 按下 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). 轻量级的, 非拥有…...