【机器视觉案例】(8) AI视觉,手势控制电脑鼠标,附python完整代码

这篇具有很好参考价值的文章主要介绍了【机器视觉案例】(8) AI视觉,手势控制电脑鼠标,附python完整代码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

各位同学好,今天和大家分享一下如何使用 MediaPipe+Opencv 通过手势识别来控制电脑鼠标的移动和点击,如果有兴趣的话,可以代替鼠标去打游戏。先放图看效果。用画图板来测试

黄框代表电脑屏幕的范围,将黄框的宽高映射到电脑屏幕的宽高。食指竖起并且中指弯下时,移动鼠标食指和中指都竖起,并且两个指尖距离小于50时,认为是点击鼠标左上角30代表FPS值

移动鼠标移动时,食指指尖有淡蓝色圆点,表明鼠标在移动,如右图的绿色线条是鼠标移动轨迹

【机器视觉案例】(8) AI视觉,手势控制电脑鼠标,附python完整代码

点击鼠标当食指和中指间的距离小于50,食指指尖圆点变成绿色,点击鼠标,如画图板上的两个点,就是点击两下实现的。

【机器视觉案例】(8) AI视觉,手势控制电脑鼠标,附python完整代码


1. 导入工具包

# 安装工具包
pip install opencv-contrib-python  # 安装opencv
pip install mediapipe  # 安装mediapipe
# pip install mediapipe --user  #有user报错的话试试这个
pip install cvzone  # 安装cvzone
pip install autopy  # 鼠标控制单元

# 导入工具包
import numpy as np
import cv2
from cvzone.HandTrackingModule import HandDetector  # 手部追踪方法
import mediapipe as mp
import time
import autopy

21个手部关键点信息如下,本节我们主要研究食指指尖"8"中指指尖"12"的坐标信息。

【机器视觉案例】(8) AI视觉,手势控制电脑鼠标,附python完整代码


2. 手部关键点检测

(1) cvzone.HandTrackingModule.HandDetector()   手部关键点检测方法

参数:

mode: 默认为 False,将输入图像视为视频流。它将尝试在第一个输入图像中检测手,并在成功检测后进一步定位手的坐标。在随后的图像中,一旦检测到所有 maxHands 手并定位了相应的手的坐标,它就会跟踪这些坐标,而不会调用另一个检测,直到它失去对任何一只手的跟踪。这减少了延迟,非常适合处理视频帧。如果设置为 True,则在每个输入图像上运行手部检测,用于处理一批静态的、可能不相关的图像。

maxHands: 最多检测几只手,默认为 2

detectionCon: 手部检测模型的最小置信值(0-1之间),超过阈值则检测成功。默认为 0.5

minTrackingCon: 坐标跟踪模型的最小置信值 (0-1之间),用于将手部坐标视为成功跟踪,不成功则在下一个输入图像上自动调用手部检测。将其设置为更高的值可以提高解决方案的稳健性,但代价是更高的延迟。如果 mode 为 True,则忽略这个参数,手部检测将在每个图像上运行。默认为 0.5

它的参数和返回值类似于官方函数 mediapipe.solutions.hands.Hands()

(2)cvzone.HandTrackingModule.HandDetector.findHands()    找到手部关键点并绘图

参数:

img: 需要检测关键点的帧图像,格式为BGR

draw: 是否需要在原图像上绘制关键点及识别框

flipType: 图像是否需要翻转,当视频图像和我们自己不是镜像关系时,设为True就可以了

返回值:

hands: 检测到的手部信息,包含:21个关键点坐标,检测框坐标及宽高,检测框中心坐标,检测出是哪一只手。

img: 返回绘制了关键点及连线后的图像

手部检测的代码如下:

import cv2
from cvzone.HandTrackingModule import HandDetector   # 手部检测方法
import time

#(1)导数视频数据
cap = cv2.VideoCapture(0)  # 0代表自己电脑的摄像头
cap.set(3, 1280)  # 设置显示框的宽度1280
cap.set(4, 720)  # 设置显示框的高度720

pTime = 0  # 设置第一帧开始处理的起始时间

#(2)接收手部检测方法
detector = HandDetector(mode=False,  # 视频流图像 
                        maxHands=1,  # 最多检测一只手
                        detectionCon=0.8,  # 最小检测置信度 
                        minTrackCon=0.5)   # 最小跟踪置信度

