AI项目二:基于mediapipe的虚拟鼠标控制

news2024/10/7 10:24:36

若该文为原创文章,转载请注明原文出处。

一、项目介绍

由于博主太懒,mediapipe如何实现鼠标控制的原理直接忽略,最初的想法是想控制摄像头识别手指控制鼠标,达到播放电影的效果。基本上效果也是可以的。简单的说是使用mediapipe检测出手指的关键点,通过检测食指关键点去移动鼠标,当食指和中指距离小于一定值,当成点击事件处理。

二、环境搭建

使用的是miniconda3终端,前面有提及如何安装,不懂或不明白,自行百度。

1、打开终端

2、创建mediapipe虚拟环境

conda create -n mediapipe_env python=3.8

创建过程中提示如个界面,输入y

 等待一会,就创建好了,如果出错,自行换 conda源。

 根据提示,激活环境

3、激活环境

conda activate mediapipe_env

三、依赖安装

在编写代码前,需要先在安装mediapipe等一些依赖,安装前确保环境已经被激活。

1、安装mediapipe

pip install mediapipe -i https://pypi.tuna.tsinghua.edu.cn/simple 

2、安装numpy

pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple

3、安装autopy

pip install autopy -i https://pypi.tuna.tsinghua.edu.cn/simple

4、安装opencv

pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple

四、代码及测试

代码直接使用notepad++编辑,看个人习惯,可以使用VS或pycharm或其他的

运行直接在终端操作。使用pycharm等需要自行搭建环境。

下面直接上代码

1、虚拟鼠标

AiVirtualMouse.py

import cv2
import HandTrackingModule as htm
import autopy
import numpy as np
import time


##############################
wCam, hCam = 1080, 720
frameR = 100
smoothening = 5
##############################
cap = cv2.VideoCapture(0)  # 若使用笔记本自带摄像头则编号为0  若使用外接摄像头 则更改为1或其他编号
cap.set(3, wCam)
cap.set(4, hCam)
pTime = 0
plocX, plocY = 0, 0
clocX, clocY = 0, 0

detector = htm.handDetector()
wScr, hScr = autopy.screen.size()
# print(wScr, hScr)

while True:
    success, img = cap.read()
    # 1. 检测手部 得到手指关键点坐标
    img = detector.findHands(img)
    cv2.rectangle(img, (frameR, frameR), (wCam - frameR, hCam - frameR), (0, 255, 0), 2,  cv2.FONT_HERSHEY_PLAIN)
    lmList = detector.findPosition(img, draw=False)

    # 2. 判断食指和中指是否伸出
    if len(lmList) != 0:
        x1, y1 = lmList[8][1:]
        x2, y2 = lmList[12][1:]
        fingers = detector.fingersUp()

        # 3. 若只有食指伸出 则进入移动模式
        if fingers[1] and fingers[2] == False:
            # 4. 坐标转换: 将食指在窗口坐标转换为鼠标在桌面的坐标
            # 鼠标坐标
            x3 = np.interp(x1, (frameR, wCam - frameR), (0, wScr))
            y3 = np.interp(y1, (frameR, hCam - frameR), (0, hScr))

            # smoothening values
            clocX = plocX + (x3 - plocX) / smoothening
            clocY = plocY + (y3 - plocY) / smoothening

            autopy.mouse.move(wScr - clocX, clocY)
            cv2.circle(img, (x1, y1), 15, (255, 0, 255), cv2.FILLED)
            plocX, plocY = clocX, clocY

        # 5. 若是食指和中指都伸出 则检测指头距离 距离够短则对应鼠标点击
        if fingers[1] and fingers[2]:
            length, img, pointInfo = detector.findDistance(8, 12, img)
            if length < 40:
                cv2.circle(img, (pointInfo[4], pointInfo[5]),
                           15, (0, 255, 0), cv2.FILLED)
                autopy.mouse.click()

    cTime = time.time()
    fps = 1 / (cTime - pTime)
    pTime = cTime
    cv2.putText(img, f'fps:{int(fps)}', [15, 25],
                cv2.FONT_HERSHEY_PLAIN, 2, (255, 0, 255), 2)
    cv2.imshow("Image", img)
    cv2.waitKey(1)

