写在前面:程序不是很难,只是调用了很多的库,安装好库后点击运行即可。

pip install 以下这些
mediapipe==0.8.9
numpy
autopy
numpy
opencv-python

如果还有缺少按照相应的报错提示安装对应的库即可。

通过食指控制鼠标移动,五指控制上滑下滑,双指右键。

具体效果不展示了,因为不愿意露脸,大家自己尝试一下就知道了。

demo_windows.py

"""
功能:手势操作电脑鼠标
1、使用OpenCV读取摄像头视频流;
2、识别手掌关键点像素坐标;
3、根据坐标计算不同的手势模式
4、控制对应的鼠标操作:移动、单击、双击、右击、向上滑、向下滑、拖拽
"""# 导入其他依赖包
import timeimport autopy
# 导入OpenCV
import cv2
import numpy as np
import pyautogui# 导入handprocess
import handProcess
from utils import Utils# 识别控制类
class VirtualMouse:def __init__(self):# image实例,以便另一个类调用self.image=None# 主函数def recognize(self):handprocess = handProcess.HandProcess(False,1)utils = Utils()fpsTime = time.time()cap = cv2.VideoCapture(0)# 视频分辨率resize_w = 960resize_h = 720# 控制边距frameMargin = 100# 屏幕尺寸screenWidth, screenHeight = pyautogui.size() # 柔和处理参数stepX, stepY = 0, 0finalX, finalY = 0, 0smoothening = 7action_trigger_time = {'single_click':0,'double_click':0,'right_click':0}mouseDown = False# fps = cap.get(cv2.CAP_PROP_FPS)# fps = 18# videoWriter = cv2.VideoWriter('./record_video/out'+str(time.time())+'.mp4', cv2.VideoWriter_fourcc(*'H264'), fps, (618,720))while cap.isOpened():action_zh = ''success, self.image = cap.read()# 裁剪self.image = cv2.resize(self.image, (resize_w, resize_h))if not success:print("空帧")continue# 提高性能self.image.flags.writeable = False# 转为RGBself.image = cv2.cvtColor(self.image, cv2.COLOR_BGR2RGB)# 镜像,需要根据镜头位置来调整self.image = cv2.flip(self.image, 1)# 处理手掌self.image = handprocess.processOneHand(self.image)# 画框框cv2.rectangle(self.image, (frameMargin, frameMargin), (resize_w - frameMargin, resize_h - frameMargin),(255, 0, 255), 2)# 获取动作self.image,action,key_point = handprocess.checkHandAction(self.image,drawKeyFinger=True)action_zh = handprocess.action_labels[action]if key_point:# 映射距离x3 = np.interp(key_point[0], (frameMargin, resize_w - frameMargin), (0, screenWidth))y3 = np.interp(key_point[1], (frameMargin, resize_h - frameMargin), (0, screenHeight))# 柔和处理finalX = stepX + (x3 - stepX) / smootheningfinalY = stepY + (y3 - stepY) / smootheningnow = time.time() if action_zh == '鼠标拖拽':# 原始方法# pyautogui.dragTo(finalX, finalY)     # 解决windows可能无效及卡顿问题if not mouseDown:pyautogui.mouseDown(button='left')mouseDown = Trueautopy.mouse.move(finalX, finalY)else:if mouseDown:pyautogui.mouseUp(button='left')mouseDown = Falseif action_zh == '鼠标移动':# pyautogui.moveTo(finalX, finalY)# 解决移动卡顿的问题autopy.mouse.move(finalX, finalY)elif action_zh == '单击准备':passelif action_zh == '触发单击'  and  (now - action_trigger_time['single_click'] > 0.3):pyautogui.click()action_trigger_time['single_click'] = nowelif action_zh == '右击准备':passelif action_zh == '触发右击' and  (now - action_trigger_time['right_click'] > 2):pyautogui.click(button='right')  action_trigger_time['right_click'] = nowelif action_zh == '向上滑页':pyautogui.scroll(30)elif action_zh == '向下滑页':pyautogui.scroll(-30)stepX, stepY = finalX, finalYself.image.flags.writeable = Trueself.image = cv2.cvtColor(self.image, cv2.COLOR_RGB2BGR)# 显示刷新率FPScTime = time.time()fps_text = 1/(cTime-fpsTime)fpsTime = cTimeself.image = utils.cv2AddChineseText(self.image, "帧率: " + str(int(fps_text)),  (10, 30), textColor=(255, 0, 255), textSize=50)# 显示画面# videoWriter.write(self.image) self.image = cv2.resize(self.image, (resize_w//2, resize_h//2))cv2.imshow('virtual mouse', self.image)if cv2.waitKey(5) & 0xFF == 27:breakcap.release()# 开始程序
control = VirtualMouse()
control.recognize()