#(3)处理每一帧图像
while True:
    
    # 图片是否成功接收、img帧图像
    success, img = cap.read()
    
    # 翻转图像,使自身和摄像头中的自己呈镜像关系
    img = cv2.flip(img, flipCode=1)  # 1代表水平翻转,0代表竖直翻转
    
    #(4)手部检测方法
    # 传入每帧图像, 返回手部关键点的坐标信息(字典构成的列表hands),绘制关键点后的图像img
    hands, img = detector.findHands(img, flipType=False)  # 上面反转过了,这里就不用再翻转了
    # print(hands)
    
    #(5)显示图像
    # 查看FPS
    cTime = time.time() #处理完一帧图像的时间
    fps = 1/(cTime-pTime)
    pTime = cTime  #重置起始时间
    
    # 在视频上显示fps信息,先转换成整数再变成字符串形式,文本显示坐标,文本字体,文本大小
    cv2.putText(img, str(int(fps)), (70,50), cv2.FONT_HERSHEY_PLAIN, 3, (255,0,0), 3)  
    
    # 显示图像,输入窗口名及图像数据
    cv2.imshow('image', img)    
    if cv2.waitKey(1) & 0xFF==27:  #每帧滞留20毫秒后消失,ESC键退出
        break

# 释放视频资源
cap.release()
cv2.destroyAllWindows()

打印每帧图像检测到的手部信息hands列表,由字典组成。lmList 代表21个手部关键点的像素坐标;bbox 代表检测框的左上角坐标和框的宽高;center 代表检测框的中心点的像素坐标;type 代表检测出的是左手还是右手。

----------------------------------------------------------------------------
[{'lmList': [[522, 755], [621, 761], [709, 724], [765, 675], [794, 615], [705, 629], [761, 588], [749, 643], [715, 686], [676, 599], [743, 565], [713, 637], [664, 684], [634, 565], [710, 543], [668, 622], [613, 666], [576, 533], [657, 519], [640, 580], [597, 620]],
 'bbox': (522, 519, 272, 242), 
 'center': (658, 640), 
 'type': 'Left'}]
[{'lmList': [[520, 763], [620, 774], [716, 753], [779, 707], [816, 650], [716, 655], [781, 619], [767, 677], [727, 721], [689, 627], [759, 595], [731, 667], [683, 710], [649, 594], [727, 579], [680, 653], [620, 689], [593, 558], [674, 549], [655, 608], [608, 642]],
 'bbox': (520, 549, 296, 225),
 'center': (668, 661),
 'type': 'Left'}]
----------------------------------------------------------------------------

检测结果如图所示:

【机器视觉案例】(8) AI视觉,手势控制电脑鼠标,附python完整代码


2. 移动鼠标

移动鼠标的思路是:如果检测到食指竖起,并且中指弯下,那么就认为是移动鼠标,鼠标的位置坐标是食指指尖所在的位置坐标

检测哪个手指是竖起的方法是 detector.fingersUp() ,传入检测到的某只手的手部信息hands[0]返回值由5个元素构成的列表元素为1代表该手指竖起,0代表手指弯下,例如:[0,1,1,0,0] 就代表食指和中指竖起,其他手指弯下。

当手指在摄像头画面的下半部分移动时,由于摄像头界限范围问题,手掌部分会在摄像头画面中消失,导致检测不到手部关键点,因此,在屏幕画面的偏上半部分绘制一个黄色的矩形框,手指只能在矩形框中移动,避免手部关键点的消失。

由于我们设置的矩形框大小明显要小于电脑屏幕的大小,导致手控的鼠标无法在整个电脑屏幕上移动。因此,需要将矩形框的宽和高映射到电脑屏幕的宽和高。使用线性插值方法 np.interp(x, xp, fp)  简单来说就是将变量x的范围从原来的xp映射到fp。如:np.interp(x1, (pt1[0], pt2[0]), (0, wScr)),就是将x坐标的范围从原来的 pt1[0]pt1[0]+w,映射到整个电脑屏幕  wScr

返回电脑屏幕的宽和高: autopy.screen.size()

移动鼠标的位置到坐标(x,y): autopy.mouse.move(x, y)

autopy具体使用方法见下文:https://blog.csdn.net/qq_30462003/article/details/100130472

因此,我们在上述代码中补充:

import cv2
import numpy as np
from cvzone.HandTrackingModule import HandDetector   # 手部检测方法
import time
# pip install autopy  #鼠标控制单元
import autopy

#(1)导数视频数据
wScr, hScr = autopy.screen.size()   # 返回电脑屏幕的宽和高(1920.0, 1080.0)
wCam, hCam = 1280, 720   # 视频显示窗口的宽和高
pt1, pt2 = (100,100), (1100, 500)   # 虚拟鼠标的移动范围,左上坐标pt1,右下坐标pt2

