基于mediapipe的手势游戏控制

embedded/2025/1/15 21:12:55/

基于mediapipe的手势游戏控制

​ 玩游戏,那不是有手就行!!!

mediapipe介绍

​ Mediapipe是Google在2019年开发并提出的一款开源的跨平台多媒体处理框架,用于构建基于机器学习的应用程序,特别是涉及到计算机视觉、音频处理、姿势估计等领域。Mediapipe实际上是一个集成的机器学习视觉算法的工具库(包含人脸检测、人脸关键点、手势识别、头像分割和姿态识别等各种模型),该库提供了一系列预训练模型和工具,可以帮助开发者快速构建和部署计算机视觉和音频处理应用。它提供了一套易于使用的API,可以用于实时姿势估计、手势识别、面部识别、目标跟踪等任务。

手势捕捉

​ 项目地址: https://github.com/google/mediapipe

​ pip安装mediapipe、opencv

pip install mediapipe
pip install opencv-python

在文件中引入依赖

python">import cv2
import mediapipe as mp

通过cv2打开摄像头获取影像,电脑默认的输入是0,如果有其他输入通过更改序号来切换输入设备。

python">cap = cv2.VideoCapture(0)

初始化手势捕捉需要用到的对象

mpHands = mp.solutions.hands
hands = mpHands.Hands()
# 用于将识别到的点坐标绘制到输入的图片上
mpDraw = mp.solutions.drawing_utils 

写一个死循环,频繁监听摄像头输入并对手势进行绘制

while True:ret, img = cap.read()if ret:# cv2默认获取的图片是BGR的颜色通道,需要将其转换为RGBimgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)# 对图像进行识别result = hands.process(imgRGB)if result.multi_hand_landmarks:# 遍历出现的手,这边仅用一只手进行操控,所以这边应该只有一个for handLms in result.multi_hand_landmarks:# 将识别到的手势坐标点绘制到获取的图像上 mpHands.HAND_CONNECTIONS是将所有坐标点连接起来mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)# 将操作后的图像显示在屏幕上cv2.imshow('img', img)

最终的效果如下

请添加图片描述

返回的结果每个点都有固定的序号,我们将序号也固定在图像上,方便我们观察每个序号处于什么节点。

先获取原始图像的高和宽

python">imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
imgHeight = img.shape[0]
imgWidth = img.shape[1]

在绘制手部坐标后,对坐标点进行遍历,得到每个点的坐标。

for i, lm in enumerate(handLms.landmark):xPos = int(lm.x * imgWidth)yPos = int(lm.y * imgHeight)cv2.putText(img, str(i), (xPos - 25, yPos + 5), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 0, 255), 2)

绘制出来如图所示:

请添加图片描述

可以看到他是从手根部开始计数,按照拇指、食指、中指…的顺序进行排列,这样我们可以知道如果我们想要获取到某个位置的坐标应该用那个序号进行获取。

手势控制

上面我们获取到了每个节点的坐标,实际上我们只需要以一个点为参照就可以知道手是在向什么方向移动,因为在手势不变的情况下每个点的相对位置是基本一致的,所以我们只需要分析某个点的坐标移动,就可以得出手部的移动趋势。

例如我们固定以拇指的顶部,也就是图中的4号节点作为参照点分析,记录上一次的X轴坐标, 然后每次移动跟上一次做比较如果大于上一次则向右移动了,小于上次则向左移动了。

分析完手的移动意图后我们就可以使用pynput模拟键盘输入了。这边仅提供一个思路,具体的轨迹分析移动距离是一个大工程,简单代码实际得出来的操控体验不佳。

pip install pynput
python">from pynput.keyboard import Controller
import time
# 模拟按下键盘的D键
keyboard = Controller()keyboard.press('d')time.sleep(0.2)keyboard.release('d')

避免频繁输入,控制一个移动阈值,当移动的距离小于阈值时不进行按键输入。

最终效果如下,实际体验烂得一匹,动画中手部视频延迟于游戏是因为每次按键输入都有延迟,然后才会把手部图像输出到屏幕上,所以看上去手还没动,车把手就动了,现实其实还是蛮跟手的,但是没有什么用,就是图一乐。

请添加图片描述

结语

​ 扩展一下,当我们握拳时,手指顶部的坐标和手掌根部的坐标相对距离会缩短,那我们也可以根据这个特性使用握拳以及张开程度来控制油门。再扩展一下,可以训练一个检测姿态的模型,检测人在骑着某个东西的时候身体的倾斜,同时输入到游戏中,是不是更有代入感一些。想要实现这些并且有一个还不错的游戏体验,需要大量时间进行调试,时间成本以及知识库都是一个大考验。


http://www.ppmy.cn/embedded/154199.html

相关文章

汽车故障码U007388 PCAN Bus OFF 解析和处理方法

一、故障码解析 含义: U007388 是一个汽车故障码,“U” 开头的故障码一般涉及网络通信故障。PCAN(Power Control Area Network)通常是指动力控制局域网。“Bus OFF” 表明该网络处于离线状态,意味着 PCAN 网络中的某些…

leetcode 87. 扰乱字符串

题目:87. 扰乱字符串 - 力扣(LeetCode) dfs状态记录。 dfs:以两个字符串 [a1,a2,a3,a4] 和 [b1,b2,b3,b4]为例,可以往下搜以下几种情况,一种情况为true就能返回true F([a1],[b1]) && F([a2,a3,a4…

Linux 常见运营维护,从安装软件开始,到mysql,php,redis,tomcat等软件安装,配置,优化,持续更新中。。。

下载centos7 CentOS 7 完整版(DVD): https://mirrors.aliyun.com/centos/7/isos/x86_64/CentOS-7-x86_64-DVD-2009.isoCentOS 7 最小化版(Minimal): https://mirrors.aliyun.com/centos/7/isos/x86_64/C…

[ComfyUI]接入Google的Whisk,巨物融合玩法介绍

一、介紹​ 前段时间,谷歌推出了一个图像生成工具whisk,有一个很好玩的图片融合玩法,分别提供三张图片,就可以任何组合来生成图片。​ ​ 最近我发现有人开发了对应的ComfyUI插件,对whisk做了支持,就来体验了下&#…

微信小程序:实现首页权限菜单效果

一、效果 二、数据库表 1、菜单表 包含权限名称,模块名称,图标名称,页面跳转的方法,菜单是否显示栏位 2、角色对应权限表 包含角色id和权限id,这个表将角色和菜单角色连接,给角色赋予权限功能 3、 账户表 用于绑定账号隶属于什么角色,绑定的角色表 4、角色表 菜单的…

【机器学习】数学知识:指数函数(exp)

在数学和编程中,exp 表示指数函数,即自然常数 e 为底的幂函数。 其数学表达式为: 其中: e 是一个常数,称为自然对数的底数,其值约为 2.718。x 是指数。 性质 基本性质: 与自然对数的关系&…

wireshark排除私接小路由

1.wireshark打开,发现了可疑地址,合法的地址段DHCP是192.168.100.0段的,打开后查看发现可疑地址段,分别是,192.168.0.1 192.168.1.174 192.168.1.1。查找到它对应的MAC地址。 ip.src192.168.1.1 2.通过show fdb p…

C#Struct堆栈

Struct若其内部含有堆对象,Struct的该对象放在堆上; Struct当做参数传递时,其堆属性作为引用传递,值属性还是作为值传递; struct TS { public int[] t1; public int t2; } public void TF1(TS t) { int[] t1 t.t1; …