handProcess.py

"""
! author: enpei
! date: 2021-12-15
功能:封装手部识别常用功能,简化Demo代码复杂度
"""
# 导入OpenCV
import cv2
# 导入mediapipe
import mediapipe as mp
import time
import math
import numpy as np
from utils import Utilsclass HandProcess:def __init__(self,static_image_mode=False,max_num_hands=2):# 参数self.mp_drawing = mp.solutions.drawing_utilsself.mp_drawing_styles = mp.solutions.drawing_stylesself.mp_hands = mp.solutions.handsself.hands = self.mp_hands.Hands(static_image_mode=static_image_mode,min_detection_confidence=0.7,min_tracking_confidence=0.5,max_num_hands=max_num_hands)self.landmark_list = []self.action_labels = {'none': '无','move': '鼠标移动','click_single_active': '触发单击','click_single_ready': '单击准备','click_right_active': '触发右击','click_right_ready': '右击准备','scroll_up': '向上滑页','scroll_down': '向下滑页','drag': '鼠标拖拽'}self.action_deteted = ''# 检查左右手在数组中的indexdef checkHandsIndex(self,handedness):# 判断数量if len(handedness) == 1:handedness_list = [handedness[0].classification[0].label]else:handedness_list = [handedness[0].classification[0].label,handedness[1].classification[0].label]return handedness_list# 计算两点点的距离def getDistance(self,pointA,pointB):return math.hypot((pointA[0]-pointB[0]),(pointA[1]-pointB[1]))# 获取坐标    def getFingerXY(self,index):return (self.landmark_list[index][1],self.landmark_list[index][2])# 绘制相关点def drawInfo(self,img,action):thumbXY,indexXY,middleXY = map(self.getFingerXY,[4,8,12])if action == 'move':img = cv2.circle(img,indexXY,20,(255,0,255),-1)elif action == 'click_single_active':middle_point = int(( indexXY[0]+ thumbXY[0])/2),int((  indexXY[1]+ thumbXY[1] )/2)img = cv2.circle(img,middle_point,30,(0,255,0),-1)elif action == 'click_single_ready':img = cv2.circle(img,indexXY,20,(255,0,255),-1)img = cv2.circle(img,thumbXY,20,(255,0,255),-1)img = cv2.line(img,indexXY,thumbXY,(255,0,255),2)elif action == 'click_right_active':middle_point = int(( indexXY[0]+ middleXY[0])/2),int((  indexXY[1]+ middleXY[1] )/2)img = cv2.circle(img,middle_point,30,(0,255,0),-1)elif action == 'click_right_ready':img = cv2.circle(img,indexXY,20,(255,0,255),-1)img = cv2.circle(img,middleXY,20,(255,0,255),-1)img = cv2.line(img,indexXY,middleXY,(255,0,255),2)return img# 返回手掌各种动作def checkHandAction(self,img,drawKeyFinger=True):upList = self.checkFingersUp()action = 'none'if len(upList) == 0:return img,action,None# 侦测距离dete_dist = 100# 中指key_point = self.getFingerXY(8)# 移动模式:单个食指在上,鼠标跟随食指指尖移动,需要smooth处理防抖if (upList == [0,1,0,0,0]):action = 'move'# 单击:食指与拇指出现暂停移动,如果两指捏合,触发单击if (upList == [1,1,0,0,0]):l1 = self.getDistance(self.getFingerXY(4),self.getFingerXY(8))action = 'click_single_active'  if l1 < dete_dist else  'click_single_ready'                # 右击:食指、中指出现暂停移动,如果两指捏合,触发右击if (upList == [0,1,1,0,0]):l1 = self.getDistance(self.getFingerXY(8),self.getFingerXY(12))action = 'click_right_active' if l1 < dete_dist else 'click_right_ready'# 向上滑:五指向上if (upList == [1,1,1,1,1]):action = 'scroll_up'# 向下滑:除拇指外四指向上if (upList == [0,1,1,1,1]):action = 'scroll_down'# 拖拽:拇指、食指外的三指向上if (upList == [0,0,1,1,1]):# 换成中指key_point = self.getFingerXY(12)action = 'drag'# 根据动作绘制相关点img = self.drawInfo(img,action) if drawKeyFinger else imgself.action_deteted = self.action_labels[action]return img,action,key_point# 返回向上手指的数组def checkFingersUp(self):fingerTipIndexs = [4,8,12,16,20]upList = []if len(self.landmark_list) == 0:return upList# 拇指,比较x坐标if self.landmark_list[fingerTipIndexs[0]][1] < self.landmark_list[fingerTipIndexs[0]-1][1]:upList.append(1)else:upList.append(0)# 其他指头,比较Y坐标for i in range(1,5):if self.landmark_list[fingerTipIndexs[i]][2] < self.landmark_list[fingerTipIndexs[i]-2][2]:upList.append(1)else:upList.append(0)return upList# 分析手def processOneHand(self,img,drawBox=True,drawLandmarks=True):utils = Utils()results = self.hands.process(img)self.landmark_list = []if results.multi_hand_landmarks:for hand_index,hand_landmarks in enumerate(results.multi_hand_landmarks):if drawLandmarks: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())# 遍历landmarkfor landmark_id, finger_axis in enumerate(hand_landmarks.landmark):h,w,c = img.shapep_x,p_y = math.ceil(finger_axis.x * w), math.ceil(finger_axis.y * h)self.landmark_list.append([landmark_id, p_x, p_y,finger_axis.z])# 框框和labelif drawBox:x_min,x_max =  min(self.landmark_list,key=lambda i : i[1])[1], max(self.landmark_list,key=lambda i : i[1])[1]y_min,y_max =  min(self.landmark_list,key=lambda i : i[2])[2], max(self.landmark_list,key=lambda i : i[2])[2]img = cv2.rectangle(img,(x_min-30,y_min-30),(x_max+30,y_max+30),(0, 255, 0),2)img = utils.cv2AddChineseText(img, self.action_deteted,  (x_min-20,y_min-120), textColor=(255, 0, 255), textSize=60)return img