cap = cv2.VideoCapture(0)  # 0代表自己电脑的摄像头
cap.set(3, wCam)  # 设置显示框的宽度1280
cap.set(4, hCam)  # 设置显示框的高度720

pTime = 0  # 设置第一帧开始处理的起始时间

#(2)接收手部检测方法
detector = HandDetector(mode=False,  # 视频流图像 
                        maxHands=1,  # 最多检测一只手
                        detectionCon=0.8,  # 最小检测置信度 
                        minTrackCon=0.5)   # 最小跟踪置信度

#(3)处理每一帧图像
while True:
    
    # 图片是否成功接收、img帧图像
    success, img = cap.read()
    
    # 翻转图像,使自身和摄像头中的自己呈镜像关系
    img = cv2.flip(img, flipCode=1)  # 1代表水平翻转,0代表竖直翻转
    
    # 在图像窗口上创建一个矩形框,在该区域内移动鼠标
    cv2.rectangle(img, pt1, pt2, (0,255,255), 5)
    
    #(4)手部关键点检测
    # 传入每帧图像, 返回手部关键点的坐标信息(字典),绘制关键点后的图像
    hands, img = detector.findHands(img, flipType=False)  # 上面反转过了,这里就不用再翻转了
    # print(hands)
    
    # 如果能检测到手那么就进行下一步
    if hands:
        
        # 获取手部信息hands中的21个关键点信息
        lmList = hands[0]['lmList']  # hands是由N个字典组成的列表,字典包每只手的关键点信息
        
        # 获取食指指尖坐标,和中指指尖坐标
        x1, y1 = lmList[8]  # 食指尖的关键点索引号为8
        x2, y2 = lmList[12] # 中指指尖索引12
        
        
        #(5)检查哪个手指是朝上的
        fingers = detector.fingersUp(hands[0])  # 传入
        # print(fingers) 返回 [0,1,1,0,0] 代表 只有食指和中指竖起
        
        # 如果食指竖起且中指弯下,就认为是移动鼠标
        if fingers[1] == 1 and fingers[2] == 0:
            
            # 开始移动时,在食指指尖画一个圆圈,看得更清晰一些
            cv2.circle(img, (x1,y1), 15, (255,255,0), cv2.FILLED)  # 颜色填充整个圆
            
            #(6)确定鼠标移动的范围
            # 将食指的移动范围从预制的窗口范围,映射到电脑屏幕范围
            x3 = np.interp(x1, (pt1[0], pt2[0]), (0, wScr))
            y3 = np.interp(y1, (pt1[1], pt2[1]), (0, hScr))

            #(7)移动鼠标
            autopy.mouse.move(x3, y3)  # 给出鼠标移动位置坐标
   
    #(8)显示图像
    # 查看FPS
    cTime = time.time() #处理完一帧图像的时间
    fps = 1/(cTime-pTime)
    pTime = cTime  #重置起始时间
    
    # 在视频上显示fps信息,先转换成整数再变成字符串形式,文本显示坐标,文本字体,文本大小
    cv2.putText(img, str(int(fps)), (70,50), cv2.FONT_HERSHEY_PLAIN, 3, (255,0,0), 3)  
    
    # 显示图像,输入窗口名及图像数据
    cv2.imshow('image', img)    
    if cv2.waitKey(1) & 0xFF==27:  #每帧滞留20毫秒后消失,ESC键退出
        break

# 释放视频资源
cap.release()
cv2.destroyAllWindows()

效果图如下:

【机器视觉案例】(8) AI视觉,手势控制电脑鼠标,附python完整代码


3. 点击鼠标

点击鼠标的思路是:如果食指和中指同时竖起,并且食指指尖和中指指尖之间的像素距离小于50时,那么就认为是点击鼠标。

检测哪个手指是竖起的方法是上面已经解释过的 detector.fingersUp() 方法,检测指尖距离的方法是: detector.findDistance(pt1, pt2, img) pt1 pt2 是两个点的坐标,传入img来绘制指尖连线图。

点击鼠标的函数,autopy.mouse.click()

由于用手指控制鼠标时,每一帧的坐标位置的变化幅度较大,导致电脑鼠标在手指控制下很容易晃动,很难准确定位到一个目标。因此需要平滑每一帧的坐标变化,使坐标变化更缓慢一些

例如:cLocx = pLocx + (x3 - pLocx) / smooth,式中:前帧的鼠标位置的x坐标 cLocx前一帧的鼠标位置的x坐标 pLocx当前鼠标位置的x坐标 x3自定义平滑系数smooth,值越大鼠标移动就越慢,平稳性就越高。

