基于mediapipe和opencv的手势控制电脑鼠标

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

通过我的上一篇文章,可以了解到mediapipe关于手部检测的使用方法。这时我们就可以进行一些更加炫酷的操作。这篇文章我就来讲解一下如何用手势来控制电脑鼠标。

在开始之前我们要介绍一个能够操作电脑鼠标的库pyautogui,这里我简单介绍一下该库的一些函数,方便大家观看最后的源码

函数名 作用
pyautogui.size() 获取屏幕的分辨率,返回值为width,height
pyautogui.click(x,y,button = ‘left/right’) 在屏幕的(x,y)处进行左键或右键的点击操作
pyautogui.doubleClick(x,y) 在屏幕的(x,y)处双击左键
pyautogui.moveTo(x, y, duration=0) 将鼠标移动到指定的(x,y)处;duration 的作用是设置移动时间,是可选参数
pyautogui.FAILSAFE =True 默认这项功能为True, 这项功能意味着:当鼠标在屏幕的最左上角,程序会报错;目的是防止程序一直控制鼠标导致程序无法结束

由于mediapipe的使用方法在上一篇文章中已经介绍过了,这里就不再重复介绍了。如果小伙伴不知道mediapipe是什么的话,点击这里,看我的上一篇文章

思路

首先使用opencv调用摄像头,从摄像头读取图像,将图像反转(摄像头读取的图像与现实中是相反的),并将图像转换为RGB模式。接着使用mediapipe进行手部检测,并用列表存储手部的21个关键点的坐标。利用该列表进行检测:
        当手指食指小于160度的时候认定鼠标点击左键
        当手指中食小于160度的时候认定鼠标点击右键
        当手指食指和中值之间的距离小于40的时候认定鼠标点双击左键
        (如果不知道如何检测手指角度数,请看我的上一篇文章)
然后我用手部关键点的0和9的坐标的中值来代替鼠标,大概就在下图我标注的绿色点的位置
手势控制鼠标,opencv,计算机外设,计算机视觉

实现过程的难点

这里有两个难点:第一,一开始的时候我获取到屏幕的分辨率(width,height),然后再在获取的每一帧的图像的大小(x,y),接着获取比例关系(ratio_x=width/x,ratio_y=height/y),当得到如上图的绿色点的坐标乘上比例关系就获得了屏幕鼠标应该在的位置。这样做看起来很好,但在实践的过程中有很大的问题,因为你会发现屏幕上的鼠标会到达不了屏幕的边缘区域(你可以亲自测试一下)。
第二,如果手指悬停在某一点处,电脑上的鼠标会一直晃动。因为你的手指会一直抖动,做不到完全静止,这细微的变化乘上比例,就会被放大,这样就会造成看似手指悬停,但是屏幕上的鼠标会抖动的原因。

解决办法:

第一:在网上看见了numpy.interp(),这是一个一维的插值函数(该函数的参数,这里就不讲解了,在最后的源代码中我会做注释讲解的),下图时插值函数的效果图,图上的x,y轴代表了图像和屏幕的大小。虽然这里的插值和我使用的比例方法可以都看作是线性的直线方程,但是还是插值函数效果更好。这令我很困惑。
手势控制鼠标,opencv,计算机外设,计算机视觉
第二:对于手指悬停,鼠标一直抖动的问题。我们可以先记录一下这次屏幕上鼠标的坐标(pre_x, pre_y),等得到下一次鼠标坐标(mouse_x,mouse_y)的时候,
进行计算x = (mouse_x - pre_x)/ smooth 和 y =(mouse_y - pre_y)/ smooth
这里的(mouse_x - pre_x)和(mouse_y - pre_y)相当与计算出了这两次鼠标的距离,除以smooth
相当于缩短了距离,然后用(pre_x + x, pre_y + y)用于当前鼠标的坐标位置,然后更新
pre_x = pre_x + x, pre_y = pre_y + y。这样就缩减了前后两次鼠标的距离,来防止鼠标的抖动,且更新了鼠标的位置。
这里要注意(mouse_x - pre_x)和 (mouse_y - pre_y)的相减顺序,以及smooth一定要大于1(小于1相当于扩大了距离),当smooth的值越大时,鼠标移动会变慢,鼠标会稳定;值越小,鼠标移动就会变快,鼠标会抖动。

完整代码;
import pyautogui
import time
import cv2
import numpy as np
import math
import mediapipe as mp

# 获取手指的坐标,全部获取存入列表中并返回该列表
def finger_coordinate(hand):
    finger = []
    for handlms in hand.multi_hand_landmarks:
        for lm in handlms.landmark:
            x, y = int(lm.x * cap_x), int(lm.y * cap_y)
            finger.append([x, y])
        #mpdraw.draw_landmarks(frame, handlms, mphand.HAND_CONNECTIONS)
    return finger

