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

【python】OpenCV—Hand Detection

在这里插入图片描述

文章目录

  • 1、功能描述
  • 2、代码实现
  • 3、效果展示
  • 4、完整代码
  • 5、参考
  • 6、其它手部检测和手势识别的方案


更多有趣的代码示例,可参考【Programming】


1、功能描述

基于 opencv-python 和 mediapipe 进行手部检测

在这里插入图片描述

2、代码实现

导入必要的库函数

import cv2
import mediapipe as mp

进入主程序首先实例化 HandDetector() 类,读入图片,调用 find_hands 方法实现手部检测

if __name__ == "__main__":detector = HandDetector()img = cv2.imread("1.jpg")img, results = detector.find_hands(img)

HandDetector 类初始化如下,主要是配置好 mediapipe 的手部关键点检测算子以及可视化工具

class HandDetector:def __init__(self, static_mode=False, max_hands=2, detection_confidence=0.5, tracking_confidence=0.5):self.static_mode = static_modeself.max_hands = max_handsself.detection_confidence = detection_confidenceself.tracking_confidence = tracking_confidenceself.mp_hands = mp.solutions.handsself.hands = self.mp_hands.Hands(static_image_mode=static_mode,max_num_hands=max_hands,min_detection_confidence=detection_confidence,min_tracking_confidence=tracking_confidence)self.mp_drawing = mp.solutions.drawing_utilsself.mp_drawing_styles = mp.solutions.drawing_styles

find_hands 方法实现如下,用于检测手部关键点,并返回绘制后的图片(mediapipe绘制的)和检测结果

    def find_hands(self, img, draw=True):img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)self.results = self.hands.process(img_rgb)if self.results.multi_hand_landmarks and draw:for hand_landmarks in self.results.multi_hand_landmarks:self.mp_drawing.draw_landmarks(img,hand_landmarks,self.mp_hands.HAND_CONNECTIONS,self.mp_drawing_styles.get_default_hand_landmarks_style(),self.mp_drawing_styles.get_default_hand_connections_style())return img, self.results

接下来调用 find_positions 方法,根据手部关键点,找出手部检测框

    lm_list, bbox = detector.find_positions(img, hand_index=0)

find_positions 方法实现如下,遍历手部关键点,保存最大最小横纵坐标,在此基础上,外扩(w+h)/ 2 的一定比例,返回关键点列表和手部检测框

    def find_positions(self, img, hand_index=0):h, w, c = img.shapelandmark_list = []bbox = [0, 0, 0, 0]  # x_min, y_min, x_max, y_max# Check if any hands detectedif not self.results.multi_hand_landmarks:return landmark_list, bbox# Check if requested hand index existsif hand_index >= len(self.results.multi_hand_landmarks):return landmark_list, bbox# Extract hand landmarkshand = self.results.multi_hand_landmarks[hand_index]# Initialize bounding box coordinatesx_min, y_min = w, hx_max, y_max = 0, 0# Process each landmarkfor id, lm in enumerate(hand.landmark):# Convert normalized coordinates to pixel coordinatescx, cy, cz = int(lm.x * w), int(lm.y * h), lm.zlandmark_list.append([id, cx, cy, cz])# Update bounding boxx_min = min(x_min, cx)y_min = min(y_min, cy)x_max = max(x_max, cx)y_max = max(y_max, cy)# Add padding to bounding boxpadding = int((y_max - y_min + x_max - x_min) * 0.1 / 2)bbox = [max(0, x_min - padding),max(0, y_min - padding),min(w, x_max + padding),min(h, y_max + padding)]return landmark_list, bbox

如果检测出来了关键点,调用 get_hand_type 获取检测出来的是左手还是右手,调用 draw_bounding_box 方法绘制手部矩形框

    if lm_list:hand_type = detector.get_hand_type(0)img = detector.draw_bounding_box(img, bbox, hand_type)# 绘制某一个关键点# if len(lm_list) > 8:#     cv2.circle(img, (lm_list[8][1], lm_list[8][2]), 5, (255, 0, 255), cv2.FILLED)

get_hand_type方法实现如下,调用 mediapipe 的接口获取左手 or 右手

    def get_hand_type(self, idx=0):if not self.results.multi_hand_landmarks:return Noneif idx >= len(self.results.multi_handedness):return None# Get hand type from classificationhand_type = self.results.multi_handedness[idx].classification[0].labelreturn hand_type

draw_bounding_box 方法实现如下,绘制矩形框,写上左手 or 右手标签

    def draw_bounding_box(self, img, bbox, hand_label="Hand"):x_min, y_min, x_max, y_max = bboxcv2.rectangle(img, (x_min, y_min), (x_max, y_max), (0, 255, 0), 2)cv2.putText(img, hand_label, (x_min, y_min - 10),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)return img