因此,在上述代码中补充:

import cv2
import numpy as np
from cvzone.HandTrackingModule import HandDetector   # 手部检测方法
import time
import autopy

#(1)导数视频数据
wScr, hScr = autopy.screen.size()   # 返回电脑屏幕的宽和高(1920.0, 1080.0)
wCam, hCam = 1280, 720   # 视频显示窗口的宽和高
pt1, pt2 = (100,100), (1100, 500)   # 虚拟鼠标的移动范围,左上坐标pt1,右下坐标pt2

cap = cv2.VideoCapture(0)  # 0代表自己电脑的摄像头
cap.set(3, wCam)  # 设置显示框的宽度1280
cap.set(4, hCam)  # 设置显示框的高度720

pTime = 0  # 设置第一帧开始处理的起始时间

pLocx, pLocy = 0, 0  # 上一帧时的鼠标所在位置

smooth = 4  # 自定义平滑系数,让鼠标移动平缓一些

#(2)接收手部检测方法
detector = HandDetector(mode=False,  # 视频流图像 
                        maxHands=1,  # 最多检测一只手
                        detectionCon=0.8,  # 最小检测置信度 
                        minTrackCon=0.5)   # 最小跟踪置信度

#(3)处理每一帧图像
while True:
    
    # 图片是否成功接收、img帧图像
    success, img = cap.read()
    
    # 翻转图像,使自身和摄像头中的自己呈镜像关系
    img = cv2.flip(img, flipCode=1)  # 1代表水平翻转,0代表竖直翻转
    
    # 在图像窗口上创建一个矩形框,在该区域内移动鼠标
    cv2.rectangle(img, pt1, pt2, (0,255,255), 5)
    
    #(4)手部关键点检测
    # 传入每帧图像, 返回手部关键点的坐标信息(字典),绘制关键点后的图像
    hands, img = detector.findHands(img, flipType=False)  # 上面反转过了,这里就不用再翻转了
    # print(hands)
    
    # 如果能检测到手那么就进行下一步
    if hands:
        
        # 获取手部信息hands中的21个关键点信息
        lmList = hands[0]['lmList']  # hands是由N个字典组成的列表,字典包每只手的关键点信息
        
        # 获取食指指尖坐标,和中指指尖坐标
        x1, y1 = lmList[8]  # 食指尖的关键点索引号为8
        x2, y2 = lmList[12] # 中指指尖索引12

        #(5)检查哪个手指是朝上的
        fingers = detector.fingersUp(hands[0])  # 传入
        # print(fingers) 返回 [0,1,1,0,0] 代表 只有食指和中指竖起
        
        # 如果食指竖起且中指弯下,就认为是移动鼠标
        if fingers[1] == 1 and fingers[2] == 0:
            
            # 开始移动时,在食指指尖画一个圆圈,看得更清晰一些
            cv2.circle(img, (x1,y1), 15, (255,255,0), cv2.FILLED)  # 颜色填充整个圆

            #(6)确定鼠标移动的范围
            # 将食指的移动范围从预制的窗口范围,映射到电脑屏幕范围
            x3 = np.interp(x1, (pt1[0], pt2[0]), (0, wScr))
            y3 = np.interp(y1, (pt1[1], pt2[1]), (0, hScr))

            #(7)平滑,使手指在移动鼠标时,鼠标箭头不会一直晃动
            cLocx = pLocx + (x3 - pLocx) / smooth  # 当前的鼠标所在位置坐标
            cLocy = pLocy + (y3 - pLocy) / smooth            
      
            #(8)移动鼠标
            autopy.mouse.move(cLocx, cLocy)  # 给出鼠标移动位置坐标
            
            # 更新前一帧的鼠标所在位置坐标,将当前帧鼠标所在位置,变成下一帧的鼠标前一帧所在位置
            pLocx, pLocy = cLocx, cLocy
 
        #(9)如果食指和中指都竖起,指尖距离小于某个值认为是点击鼠标
        if fingers[1] == 1 and fingers[2] == 1:  # 食指和中指都竖起
         
            # 计算食指尖和中指尖之间的距离distance,绘制好了的图像img,指尖连线的信息info
            distance, info, img = detector.findDistance((x1, y1), (x2, y2), img)
            # print(distance)
            
            # 当指间距离小于50(像素距离)就认为是点击鼠标
            if distance < 50:
                
                # 在食指尖画个绿色的圆,表示点击鼠标
                cv2.circle(img, (x1,y1), 15, (0,255,0), cv2.FILLED)
                
                # 点击鼠标
                autopy.mouse.click()

    #(10)显示图像
    # 查看FPS
    cTime = time.time() #处理完一帧图像的时间
    fps = 1/(cTime-pTime)
    pTime = cTime  #重置起始时间
    
    # 在视频上显示fps信息,先转换成整数再变成字符串形式,文本显示坐标,文本字体,文本大小
    cv2.putText(img, str(int(fps)), (70,50), cv2.FONT_HERSHEY_PLAIN, 3, (255,0,0), 3)  
    
    # 显示图像,输入窗口名及图像数据
    cv2.imshow('image', img)    
    if cv2.waitKey(1) & 0xFF==27:  #每帧滞留20毫秒后消失,ESC键退出
        break