#判断手指的弯曲度数以及食指和中值的距离,将判断的结果存入judge_finfer列表中,
#如果食指弯曲则judge_finger[0] = 1,中指弯曲则judge_finger[1] = 1,如果两手指的距离小于40则judge_finger[2] = 1
#最后返回judge_finger
def check_finger(finger):
    judge_finger = [0,0,0]
    for i,id in enumerate([5,9]):
        a = round(math.hypot(finger[id][0]-finger[id+1][0],finger[id][1]-finger[id+1][1]),2)
        b = round(math.hypot(finger[id+1][0]-finger[id+2][0],finger[id+1][1]-finger[id+2][1]),2)
        c = round(math.hypot(finger[id][0]-finger[id+2][0],finger[id][1]-finger[id+2][1]),2)
        try:
            angle = math.acos((a**2+b**2-c**2)/(2*a*b))*57
        except ValueError:
            angle = 180
        except ZeroDivisionError:
            angel = 0
        if angle < 160:
            judge_finger[i] = 1

    dist = math.hypot(finger[8][0]-finger[12][0],finger[8][1]-finger[12][1])
    cv2.circle(frame, finger[8], 25, (255, 0, 255), -1, )
    cv2.circle(frame, finger[12], 25, (255, 0, 255), -1, )
    if dist < 40:
        judge_finger[2] = 1
    return judge_finger


########################
#变量设置区域
offset_x = 60
offset_y = 150

smooth = 5
pre_x = 0
pre_y = 0
########################

########################
#初始化区域
cap = cv2.VideoCapture(0)

cap_x = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
cap_y = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
screen_x,screen_y = pyautogui.size()

mphand = mp.solutions.hands
hands = mphand.Hands()
mpdraw = mp.solutions.drawing_utils
########################


while cap.isOpened():
    #从摄像头中获取图像,并将图像反转,转换为RGB模式
    _,frame = cap.read()
    frame = cv2.flip(frame, 1)
    img = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
    cv2.rectangle(frame, (offset_x, offset_y), (cap_x - offset_x, cap_y), (0, 255, 0), 2)

    #进行手势的检测,返回关于手势的检测值
    hand = hands.process(img)
    #判断是否检测到手部
    if hand.multi_hand_landmarks:
        #检测手指的坐标值,并返回列表
        finger = finger_coordinate(hand)

        #1.确定鼠标的坐标

        #以编号0和9的中值为鼠标点
        x,y = (finger[0][0]+finger[9][0])//2,(finger[0][1]+finger[9][1])//2
        cv2.circle(frame, (x,y), 25, (255, 0, 255), -1)
        #使用插值法进行图像点到屏幕鼠标点的映射
        mouse_x = np.interp(x,(offset_x,cap_x-offset_x),(0,screen_x))
        mouse_y = np.interp(y,(offset_y,cap_y),(0,screen_y))
        #平滑鼠标坐标
        mouse_x = pre_x + (mouse_x-pre_x) / smooth
        mouse_y = pre_y + (mouse_y-pre_y) / smooth
        pre_x = mouse_x
        pre_y = mouse_y
        #将确定的鼠标点进行在屏幕上移动
        pyautogui.moveTo(mouse_x, mouse_y, duration=0)

        #2.检测手指来确定鼠标的点击操作

        #以第二根和第三根手指弯曲的角度为左右键,小于160度视为点击操作,以及两手指的距离小于40视为左键双击
        judge_finger = check_finger(finger)
        # 每次只能进行一个操作,所以返回值只能有一个为真,如果有超过1个为真,则进行下一次循环
        count = judge_finger.count(1)
        if count == 1:
            index = judge_finger.index(1)
            if index == 0:
                pyautogui.click(mouse_x,mouse_y,button = 'left')
                cv2.putText(frame, 'click left', (10, 20), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 1)
            elif index == 1:
                pyautogui.click(mouse_x,mouse_y,button = 'right')
                cv2.putText(frame, 'click right', (10, 20), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 1)
            else:
                pyautogui.doubleClick(mouse_x,mouse_y)
                cv2.putText(frame, 'click double', (10, 20), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 1)
        else:
            cv2.putText(frame,'no or more operate',(10,20),cv2.FONT_HERSHEY_COMPLEX,1,(0,255,0),1)
    else:
        cv2.putText(frame, 'plese put your hand', (10, 20), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 1)

    #显示图像,并在按下ESC按键时退出程序
    cv2.imshow('img',frame)
    ret = cv2.waitKey(1)
    if ret == 27:
        break

#释放摄像头
cap.release()
cv2.destroyAllWindows()