最后,展示检测结果,保存检测结果,退出后关闭所有窗口

    cv2.imshow("Hand Detector", img)cv2.imwrite("result.jpg", img)cv2.waitKey(0)cv2.destroyAllWindows()

3、效果展示

输入图片

在这里插入图片描述

输出结果

在这里插入图片描述

需要绘制两个手的话改改代码

    detector = HandDetector()img = cv2.imread("2.jpg")img, results = detector.find_hands(img)for i in range(2):lm_list, bbox = detector.find_positions(img, hand_index=i)if lm_list:hand_type = detector.get_hand_type(i)img = detector.draw_bounding_box(img, bbox, hand_type)# 绘制某一个关键点# if len(lm_list) > 8:#     cv2.circle(img, (lm_list[8][1], lm_list[8][2]), 5, (255, 0, 255), cv2.FILLED)cv2.imshow("Hand Detector", img)cv2.imwrite("result.jpg", img)cv2.waitKey(0)cv2.destroyAllWindows()

输入图片

在这里插入图片描述

输出图片

在这里插入图片描述

4、完整代码

import cv2
import mediapipe as mpclass HandDetector:def __init__(self, static_mode=False, max_hands=2, detection_confidence=0.5, tracking_confidence=0.5):self.static_mode = static_modeself.max_hands = max_handsself.detection_confidence = detection_confidenceself.tracking_confidence = tracking_confidenceself.mp_hands = mp.solutions.handsself.hands = self.mp_hands.Hands(static_image_mode=static_mode,max_num_hands=max_hands,min_detection_confidence=detection_confidence,min_tracking_confidence=tracking_confidence)self.mp_drawing = mp.solutions.drawing_utilsself.mp_drawing_styles = mp.solutions.drawing_stylesdef find_hands(self, img, draw=True):img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)self.results = self.hands.process(img_rgb)if self.results.multi_hand_landmarks and draw:for hand_landmarks in self.results.multi_hand_landmarks:self.mp_drawing.draw_landmarks(img,hand_landmarks,self.mp_hands.HAND_CONNECTIONS,self.mp_drawing_styles.get_default_hand_landmarks_style(),self.mp_drawing_styles.get_default_hand_connections_style())return img, self.resultsdef find_positions(self, img, hand_index=0):h, w, c = img.shapelandmark_list = []bbox = [0, 0, 0, 0]  # x_min, y_min, x_max, y_max# Check if any hands detectedif not self.results.multi_hand_landmarks:return landmark_list, bbox# Check if requested hand index existsif hand_index >= len(self.results.multi_hand_landmarks):return landmark_list, bbox# Extract hand landmarkshand = self.results.multi_hand_landmarks[hand_index]# Initialize bounding box coordinatesx_min, y_min = w, hx_max, y_max = 0, 0# Process each landmarkfor id, lm in enumerate(hand.landmark):# Convert normalized coordinates to pixel coordinatescx, cy, cz = int(lm.x * w), int(lm.y * h), lm.zlandmark_list.append([id, cx, cy, cz])# Update bounding boxx_min = min(x_min, cx)y_min = min(y_min, cy)x_max = max(x_max, cx)y_max = max(y_max, cy)# Add padding to bounding boxpadding = int((y_max - y_min + x_max - x_min) * 0.1 / 2)bbox = [max(0, x_min - padding),max(0, y_min - padding),min(w, x_max + padding),min(h, y_max + padding)]return landmark_list, bboxdef draw_bounding_box(self, img, bbox, hand_label="Hand"):x_min, y_min, x_max, y_max = bboxcv2.rectangle(img, (x_min, y_min), (x_max, y_max), (0, 255, 0), 2)cv2.putText(img, hand_label, (x_min, y_min - 10),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)return imgdef get_hand_type(self, idx=0):if not self.results.multi_hand_landmarks:return Noneif idx >= len(self.results.multi_handedness):return None# Get hand type from classificationhand_type = self.results.multi_handedness[idx].classification[0].labelreturn hand_typeif __name__ == "__main__":detector = HandDetector()img = cv2.imread("1.jpg")img, results = detector.find_hands(img)lm_list, bbox = detector.find_positions(img, hand_index=0)if lm_list:hand_type = detector.get_hand_type(0)img = detector.draw_bounding_box(img, bbox, hand_type)# 绘制某一个关键点# if len(lm_list) > 8:#     cv2.circle(img, (lm_list[8][1], lm_list[8][2]), 5, (255, 0, 255), cv2.FILLED)cv2.imshow("Hand Detector", img)cv2.imwrite("result.jpg", img)cv2.waitKey(0)cv2.destroyAllWindows()