# 释放视频资源
cap.release()
cv2.destroyAllWindows()

结果图像展示,在绘图板中每点击一次就绘制一个圆圈。

【机器视觉案例】(8) AI视觉,手势控制电脑鼠标,附python完整代码文章来源地址https://www.toymoban.com/news/detail-462945.html

到了这里,关于【机器视觉案例】(8) AI视觉,手势控制电脑鼠标,附python完整代码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 软件工程毕设 基于机器视觉opencv的手势检测 手势识别 算法 - 深度学习 卷积神经网络 opencv python

    今天学长向大家介绍一个机器视觉项目 基于机器视觉opencv的手势检测 手势识别 算法 普通机器视觉手势检测的基本流程如下: 其中轮廓的提取,多边形拟合曲线的求法,凸包集和凹陷集的求法都是采用opencv中自带的函数。手势数字的识别是利用凸包点以及凹陷点和手部中心

    2024年01月17日
    浏览(76)
  • 计算机毕设 深度学习手势识别 - yolo python opencv cnn 机器视觉

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月14日
    浏览(61)
  • opencv实战项目 手势识别-手势控制鼠标

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

    2024年02月13日
    浏览(48)
  • 毕业设计-基于机器视觉的手势识别系统-OPENCV

    目录 前言 课题背景和意义 实现技术思路 一、系统总体设计 二、手势区域特征提取 三、系统设计与实现 四、总结 实现效果图样例 最后     📅大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年

    2024年02月08日
    浏览(64)
  • 计算机竞赛 基于机器视觉的手势检测和识别算法

    🔥 优质竞赛项目系列,今天要分享的是 基于深度学习的手势检测与识别算法 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-senior/postgraduate 废话不多说,先看看学长实现的效果吧 主流的手势分割方法主要分为静态手

    2024年02月11日
    浏览(54)
  • 基于ESP32-CAM 和 OpenCV 设计的手势控制虚拟鼠标

    概述 在本文中,我们将使用 ESP32-CAM 和 OpenCV开发 手势控制虚拟鼠标 。ESP32  Camera Module 和 Python 程序可用于无线控制 鼠标跟踪 和 点击 操作。 入门者必须具备 Python、 图像处理 、嵌入式系统以及物联网的丰富知识。首先,我们将了解如何控制鼠标跟踪和单击,以及运行 pyt

    2024年02月09日
    浏览(51)
  • 互联网加竞赛 基于机器视觉的手势检测和识别算法

    🔥 优质竞赛项目系列,今天要分享的是 基于深度学习的手势检测与识别算法 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-senior/postgraduate 废话不多说,先看看学长实现的效果吧 主流的手势分割方法主要分为静态手

    2024年01月20日
    浏览(47)
  • 宇树A1机器狗手势控制

    在上一篇博客的基础上,结合手势识别和实验室的unitreeA1机器狗做了一个机器狗的手势控制,可以实现手势控制机器狗的前后左右平动。 1、需要对ROS的话题通信机制及其环境配置有一定了解。 2、建议先在Windows上跑通上一篇博客的手势识别模型再来进行机器狗的手势控制。

    2024年02月06日
    浏览(34)
  • AI:152- 利用深度学习进行手势识别与控制

    本文收录于专栏:精通AI实战千例专栏合集 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 每一个案例都附带关键代码,详细讲解供大家学习,希望可以帮到大家。正在不断更新中~ 随着人工智能技术的不断发

    2024年04月15日
    浏览(72)
  • AI:83-基于深度学习的手势识别与实时控制

    🚀 本文选自专栏:人工智能领域200例教程专栏 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的代码,详细讲解供大家学习,希望可以帮到大家。欢迎订阅支持,正在

    2024年04月24日
    浏览(49)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包