HandTrackingModule.py

import cv2
import mediapipe as mp
import time
import math

class handDetector():
    def __init__(self, mode=False, maxHands=2, detectionCon=0.8, trackCon=0.8):
        self.mode = mode
        self.maxHands = maxHands
        self.detectionCon = detectionCon
        self.trackCon = trackCon

        self.mpHands = mp.solutions.hands
        self.hands = self.mpHands.Hands(self.mode, self.maxHands, self.detectionCon, self.trackCon)
        self.mpDraw = mp.solutions.drawing_utils
        self.tipIds = [4, 8, 12, 16, 20]

    def findHands(self, img, draw=True):
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        self.results = self.hands.process(imgRGB)

        print(self.results.multi_handedness)  # 获取检测结果中的左右手标签并打印

        if self.results.multi_hand_landmarks:
            for handLms in self.results.multi_hand_landmarks:
                if draw:
                    self.mpDraw.draw_landmarks(img, handLms, self.mpHands.HAND_CONNECTIONS)
        return img

    def findPosition(self, img, draw=True):
        self.lmList = []
        if self.results.multi_hand_landmarks:
            for handLms in self.results.multi_hand_landmarks:
                for id, lm in enumerate(handLms.landmark):
                    h, w, c = img.shape
                    cx, cy = int(lm.x * w), int(lm.y * h)
                    # print(id, cx, cy)
                    self.lmList.append([id, cx, cy])
                    if draw:
                        cv2.circle(img, (cx, cy), 12, (255, 0, 255), cv2.FILLED)
        return self.lmList

    def fingersUp(self):
        fingers = []
        # 大拇指
        if self.lmList[self.tipIds[0]][1] > self.lmList[self.tipIds[0] - 1][1]:
            fingers.append(1)
        else:
            fingers.append(0)

        # 其余手指
        for id in range(1, 5):
            if self.lmList[self.tipIds[id]][2] < self.lmList[self.tipIds[id] - 2][2]:
                fingers.append(1)
            else:
                fingers.append(0)

        # totalFingers = fingers.count(1)
        return fingers

    def findDistance(self, p1, p2, img, draw=True, r=15, t=3):
        x1, y1 = self.lmList[p1][1:]
        x2, y2 = self.lmList[p2][1:]
        cx, cy = (x1 + x2) // 2, (y1 + y2) // 2

        if draw:
            cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), t)
            cv2.circle(img, (x1, y1), r, (255, 0, 255), cv2.FILLED)
            cv2.circle(img, (x2, y2), r, (255, 0, 255), cv2.FILLED)
            cv2.circle(img, (cx, cy), r, (0, 0, 255), cv2.FILLED)
            length = math.hypot(x2 - x1, y2 - y1)

        return length, img, [x1, y1, x2, y2, cx, cy]


def main():
    pTime = 0
    cTime = 0
    cap = cv2.VideoCapture(0)
    detector = handDetector()
    while True:
        success, img = cap.read()
        img = detector.findHands(img)        # 检测手势并画上骨架信息

        lmList = detector.findPosition(img)  # 获取得到坐标点的列表
        if len(lmList) != 0:
            print(lmList[4])

        cTime = time.time()
        fps = 1 / (cTime - pTime)
        pTime = cTime

        cv2.putText(img, 'fps:' + str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 3)
        cv2.imshow('Image', img)
        cv2.waitKey(1)


if __name__ == "__main__":
    main()

 虚拟鼠标功能,当食指和中指合在一起后,画面消失,此时界面就可以通过手指来控制。

 

运行后出现(arg0:int)-> mediapipe.python._framework_bindings.packet.PacketInvoked with: 0.5这个错误

处理方法:

修改错误提示中solution_base.py文件中595行,改为如下:

return getattr(packet_creator,'create_'+ packet_data_type.value)(True if round(data)>0 else False)

如有侵权,或需要完整代码,请及时联系博主。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/886721.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【软件测试】随笔系统测试报告

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: 软件测试 随笔系统采用 SSM 框架前后端分离的方法实现&#xff0c;本文主要针对功能&#xff1a;登录&#xff0c;注册&#xff0c;注销&#xff0c;写随笔&#xff0c;删除随笔&#xff0c;随笔详情页…

SQLite数据库实现数据增删改查

当前文章介绍的设计的主要功能是利用 SQLite 数据库实现宠物投喂器上传数据的存储&#xff0c;并且支持数据的增删改查操作。其中&#xff0c;宠物投喂器上传的数据包括投喂间隔时间、水温、剩余重量等参数。 实现功能&#xff1a; 创建 SQLite 数据库表&#xff0c;用于存储宠…

【KD】2023 ICML Linkless Link Prediction via Relational Distillation

1、简介 图神经网络(GNN)有很强的链接预测能力,但是其计算依赖于对邻居节点知识的聚合,因此导致其在实际应用中往往有较高的延迟。与GNN不同,多层感知机(MLP)在预测时不依赖于邻居节点信息,因此其推理速度更快,但也在一定程度上影响了其预测准确性。为了同时利用这两…

Linux下如何修改CPU 电源工作模式

最近处理一起历史遗留问题&#xff0c;感觉很爽。 现象&#xff1a; 背景&#xff1a;设备采用ARM&#xff0c;即rk3568处理器&#xff0c;采用Linux系统&#xff1b;主要用于视觉后端处理 现象&#xff1a;当软件运行一段时间&#xff0c;大概1个小时&#xff08;也不是很固定…

安卓开发问题记录:app:checkDebugDuplicateClasses

开发过程中报错&#xff1a; Duplicate class android.support.v4.app.INotificationSideChannel found in modules core-1.7.0-runtime (androidx.core:core:1.7.0) and support-v4-21.0.3-runtime (com.android.support:support-v4:21.0.3)按网上找到的说法&#xff1a;新引…

Java学习路线大全推荐来啦!

Java作为目前最热门使用最广泛的编程语言之一&#xff0c;许多人都想学习它。但Java学习书籍那么多&#xff0c;如何选择适合自己的呢?在这里&#xff0c;小编将为大家推荐两本Java学习书籍。 1.动力节点Java 《Java从零基础到精通》是一本Java实用教材&#xff0c;由动力节点…

Maven(四)常用命令大全

目录 一、mvn 命令参数二、mvn 插件命令1.介绍2.查看插件的使用文档3.常用的插件命令 官网地址&#xff1a; https://maven.apache.org/官方插件清单&#xff1a; https://maven.apache.org/plugins/index.html Maven 是一个强大的构建工具&#xff0c;它提供了许多命令来进行项…

EasyV用户必须了解的实操方法论|模板复用五步法

本文根据元宝 在模板复用训练课程上的分享整理而成。 从我们模板复用课程上线到现在&#xff0c;每一期我们都在反复强调&#xff1a;**如何让「所有的」EasyV用户都能搭建制作出「可以落地交付」的可视化大屏是我们课程制作的初衷&#xff0c;跳出「大屏搭建 大屏设计」的思维…

【机器视觉系统】NoobVision

NoobVision 基于Qt/C实现的视觉框架平台&#xff0c;已有多款项目成功实施 功能不算非常完善&#xff0c;但架构设计成熟 Q 2903612753

Spring事务的隔离级别介绍说明以及怎么去修改Spring事务的隔离级别

&#x1f600;前言 本篇是Spring 声明式事务系列的最后一篇介绍了Spring事务的隔离级别介绍说明 &#x1f3e0;个人主页&#xff1a;尘觉主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是尘觉&#xff0c;希望我的文章可以帮助到大家&#xff0c;您的满意是我的…

SystemVerilog中$timeformat的用法