5、参考

  • https://github.com/Sxhail/Hand-Detection-Model/blob/main/hand_detector.py
  • 【python】OpenCV—Hand Landmarks Detection

6、其它手部检测和手势识别的方案

手检测:深度图,Tiny YOLOv3

https://github.com/LadaOndris/hand-recognition

It consists of hand detection, hand pose estimation, and gesture classification.

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


手检测:yolov3、yolov4

https://github.com/cansik/yolo-hand-detection

在这里插入图片描述

数据集: CMU Hand DB dataset + Egohands dataset


手检测:检测,朝向

This project utilizes a modified MobileNet in company with the SSD framework to achieve a robust and fast detection of hand location and orientation.

在这里插入图片描述

https://github.com/yangli18/hand_detection


手检测:yolov4

https://github.com/ehsainit/yolo-hand-detection

训练数据集 http://vision.soic.indiana.edu/projects/egohands/


手检测:yolov5

https://github.com/siriusdemon/hand-yolov5/tree/main

在这里插入图片描述


手检测:多边形矩形框,yolov7,COCO-Hand data.

https://github.com/nuwandda/yolov7-hand-detection?tab=readme-ov-file

在这里插入图片描述

https://www3.cs.stonybrook.edu/~cvl/projects/hand_det_attention/


手检测多边形矩形框:https://github.com/SupreethN/Hand-CNN

论文 Contextual Attention for Hand Detection in the Wild, International Conference on Computer Vision (ICCV), 2019. 的源码

在这里插入图片描述

在这里插入图片描述


忍法:大坝谁修哈

https://github.com/Kazuhito00/NARUTO-HandSignDetection

在这里插入图片描述


手势检测:火影忍者,yolov11

https://github.com/Jannat-Javed/Naruto-Hand-Seals-Detection

在这里插入图片描述


更多有趣的代码示例,可参考【Programming】

相关文章:

【python】OpenCV—Hand Detection

文章目录 1、功能描述2、代码实现3、效果展示4、完整代码5、参考6、其它手部检测和手势识别的方案 更多有趣的代码示例,可参考【Programming】 1、功能描述 基于 opencv-python 和 mediapipe 进行手部检测 2、代码实现 导入必要的库函数 import cv2 import media…...

es6的100个问题

基础概念 解释 let、const 和 var 的区别。什么是块级作用域?ES6 如何实现它?箭头函数和普通函数的主要区别是什么?解释模板字符串(Template Literals)的用途,并举例嵌套变量的写法。解构赋值的语法是什么…...

【Git 常用指令速查表】

Git 常用指令速查表 Git 常用指令速查表目录1. 初始化仓库2. 提交代码流程3. 分支管理4. 远程仓库操作5. 撤销操作6. 查看状态与日志7. 其他实用指令完整操作示例常用场景速查表 Git 常用指令速查表 目录 初始化仓库提交代码流程分支管理远程仓库操作撤销操作查看状态与日志其…...

Flink中聚合算子介绍

前言 在flink api中,聚合算子是非常常用的。所谓的聚合就是在分组的基础上做比较计算的操作。下面通过几个简单案例来说明聚合算子的用法和注意事项。 聚合算子案例 因为flink的api操作流程比较固定,从获取执行环境》获取数据源》执行数据转换操作》输…...

【基础】Windows 中通过 VSCode 使用 GCC 编译调试 C++

准备 安装 VSCode 及 C 插件。通过 MSYS2 安装 MinGW-w64 工具链,为您提供必要的工具来编译代码、调试代码并配置它以使用IntelliSense。参考:Windows 中的 Linux 开发工具链 验证安装: gcc --version g --version gdb --version三个核心配…...

Web Services 简介

Web Services 简介 概述 Web Services 是一种网络服务技术,允许不同的应用程序通过互联网进行交互和数据交换。随着互联网的普及和发展,Web Services 已经成为企业级应用中不可或缺的一部分。本文将详细介绍 Web Services 的概念、特点、应用场景以及相关的技术架构。 什么…...

数据仓库 - 转转 - 一面凉经

面试流程 自我介绍 Python 中,如何在数据清洗过程中应对内存不够的情况 如何避免,在使用Pandas处理大规模数据时,经常会遇到“SettingWithCopyWarning”警告 在Hive中,当您使用动态分区功能进行数据插入时,可能会遇…...

2025跳槽学习计划

