基于opencv-mediapipe的手势识别

这篇具有很好参考价值的文章主要介绍了基于opencv-mediapipe的手势识别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

上一篇文章介绍了基于opencv的手势识别,如果大家运行了我的代码,会发现代码中找出手部轮廓的效果不是很理想。当时我在网上找寻解决的办法,刚好找到了mediapip库,然后我就利用opencv和mediapipe这两个库重新进行了手势识别的代码编写。效果还不错,写篇文章记录一下。

1.mediapipe简介

Mediapipe是google的一个开源项目,可以提供开源的、跨平台的常用机器学习(machine learning)方案。Mediapipe实际上是一个集成的机器学习视觉算法的工具库,包含了人脸检测、人脸关键点、手势识别、头像分割和姿态识别等各种模型。

由于我主要做的是手势识别,我就主要简单地讲解一下该库的手部检测模块,以便大家能更好的理解最后的手势识别的源代码。(如果大家想要了解其他模块,可以点击这里的进行了解:mediapipe官方简介

首先进行手部检测模块的初始化
mphand = mp.solutions.hands
hands = mphand.Hands()
mpHand.Hands参数 参数详解
static_image_mode=False 如果设置为False ,减少了延迟,非常适合处理视频帧。如果设置为True ,适合处理一批可能不相关的静态图像。默认为False 。
max_num_hands=2 要检测的最大手数。默认为2
model_complexity=1 手部标志模型的复杂性:0或1 .地标精度和推理延迟通常随着模型复杂性的增加而增加。默认为 1
min_detection_confidence=0.5 手部检测模型中的最小置信度值 ,以便将检测视为成功。默认为 0.5
min_tracking_confidence=0.5 地标跟踪模型中的最小置信度值 ,表示手部地标被视为成功跟踪,否则将在下一个输入图像上自动调用手部检测。将其设置为更高的值可以提高解决方案的健壮性,但代价是延迟更高。如果static_image_mode为 True,则忽略,其中手部检测只是在每个图像上运行。默认为0.5

如果不太理解上面的参数含义,没关系,直接默认就好。我认为只要知道max_num_hands和min_detection_confidence两个参数的含义就可以了

接着就是手势检测过程
hand = hands.process(img)

参数img是要进行检测的图片,由于opencv读入的图片为BGR模式,这里的img一定要转换为RGB模式

最后就是读取检测后的结果
 finger = []
    for handlms in hand.multi_hand_landmarks:
        for lm in handlms.landmark:
        	img_height,img_width,_ =  img.shape
        	#这里检测返回的x,y的坐标是基于原图像大小的比例坐标,
        	#所以要与原图像相乘得到真实的坐标
            x, y = int(lm.x * img_width), int(lm.y * img_height)
            finger.append([x, y])

如果打印一下finger列表,你就会看到21个坐标值。这21个坐标就是midiapipe基于人体手部21个关键点在原图像上位置坐标的检测。这21个坐标值对应的手部检测的关键点如下图:

基于opencv-mediapipe的手势识别

2.手势识别思路

mediapipe的基本用法大家已经了解了,现在讲解思路以及关键技巧的讲解

思路讲解

首先使用opencv调用摄像头,从摄像头读取图像,将图像反转(摄像头读取的图像与现实中是相反的),并将图像转换为RGB模式。接着使用mediapipe进行手部检测,并用列表存储。然后利用手指构成的角度来判断手指是否弯曲。

关键点讲解

整个程序似乎是没有什么难度的,主要的关键就是如何检测手指是否弯曲。

我在书上看到利用手指尖端与手指根部相减,观察结果的正与负来判断手指弯曲。举个例子,上图中我用8坐标点y值减去6坐标点的y值(此处y值不理解的话,点击这里),若结果为正,则表示该手指弯曲,为负,表示手指伸张。
但是这里存在着两个问题
第一,大拇指的弯曲与其余四个手指的弯曲是不同的(这里大家可以伸出自己的手观察一下,就可以理解),例如上图中我用4坐标和1坐标进行y值(此处y值同上)相减,但是并不是所有人大拇指弯曲的时候的4坐标的y值一定大于1坐标的y值,这时候就无法判断大拇指是否弯曲。
对于这个问题,我曾经想设置一个阈值来解决,但是需要不断的调试这个阈值的大小,并且每个人的手指大小不同可能这个阈值适合你,但不适合其他人。
第二,不知道大家发现没有上面的示例都是基于手部指尖朝上的情况,如果手部指尖朝下,朝左,朝右。这些情况怎么办?难道要多写一些判断条件,逐个分析。这样代码量很大,我不是很推荐。

引入角度来解决问题
引入三角函数,用手指构成的角度大小来进行判断
举个例子,这里我采用5,6,7坐标点为顶点来构成的三角形,这里我
以5,6坐标构成的边为a,
以6,7坐标构成的边为b,
以5,7坐标构成的边为c,
然后利用余弦函数来计算顶点6的角度,公式为:
a 2 + b 2 − c 2 / 2 a b a^2+b^2-c^2/2ab a2+b2c2/2ab
然后设置一个阈值为155,来判断手指是否弯曲。

3.完整代码

这里我对代码进行了注释,帮助大家阅读程序

import cv2
import numpy
import mediapipe as mp
import math

#创建手部检测的对象
mphand = mp.solutions.hands
hands = mphand.Hands()
mpdraw = mp.solutions.drawing_utils

cap = cv2.VideoCapture(0)

while cap.isOpened():
	#对读取的图像进行反转,转换为RGB模式,读出图片大小
    ret,frame = cap.read()
    frame = cv2.flip(frame,1)
    img =cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
     h,w,_ = frame.shape
     
     #进行手部的检测
    hand = hands.process(img)
    
   #判断是否检测到了手部
    if hand.multi_hand_landmarks:
        count = 0	#统计手指的伸出个数
        for handlms in hand.multi_hand_landmarks:
            finger = []
            finger_point = []
            
            #这里我将每一根手指的四个坐标整合到一个列表中,大家可以打印finger,进行详细的查看
            for id,lm in enumerate(handlms.landmark):
                x,y = int(lm.x*w),int(lm.y*h)
                if id == 0:
                    pass
                elif id % 4 == 0:
                    finger_point.append([x,y])
                    finger.append(finger_point)
                    finger_point = []
                else:
                    finger_point.append([x,y])

			#遍历每一根手指列表,计算其构成的三角形的三边长,这里使用26101418所对应的角进行判断
            for id,point in enumerate(finger):
                a = math.hypot((point[0][0]-point[1][0]),(point[0][1]-point[1][1]))
                b = math.hypot((point[1][0]-point[2][0]),(point[1][1]-point[2][1]))
                c = math.hypot((point[0][0]-point[2][0]),(point[0][1]-point[2][1]))

              #在计算value值的时候,除数可能为零,以及当三点在一点直线上,都会抛出异常,所以要捕获异常
                try :   
                	value = (a**2+b**2-c**2)/(2*a*b)
                	#这里的value为弧度制,乘上57转换为角度制,当然你也可以选择直接使用弧度制
                    angle = math.acos(value)*57
                except ValueError:
                    angle = 180
                except ZeroDivisionError:
                    angle = 0
                print(angle)   
				
				#当角度大于155的时候记为手指伸出
                if angle >= 155:
                    count += 1
                else:
                    pass
                    
            #在手部绘制关键点位置
            mpdraw.draw_landmarks(frame,handlms,mphand.HAND_CONNECTIONS)
		
		#将手指检测的结果显示在图像上
        cv2.putText(frame,str(count),(int((1/9)*w),int((1/9)*h)),cv2.FONT_HERSHEY_COMPLEX,1,(0,255,0),1)
     
     #展示图片   
    cv2.imshow('img',frame)
    
    #按下Esc退出循环
    c = cv2.waitKey(25)
    if c == 27:
        break
cap.release()
cv2.destroyAllWindows()

4.结尾

使用mediapipe库来检测手部,这让我们可以通过手势来完成很多有意思的事情,比如通过手势来控制电脑鼠标,手势作画等。这些我也在尝试去做,等我完成之后会分享给大家思路,以及遇到的困难。
最后创作不易,希望大家支持,点赞。期待大家能和我一块交流学习,共同进步。
基于opencv-mediapipe的手势识别文章来源地址https://www.toymoban.com/news/detail-483431.html

到了这里,关于基于opencv-mediapipe的手势识别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于mediapipe的手势数字识别

    基于mediapipe识别手势所对应的数字(一、二、三、四、五)。 mediapipe的官网 总体思路 :mediapipe可以识别手掌的关键点,我的思路是识别单根手指是否弯曲,然后根据五根手指的弯曲程度判断手势所对应的数字。 那怎么判断单根手指是否弯曲呢? 我是根据手指的四个关键点的相

    2024年02月11日
    浏览(55)
  • 基于Mediapipe的Python手势识别项目(手势识别游戏)附项目源码

    基于Mediapipe的手势识别,完成的手势识别游戏。运行效果图如下: 首先是初始的界面效果图: 游戏规则:屏幕上会出现蚊子和蜜蜂,当手蜷曲握起时,表示抓的动作。如果抓到右边移动的蚊子,则会增加分数,如果抓到右边的蜜蜂,则会出现被蛰到的声音 :) 调用Mediapip

    2024年02月11日
    浏览(109)
  • 基于mediapipe和opencv的手势控制电脑鼠标

    通过我的上一篇文章,可以了解到mediapipe关于手部检测的使用方法。这时我们就可以进行一些更加炫酷的操作。这篇文章我就来讲解一下如何用手势来控制电脑鼠标。 在开始之前我们要介绍一个能够操作电脑鼠标的库pyautogui,这里我简单介绍一下该库的一些函数,方便大家观

    2024年02月07日
    浏览(43)
  • Mediapipe手势识别

    代码: 它训练的时候是使用了两个模型,第一个是手掌检测,第二个是在手掌范围内进行关节点的检测。这里面的三维坐标中的Z轴并不是绝对意义上的Z轴,而是相对于手腕的位置,正值说明在手腕的前方,负值在手腕的后方。x和y都是0~1之间的数字(经过归一化后的数字,

    2024年02月05日
    浏览(45)
  • Mediapipe手势识别,并与unity通信

    Mediapipe是goole的一个开源项目,支持跨平台的常用ML方案,详情请戳下面链接 MediaPipe Mediapipe底层封装了手势识别的具体实现内容,而在Python中搭建完环境后经过很简单的调用就能够实现手势识别 环境如下: pip install mediapipe pip install opencv-python 简单的实现,代码很少,代码如

    2024年02月11日
    浏览(41)
  • mediapipe 手势节点识别自动控制音量

    参考:https://www.computervision.zone/topic/volumehandcontrol-py/ 主函数: VolumeHandControl.py

    2024年02月11日
    浏览(42)
  • 基于opencv的手势识别

    大家好,我是一名本科生,我的主要学习方向是计算机视觉以及人工智能。按照目前的学习进度来说,我就是一小白,在这里写下自己编写的程序,与大家分享,记录一下自己的成长。 思路分析 获取图片,在图片中找到手,然后进行一系列的闭运算,降噪平滑处理,轮廓查

    2024年02月03日
    浏览(57)
  • 基于opencv与mediapipe的民族舞舞蹈动作识别

    需要项目的请关注、私信 Opencv(Open Source Computer Vision Library)是一个基于开源发行的跨平台计算机视觉库,它实现了图像处理和计算机视觉方面的很多通用算法,已成为计算机视觉领域最有力的研究工具。在这里我们要区分两个概念:图像处理和计算机视觉的区别:图像处理

    2024年02月10日
    浏览(58)
  • [ Python+OpenCV+Mediapipe ] 实现手势控制音量

    目录 一、写在前面 二、本文内容 三、开发环境  四、代码实现 4.1引入所需包 4.2 定义一个类并初始化 4.3 定义绘制一界面并实现音量控制的主方法 五、看一看实际效果吧 六、完整代码 七、小结  八、感谢        本文所用例子为个人学习的小结,如有不足之处请各位多多

    2024年02月22日
    浏览(56)
  • 基于OpenCV的简易实时手势识别(含代码)

    这是我大一寒假时写着玩的,非常简陋。基于凸包检测,所以实际上是计算指尖数量判断1~5的手势。又为1 ~3手势赋了控制鼠标操作的功能(但不能移动鼠标,而且因为手势识别不太准确所以这个功能实现得很废/doge)。(才疏学浅,希望有生之年能写个更好的 版本信息:Vi

    2024年02月03日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包