IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 基于python opencv mediapape 实现的虚拟计算器 -> 正文阅读

[人工智能]基于python opencv mediapape 实现的虚拟计算器

1.环境准备

本人采用jupyter notebook作为运行环境

1.1python解释器的安装

网盘链接:https://pan.baidu.com/s/1mDv5lYJbm9rJR-fUh1bE3A

提取码:phm6

1.2anaconda的安装

网盘链接:???????https://pan.baidu.com/s/1MyHOT7hGss0SXaGeeOx8LQ

提取码:phm6

1.3jupyter的安装

打开终端输入指令

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

到这里环境大致已经搭建完成,只需要进入终端输入指令

jupyter notebook

就可以运行jupyter了,在那里启动,浏览器上的目录对应那里,为了方便建议建立一个文件夹作为jupyter notebook的工作目录,每次运行时在终端cd进入工作目录,然后再运行jupyter

1.4notebook拓展插件的安装

安装相应的拓展插件

pip install jupyter_nbextensions_configurator jupyter_contrib_nbextensions

然后进行相应的设置

jupyter contrib nbextension install --user
jupyter nbextensions_configurator enable --user

?设置结束后,重启jupyter

打开后会出现这个图标

点击进去对其进行设置

?2.相关库的准备

pip install opencv-contrib-python -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install mediapape -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install cvzone -i https://pypi.tuna.tsinghua.edu.sn/simple

?3.虚拟计算器的实现

3.1算法流程

1.打开摄像头

2.创建窗口类->绘制计算器的显示窗口

计算器的按键由外边框,内部填充,以及显示的按键文本表示,具有统一的属性,因此我们可以讲这些属性提取出来构造一个按键类

3.手部检测->点击操作->实现计算功能

3.2具体代码以及代码讲解



#创造按键类
class Button:
    #初始化传入pos按键位置,每个矩形框的宽高,矩形框的文本数据
    def __init__(self, pos, width, height, value):
    #初始化在循环前完成
        self.pos = pos
        self.width = width
        self.height = height
        self.value = value
    
    #绘图方法在循环后完成
    def draw(self, frame):
    #绘制计算器轮廓,img画板 起点pos 终点pos 颜色填充
        cv2.rectangle(frame, self.pos, (self.pos[0]+self.width, self.pos[1]+self.height), (255,255,255), cv2.FILLED)
    
    #添加边框
        cv2.rectangle(frame, self.pos, (self.pos[0]+self.width, self.pos[1]+self.height), (50,50,50), 3)
        
    #添加按键文本
        cv2.putText(frame,self.value, (self.pos[0]+30,self.pos[1]+70),cv2.FONT_HERSHEY_COMPLEX,2,(50,50,50),2)
    
    #点击后按钮绘制
    def checkClick(self, x, y):#传入食指尖坐标
        #检查食指x在哪一个按钮框内,x1<x<x1+width 控制列
        #检查食指y在哪一个按钮框内,y1<y<y1+heigth 控制行
        
        if self.pos[0] < x < self.pos[0] + self.width and self.pos[1] < y < self.pos[1] + self.height:
            #如果点击改变按钮颜色,并将文本数据绘制到数据框内
            cv2.rectangle(frame, self.pos, (self.pos[0]+self.width,self.pos[1]+self.height),(0,255,255),cv2.FILLED)
            cv2.rectangle(frame, self.pos, (self.pos[0]+self.width,self.pos[1]+self.height),(50,50,50),3)
            cv2.putText(frame, self.value, (self.pos[0]+30, self.pos[1]+70), cv2.FONT_HERSHEY_COMPLEX, 2, (0,0,255), 5)
            
            return True
        else:
            return False
        
import cv2
from cvzone.HandTrackingModule import HandDetector
import mediapipe as mp
import time
import cvzone
import pandas as pd
import numpy as np
cap=cv2.VideoCapture(0)

#解决宽高问题 cv2.VideoCapture().get(propId)
#3:CV_CAP_PROP_FRAME_WIDTH 视频流中帧的宽度。
#4:CV_CAP_PROP_FRAME_HEIGHT 视频流中帧的高度
cap.set(3, 1280)#设置框宽1080
cap.set(4, 720)#设置宽高720

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

#手部检测,置信度为0.8 最多检测一只手
detector = HandDetector(detectionCon=0.8, maxHands = 1)



#2.1创建计算器按键
#创建value列表
buttonListvalues=[['7', '8', '9', '*'],
                 ['4', '5', '6', '-'],
                 ['1', '2', '3', '+'],
                 ['0', '/', '.', '=']]


buttonList = []#存放按键信息