(1)编程基础: 目录学习资料Chttps://www.bilibili.com/video/BV1z64y1U7hs?spm_id_from333.1387.favlist.content.clickLinuxPytorchhttps://www.bilibili.com/video/BV1if4y147hS?spm_id_from333.1387.favlist.content.clickopencv数据结…...

算法 | 2024最新算法:鳑鲏鱼优化算法原理,公式,应用,算法改进研究综述,matlab代码

2024最新鳑鲏鱼优化算法(BFO)研究综述 鳑鲏鱼优化算法(Bitterling Fish Optimization, BFO)是2024年提出的一种新型群智能优化算法,受鳑鲏鱼独特的繁殖行为启发,通过模拟其交配、产卵和竞争机制进行全局优化。该算法在多个领域展现出优越性能,尤其在解决复杂非线性问题中…...

具身系列——Diffusion Policy算法实现CartPole游戏

代码原理分析 1. 核心思想 该代码实现了一个基于扩散模型(Diffusion Model)的强化学习策略网络。扩散模型通过逐步去噪过程生成动作,核心思想是: • 前向过程:通过T步逐渐将专家动作添加高斯噪声,最终变成…...

前端性能优化:深入解析哈希算法与TypeScript实践

/ 示例&#xff1a;开放寻址哈希表核心实现 class OpenAddressingHashTable<T> {private size: number;private keys: (string | null)[];private values: (T | null)[];private tombstone Symbol(Deleted);constructor(size: number 53) {this.size size;this.keys …...

知识就是力量——物联网应用技术

基础知识篇 一、常用电子元器件1——USB Type C 接口引脚详解特点接口定义作用主从设备关于6P引脚的简介 2——常用通信芯片CH343P概述特点引脚定义 CH340概述特点封装 3——蜂鸣器概述类型驱动电路原文链接 二、常用封装介绍贴片电阻电容封装介绍封装尺寸与功率关系&#xff1…...

(windows)conda虚拟环境下open-webui安装与启动

一、创建conda环境 重点强调下&#xff0c;如果用python pip安装&#xff0c;一定要选择python3.11系列版本&#xff0c;我选的3.11.9。 如果你的版本不是这个系列&#xff0c;将会出现一些未知的问题。 conda create -n open-webui python3.11 -y如下就创建好了 二、安装o…...

oracle密码过期 ORA-28001解决方案: the password has expired

** oracle密码过期 ORA-28001解决方案: the password has expired ** oracle 11g 默认密码过期时间为180天密码过期后&#xff0c;访问数据库会出现如下异常java.sql.SQLException: ORA-28001: the password has expired 查询密码过期设定 select * from dba profiles where…...

GStreamer —— 3.1、Qt+GStreamer制作多功能播放器,支持本地mp4文件、rtsp流、usb摄像头等(可跨平台,附源码)

🔔 GStreamer 相关音视频技术、疑难杂症文章合集(掌握后可自封大侠 ⓿_⓿)(记得收藏,持续更新中…) 运行效果...

六十天Linux从0到项目搭建(第十天)(系统调用 vs 库函数/进程管理的建模/为什么进程管理中需要PCB?/exec 函数/fork原理与行为详解)

1 系统调用 vs 库函数&#xff1a;本质区别与协作关系 核心区别 特性系统调用&#xff08;System Call&#xff09;库函数&#xff08;Library Function&#xff09;定义操作系统内核提供的 底层接口&#xff0c;直接操作硬件。封装系统调用的 高级函数&#xff0c;提供便捷功…...

资本运营:基于Python实现的资本运作模拟

基于Python实现的一个简单的资本运营框架&#xff1b; ​企业生命周期演示&#xff1a;观察初创→成长→上市→并购全流程 ​行业对比分析&#xff1a;不同行业的财务特征和估值差异 ​资本运作策略&#xff1a;体验IPO定价、投资决策、并购整合等操作 ​市场动态观察&#xff…...

当EFISH-SBC-RK3576遇上区块链:物联网安全与可信数据网络‌

在工业物联网场景中&#xff0c;设备身份伪造与数据篡改是核心安全隐患。‌EFISH-SBC-RK3576‌ 通过 ‌硬件安全模块 区块链链上验证‌&#xff0c;实现设备身份可信锚定与数据全生命周期加密&#xff0c;安全性能提升10倍以上。 1. 安全架构&#xff1a;从芯片到链的端到端防…...

关于spark在yarn上运行时候内存的介绍

在YARN上运行Spark时&#xff0c;内存管理是性能调优的核心环节。以下是 Driver Memory、Executor Memory、堆内存&#xff08;Heap Memory&#xff09; 和 堆外内存&#xff08;Off-Heap Memory&#xff09; 的区别与配置方法&#xff0c;以及实际场景中的最佳实践&#xff1a…...