'''
英语单词
capture  捕获
frame   帧
coordinate 坐标
offset 偏移
smooth 平滑
previous  以前
'''
总结

现在的计算机视觉,语音识别,自然语言的处理都离不开机器学习和深度学习。刚好学院现在也开了机器学习这门课,其中的内容和公式真是令人望而生畏,所以接下来我打算记录下自己的学习过程,以及自己的理解感悟,分享给大家。创作不易,希望大家能多多支持。手势控制鼠标,opencv,计算机外设,计算机视觉文章来源地址https://www.toymoban.com/news/detail-727181.html

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

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

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

相关文章

  • opencv实战项目 手势识别-手势控制鼠标

    手势识别是一种人机交互技术,通过识别人的手势动作,从而实现对计算机、智能手机、智能电视等设备的操作和控制。 1.  opencv实现手部追踪(定位手部关键点) 2.opencv实战项目 实现手势跟踪并返回位置信息(封装调用) 3.手势识别-手势音量控制(opencv) 4.opencv实战项目

    2024年02月13日
    浏览(48)
  • AI项目二:基于mediapipe的虚拟鼠标控制

    若该文为原创文章,转载请注明原文出处。 由于博主太懒,mediapipe如何实现鼠标控制的原理直接忽略,最初的想法是想控制摄像头识别手指控制鼠标,达到播放电影的效果。基本上效果也是可以的。简单的说是使用mediapipe检测出手指的关键点,通过检测食指关键点去移动鼠标

    2024年02月12日
    浏览(33)
  • 【机器视觉案例】(8) AI视觉,手势控制电脑鼠标,附python完整代码

    各位同学好,今天和大家分享一下如何使用  MediaPipe+Opencv 通过手势识别来控制电脑鼠标的移动和点击,如果有兴趣的话,可以代替鼠标去打游戏。先放图看效果。用画图板来测试 黄框 代表 电脑屏幕 的范围,将黄框的宽高映射到电脑屏幕的宽高。 食指竖起并且中指弯下 时

    2024年02月06日
    浏览(40)
  • Opencv + MediaPipe -> 手势识别

    一、概述         OpenCV(Open Source Computer Vision Library)是一个跨平台的计算机视觉库,它提供了许多用于图像和视频处理的功能,包括图像和视频的读取、预处理、特征提取、特征匹配、目标检测等。OpenCV是C++编写的,也提供了Python、Java等语言的接口,可以方便地在不同

    2024年02月05日
    浏览(75)
  • 计算机视觉之手势、面部、姿势捕捉以Python Mediapipe为工具

    计算机视觉之手势、面部、姿势捕捉以 Python Mediapipe为工具 Mediapipe 是一个开源且强大的Python库,由Google开发和维护。它提供了丰富的工具和功能,用于处理实时多媒体数据。它可以帮助开发者快速构建各种视觉和音频处理应用,并允许他们灵活地定制和扩展库的功能。 Medi

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

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

    2024年02月11日
    浏览(40)
  • 计算机竞赛 题目:基于机器视觉opencv的手势检测 手势识别 算法 - 深度学习 卷积神经网络 opencv python

    🔥 优质竞赛项目系列,今天要分享的是 基于机器视觉opencv的手势检测 手势识别 算法 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-senior/postgraduate 普通机器视觉手势检测的基本流程如下: 其中轮廓的提取,多边形

    2024年02月07日
    浏览(75)
  • MediaPipe+OpenCV 实现实时手势识别(附Python源码)

    MediaPipe官网:https://developers.google.com/mediapipe MediaPipe仓库:https://github.com/google/mediapipe MediaPipe 是一个由 Google 开发的开源跨平台机器学习框架,用于构建视觉和感知应用程序。它提供了一系列预训练的机器学习模型和工具,使开发者能够轻松地构建基于计算机视觉和机器学习的

    2024年02月07日
    浏览(43)
  • 使用MediaPipe和OpenCV的Python实现手势识别

    手势识别技术是一种非常有用的技术,它可以将人类的手势转化为计算机可以理解的形式,从而实现更加自然、快速和直观的交互方式。本文将介绍一种基于MediaPipe和OpenCV的手势识别技术,可以实现对手势的实时识别和分析。 MediaPipe是一种开源的机器学习框架,可以用于构建

    2024年02月14日
    浏览(46)
  • python+opencv+mediapipe实现手势检测上下左右(含完整代码)

    应用场景:ai换脸,根据左右手势选择图片,上下则表示选中。 版本号:python3.7(一开始是3.6,但是mediapipe最低就是3.7 因为网上检测的都不太准,所以我在判断的时候加入了如果70次里55次检测的是左才返回左,测试完之后效果还可以,蛮准的。判断方法想的头都要秃了。 实

    2024年04月11日
    浏览(47)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包