utils.py

# 导入PIL
from PIL import Image, ImageDraw, ImageFont
# 导入OpenCV
import cv2
import numpy as npclass Utils:def __init__(self):pass# 添加中文def cv2AddChineseText(self,img, text, position, textColor=(0, 255, 0), textSize=30):if (isinstance(img, np.ndarray)):  # 判断是否OpenCV图片类型img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))# 创建一个可以在给定图像上绘图的对象draw = ImageDraw.Draw(img)# 字体的格式fontStyle = ImageFont.truetype("./fonts/simsun.ttc", textSize, encoding="utf-8")# 绘制文本draw.text(position, text, textColor, font=fontStyle)# 转换回OpenCV格式return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)

手势控制鼠标(源码)相关推荐

  1. c++ opencv 通过网络连接工业相机_使用OpenCV进行手势控制游戏+源码分享

    前期文章链接: 霍夫变换--形状特征提取算法:车道线检测 开源自动驾驶汽车数据集 基于深度学习和神经网络的重要基础及方法概要 深度学习背后的数学思想 正文: 在本文中,您将了解使用OpenCV在Pyt ...

  2. 利用Kinect实现用指尖隔空控制鼠标(源码放出)

    简介 此程序为利用Kinect实现用手指隔空控制鼠标,是我另一个项目的一部分,因为在另外那个项目中鼠标的click是通过一种特殊的方式实现的,因此这个程序只实现了用手控制鼠标的移动,并没有点击的功能. ...

  3. 压枪源码,移动鼠标源码,监听鼠标源码,控制鼠标移动源码,控制鼠标移动脚本

    压枪源码,移动鼠标源码,监听鼠标源码,控制鼠标移动源码,控制鼠标移动脚本 加了很多注释了,肯定能看懂,双开火键,左键正常,侧键直接压开 先ahk官网下载安装后就能直接运行这个ahk文件了 一开始尝试p ...

  4. 手势控制鼠标进行操作的方法和源码

    网上有不少用手势控制鼠标移动进行简单操作的视频 于是我也做了一个 实现方法简述: 1.肤色检测找到手势区域,(加上kalman滤波等会提高准确度,但也会影响实时性), 2.判断手势,只有两种,掌(只要 ...

  5. 简易实现AI虚拟鼠标—手势控制鼠标

    先看一下效果: 链接至抖音(这是我自己录的,用手势控制鼠标来刷抖音) 实现起来很简单,都是在调用人家的库~~.代码参考的是这个网站(原教程及代码网址)中的Project 4 - Al Virtual ...

  6. 机器视觉贴片机控制软件系统源码 机器视觉贴片机控制系统源码2套(全套源程序和图纸)

    机器视觉贴片机控制软件系统源码 机器视觉贴片机控制系统源码2套(全套源程序和图纸) 软件界面图片: YID:839622531392254c***y

  7. python人工智能【隔空手势控制鼠标】“解放双手“

    大家好,我是csdn的博主:lqj_本人 这是我的个人博客主页: lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识h ...

  8. 易语言局域网 php 控制,易语言控制端源码,易语言被控制源码,易语言局域网远程控制源码...

    下面我们对易语言控制端源码,易语言被控制源码,易语言局域网远程控制源码文件阐述相关使用资料和易语言控制端源码,易语言被控制源码,易语言局域网远程控制源码文件的更新信息. 易语言控制端源码,易语言被控制 ...

  9. 松下伺服电机与驱动器A6系列的modbus控制SDK源码

    松下伺服电机与驱动器A6系列的modbus控制SDK源码前段时间,有个非标的项目用到了两台松下伺服电机电机,伺服驱动器为MINAS-A6/A6L系列 ,一台用于控制行走轴的前进.后退,一台用于控制旋转 ...

  10. 雕刻机6轴usb控制卡源码RTCP算法双源码含pcb图

    雕刻机6轴usb控制卡源码RTCP算法双源码含pcb图,,可真正使用 ID:1828639828742992你妹说的对

最新文章

  1. Python logging调用Logger.info方法的处理过程
  2. 网站SEO优化之如何提升网站的流量?
  3. [转]ToolTip在VC中的使用
  4. org.apache.poi.openxml4j.exceptions.InvalidOperationException: Can't open the specified file
  5. 实现pick和reigister
  6. 2.word转换为pdf
  7. java排序算法 sort_Java排序算法之SleepSort排序示例
  8. 动态规划之LIS(最长上升子序列)
  9. 数据库原理及应用(MySQL版)
  10. 高性能MySQL概述
  11. 频谱分析仪二次开发|频谱分析仪程控软件NS-Analyzer
  12. 复变函数总结一:复变函数
  13. JavaScript随机生成信用卡卡号的方法
  14. 使用Echarts制作散点图
  15. 石油大学个人训练赛(一)补题----问题 D: 卡片
  16. ArcGIS 裁剪地图显示范围
  17. 影响stable diffusion的embedding训练效率的部分问题和拟解决办法
  18. 端午特供——小朋友都会写的【狂扁·大粽子】
  19. 计算机一级ppt演示文稿第5套,PPT | 操作题第 13 套
  20. 小白从0学习推荐系统 ---01 推荐系统简介

热门文章

  1. 2019最新易桥(HttpPrinter) web打印控件完整版版|HttpPrinter web打印控件下载
  2. NCM格式如何转换为Mp3-音乐格式ncm转换mp3工具
  3. spyder python下载_Spyder Python软件-Spyder Python下载-最火手机站
  4. 魅族android密码,魅族手机Flyme账户密码或密保忘记解决办法
  5. 芯烨 XP-350b 打印机驱动
  6. 有没有可以帮忙lua解密一下的大概是这样一个压缩包
  7. HTTP协议格式和header、交互过程
  8. GIT 操作中 Reinitialized existing Git repository in.......解决方法?
  9. X509Certificate证书如何获取16位长度serial number?
  10. 购物网站的设计与实现论文