分布式系统面试总结:3、分布式锁(和本地锁的区别、特点、常见实现方案)

仅供自学回顾使用&#xff0c;请支持javaGuide原版书籍。 本篇文章涉及到的分布式锁&#xff0c;在本人其他文章中也有涉及。 《JUC&#xff1a;三、两阶段终止模式、死锁的jconsole检测、乐观锁&#xff08;版本号机制CAS实现&#xff09;悲观锁》&#xff1a;https://blog.…...

【VSCode的安装与配置】

目录&#xff1a; 一&#xff1a;下载 VSCode二&#xff1a;安装 VSCode三&#xff1a;配置 VSCode 一&#xff1a;下载 VSCode 下载地址&#xff1a;https://code.visualstudio.com/download 下载完成之后&#xff0c;在对应的下载目录中可以看到安装程序。 二&#xff1a;安装…...

ElasticSearch常用优化点

关闭交换分区&#xff1a;因为Linux采用了三级页表虚存管理&#xff0c;关闭交换分区可以减少系统IO&#xff0c;页面换入唤出时所耗费的总线时间以及减少系统中断次数&#xff1b;swap的使用会显著增加延迟和降低吞吐量。文件描述符配置&#xff1a;任何网络应用都需要增加文件…...

脱围机制-react18废除forwardRef->react19直接使用ref的理解

采用ref&#xff0c;可以在父组件调用到子组件的功能 第一步&#xff1a;在父组件声明ref并传递ref interface SideOptsHandle {refreshData: () > Promise<void> }const sideOptsRef useRef<SideOptsHandle>(null) // 创建 ref<SideOpts ref{sideOptsRef…...

Spark2 之 Expression/Functions

ExpressionConverter src/main/scala/org/apache/gluten/expression/ExpressionConverter.scala TopNTransformer src/main/scala/org/apache/gluten/execution/TopNTransformer.scala...

Windows中安装git工具

下载好git安装包 点击next 选择安装目录 根据需要去勾选 点击next 点击next PATH环境选择第二个【Git...software】即可&#xff0c;再点击【Next】。 第一种配置是“仅从Git Bash使用Git”。这是最安全的选择&#xff0c;因为您的PATH根本不会被修改。您只能使用 Git Bash 的…...

【CSS】CSS 使用全教程

CSS 使用全教程 介绍 CSS&#xff08;层叠样式表&#xff0c;Cascading Style Sheets&#xff09;是一种样式表语言&#xff0c;用于描述 HTML 或 XML 文档的布局和外观&#xff0c;它允许开发者将文档的内容结构与样式表现分离&#xff0c;通过定义一系列的样式规则来控制网页…...

《HarmonyOS Next自定义TabBar页签凸起和凹陷案例与代码》

引言 自定义TabBar在HarmonyOS Next应用中很常见&#xff0c;本文将介绍如何实现页签的凸起和凹陷效果&#xff0c;并通过代码示例展示实现过程。 实现思路 基于已有的自定义TabBar思路&#xff0c;通过调整布局和样式实现凸起和凹陷效果。凸起效果可以通过在选中的页签下方…...

全分辨率免ROOT懒人精灵-自动化编程思维-设计思路-实战训练

全分辨率免ROOT懒人精灵-自动化编程思维-设计思路-实战训练 1.2025新版懒人精灵-实战红果搜索关键词刷视频&#xff1a;https://www.bilibili.com/video/BV1eK9kY7EWV 2.懒人精灵-全分辨率节点识别&#xff08;红果看广告领金币小实战&#xff09;&#xff1a;https://www.bili…...

如何在IDEA中借助深度思考模型 QwQ 提高编码效率?

通义灵码上新模型选择功能&#xff0c;不仅引入了 DeepSeek 满血版 V3 和 R1 这两大 “新星”&#xff0c;Qwen2.5-Max 和 QWQ 也强势登场&#xff0c;正式加入通义灵码的 “豪华阵容”。开发者只需在通义灵码智能问答窗口的输入框中&#xff0c;单击模型选择的下拉菜单&#x…...

C++11QT复习 (四)

Day6-1 输入输出流运算符重载&#xff08;2025.03.25&#xff09; 1. 拷贝构造函数的调用时机 2. 友元2.1 友元函数 3. 输入输出流运算符重载3.1 关键知识点3.2 代码3.3 关键问题3.4 完整代码 4. 下标访问运算符 operator[]4.1 关键知识点4.2 代码 5. 函数调用运算符 operator…...