#创建4*4按键
for x in range(4):
    for y in range(4):
        xpos = x * 100 + 800 #得到四块宽为100的矩形的起点x坐标,从x=800开始
        ypos = y * 100 + 150 #起点y坐标 y=150
        
        #传入起点坐标及宽高
        button1 = Button((xpos, ypos), 100, 100, buttonListvalues[y][x])
        #将确定坐标的矩形框信息存入列表
        buttonList.append(button1)
"""
由于首先进行内部循环,绘制时是逐列绘制,绘制完成后buttonList=      {'7','4','1','0','8','5','2','/','9','6','3','.','*','-','+','='}
"""
myEquation = ''
delayCounter = 0

while True:
    ret, frame = cap.read()
    
    #反转图像
    #解决镜像问题
    frame = cv2.flip(frame, flipCode = 1)
    
    #检测手部关键点,返回关键点的坐标和绘制后的图像
    hands, frame = detector.findHands(frame, flipType=False,draw=True)
    
    #绘制计算器
    #首先绘制结果显示部分 width=400
    cv2.rectangle(frame, (800,50), (800+400,70+100), (255,255,255), cv2.FILLED)
    cv2.rectangle(frame, (800,50),(800+400, 70+100), (50,50,50), 3)
    
    #遍历list 调用draw 绘制每个按键
    for button in buttonList:
        button.draw(frame)
    
    #检测手指点击按键
    if hands:
        #cv2.waitKey(10000)
        lmlist = hands[0]['lmList']
        #print(np.shape(lmlist))

        #在实际运行时,发现lmlist传入的参数有误,将lmlist的形状打印,查看其参数,进行调试
        #print(np.shape(lmlist[8]))

#这里的lmlist中储存的有三个参数,但在findDistance()函数中需要传递的lmlist中的参数只有两个,分别为p1和p2的(x,y)坐标,这两个参数在lmList的前两个参数,因此对lmlist进行切片操作,得到(x,y)坐标
        lmlist[8]=lmlist[8][:2]
        lmlist[12]=lmlist[12][:2]
        #lmlist=pd.iloc(lmlist,[0,'lmList'])
        #获取食指和中指指尖距离并绘线
        #返回指尖连线长度,线条信息,绘制后的图像
        length, _, frame = detector.findDistance(p1=lmlist[8], p2=lmlist[12], img=frame)
        #print(np.shape(_))
        #获取食指坐标
        x, y=lmlist[8]
        
        #print(length)
        #如果指尖距离小于50,找到按下了哪个键
        if length < 50:
        #遍历所有按键
            
            #print(np.shape(buttonList))
            #enumrate() 将传入的列表进行处理,返回成索引一一对应其中的参数
            #enumerate   return iteration start

            for i,button in enumerate(buttonList):
             
                #点击按键 按键颜色发生变化 返回True 延时器为0才能运行
                if button.checkClick(x, y) and delayCounter==0:
                    
                    #计算
                    #找到点击按钮的编号 i 0-15  转化成索引[i%4][i//4]
                    myValue=buttonListvalues[i%4][i//4]
                    
                    if myValue== '=':
                        myEquation = str(eval(myEquation)) 
                    #eval 将字符串数据作为表达式返回一个数值
                        
                    else:
                        myEquation+=myValue#字符串直接相加
                    
                    #time.sleep(0.2)
                    #为了防止重复点击,使用一个计数器控制每次点击的间隔时长
                    #计数器 一次点击了一个键
                    delayCounter = 1
    
    #点击一个按钮以后delayCounter=1 20帧以后才能点击下一个
    
    if delayCounter != 0:
        delayCounter += 1    #延迟一帧
        if delayCounter > 50:   #10帧过去后才能再次点击
             delayCounter = 0
                
    #绘制计算表达式
    cv2.putText(frame, myEquation, (800+10,100+20), cv2.FONT_HERSHEY_PLAIN, 3, (50,50,50), 3) 
   

     #查看FPS
    cTime = time.time()#处理完一帧图片的时间
    fps = 1/(cTime-pTime)
    pTime = cTime #重置起始时间
    
    #在视频上显示fps信息,先转换成整数再变成字符串形式,文本显示坐标,文本字体,文本大小
    cv2.putText(frame, str(int(fps)),(70,50),cv2.FONT_HERSHEY_PLAIN,3,(255,0,0))
   
    cv2.imshow("image",frame)
   
    #每帧滞留时间
    key = cv2.waitKey(1)
    
    #清空计算框
    if key == ord('c'):
        myEquation = ''
    
    #退出
    if key & 0xFF==27:
        break
    
    #if cv2.waitKey(100) & 0xFF == ord('q'):
    #    break
#释放内存
cap.release()
cv2.destoryAllWindows()

3.3运行结果

?

笔者对于计算机视觉相关知识也只是学习阶段,如有改进想法或疑问可以互相交流,

邮箱:2806762759@qq.com

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:42:06  更:2022-10-08 20:44:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 23:30:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码