在SystemVerilog中&#xff0c;输出信息显示时间时&#xff0c;经常会在输出信息格式中指定“%t”格式符&#xff0c;一般情况下“%t”输出的格式都是固定的&#xff0c;但是这样固定的输出显示的时间可能有时会让用户看起来感觉比较诧异&#xff0c;例如下面的示例。 【示例】…

【word密码】设置word只读模式

想要将word文档设置为只读模式&#xff0c;方法有很多&#xff0c;今天小奥超人介绍几个方法给大家。 方法一&#xff1a;文件属性 常见的、简单的设置方法&#xff0c;不用打开word文件&#xff0c;只需要右键选择文件&#xff0c;打开文件属性&#xff0c;勾选上【只读】选…

ROSE75 GAS DM蓝牙5.2双模热插拔PCB

键盘使用说明索引&#xff08;均为出厂默认值&#xff09; 软件支持&#xff08;驱动的详细使用帮助&#xff09;一些常见问题解答&#xff08;FAQ&#xff09;首次使用步骤蓝牙配对规则&#xff08;重要&#xff09;蓝牙和USB切换键盘默认层默认触发层0的FN键配置的功能默认功…

助力金融服务行业转型,NETCLOUD的全方位解决方案!

随着科技的飞速发展和数字化时代的到来&#xff0c;金融行业也面临着前所未有的变革和挑战。在这个信息爆炸的时代&#xff0c;数字化转型已经成为金融行业不可忽视的趋势。从传统的银行、保险到投资管理&#xff0c;无一不受到数字化浪潮的影响。那么&#xff0c;为什么金融行…

Android CameraX适配Android13的踩坑之路

AndroidCameraX适配Android13的踩坑之路 前言&#xff1a; 最近把AGP插件升级到8.1.0&#xff0c;新建项目的时候目标版本和编译版本都是33&#xff0c;发现之前的demo使用Camerax拍照和录像都失败了&#xff0c;于是查看了一下官网和各种资料&#xff0c;找到了Android13的适…

中远麒麟堡垒机 SQL注入漏洞复现

0x01 产品简介 中远麒麟依托自身强大的研发能力,丰富的行业经验&#xff0c;自主研发了新一代软硬件一体化统一安全运维平台一-iAudit 统一安全运维平台。该产品支持对企业运维人员在运维过程中进行统一身份认证、统一授权、统一审计、统一监控&#xff0c;消除了传统运维过程中…

十七、地物识别

描述了使用2D卷积神经网络图像识别的全过程。下载和安装标注工具,对图像进行标注,生成标注后的图像。然后对数据进行增强,划分训练集和测试集。最后通过神经网络建立分类模型,对现有图片进行分类应用。 1、Labelme工具 Labelme工具是语义分割标注工具,在地物类型或建…

《论文阅读14》FAST-LIO

一、论文 研究领域&#xff1a;激光雷达惯性测距框架论文&#xff1a;FAST-LIO: A Fast, Robust LiDAR-inertial Odometry Package by Tightly-Coupled Iterated Kalman Filter IEEE Robotics and Automation Letters, 2021 香港大学火星实验室 论文链接论文github 二、论文概…

管理类联考——逻辑——真题篇——按知识分类——汇总篇——一、形式逻辑——性质——第三节——真假推理

文章目录 第三节 性质—真假推理题—性质—两命题间的关系—①先找矛盾&#xff0c;后找包含—矛盾&#xff1a;“所有A都是B”矛盾“有的A不是B”&#xff1b;“所有A都不是B”矛盾“有的A是B”。—包含&#xff1a;“所有A都是B”→“有的A是B”&#xff1b;“所有A都不是B”…

【k8s】基于Prometheus监控Kubernetes集群安装部署

目录 基于Prometheus监控Kubernetes集群安装部署 一、环境准备 二、部署kubernetes集群 三、部署Prometheus监控平台 四、部署Grafana服务 五、grafana web操作 基于Prometheus监控Kubernetes集群安装部署 一、环境准备 IP地址 主机名 组件 192.168.100.131 k8s-ma…