OpenCV--项目:虚拟计数器

server/2024/12/14 12:36:19/

OpenCV--项目:虚拟计数器

  • 代码和笔记

代码和笔记

import cv2
import numpy as np
import time
from cvzone.HandTrackingModule import HandDetector"""
项目:虚拟计数器
cvzone:cv任务开源库
mediapipe:姿态估计开源库(在cvzone里面)
"""# 打开摄像头,显示每一帧图片 0表示只有一个摄像头
# 如果是读取视频文件,则0改为视频的地址就行
cap = cv2.VideoCapture(0)# 设置窗口大小 ID+value
# 属性ID 3 和 4 来设置视频的宽度和高度
cap.set(3, 1280)
cap.set(4, 720)# 定义计数器的每一个按键
# pos坐标,width, height宽度和高度,value按键值
class Button:def __init__(self, pos, width, height, value):self.pos = posself.width = widthself.height = heightself.value = value# 在视频上画出计数器的每一个按键def draw(self, _img):# 绘制一个计数器的一个小格子# 先绘制一个实心的灰色矩形# 第一个是起始点坐标,第二个是起始点对角的那个坐标# 然后是颜色和线宽, -1表示填充cv2.rectangle(_img, (self.pos[0], self.pos[1]), (self.pos[0] + self.width, self.pos[1] + self.height), (225, 225, 225), -1)# 再画一个黑色的矩形边框cv2.rectangle(_img, (self.pos[0], self.pos[1]), (self.pos[0] + self.width, self.pos[1] + self.height), (0, 0, 0), 3)# 给矩形内赋值按键的值# 第一个是值,第二个是文本左下角坐标,第三个是字体类型# 第四个是字体大小,第五个是颜色,最后一个是线宽cv2.putText(_img, self.value, (self.pos[0] + 30, self.pos[1] + 70), cv2.FONT_HERSHEY_PLAIN, 2, (50, 50, 50), 2)# 判断手的坐标是否在按键的框里,判断是否点击def check_click(self, x, y):if self.pos[0] < x < self.pos[0] + self.width and self.pos[1] < y < self.pos[1] + self.height:# 点的时候触发一个变大的效果cv2.rectangle(img, (self.pos[0] + 3, self.pos[1] + 3), (self.pos[0] + self.width - 3, self.pos[1] + self.height - 3),(255, 255, 255), -1)cv2.putText(img, self.value, (self.pos[0] + 25, self.pos[1] + 80), cv2.FONT_HERSHEY_PLAIN, 5, (0, 0, 0), 5)return Trueelse:return False# 因为计数器有多个按键,用循环画出按键
button_values = [['7', '8', '9', '*'],['4', '5', '6', '-'],['1', '2', '3', '+'],['0', '/', '.', '=']]button_list = []
# 开始画,先画第一列,然后是第二列.....
# 注意OpenCV中纵轴的正方向是往下,先遍历列后遍历行
for x in range(4):for y in range(4):x_pos = x * 100 + 800y_pos = y * 100 + 150button = Button((x_pos, y_pos), 100, 100, button_values[y][x])button_list.append(button)# 创建手势识别器
# maxHands:最大能够识别的手数。detectionCon:检测到是手的概率
detector = HandDetector(maxHands=1, detectionCon=0.8)# 计数器公式显示
equation = ''
# 缓冲器,避免重复点击
delay_count = 0while True:# 读取每一帧图片,返回标记和图片flag, img = cap.read()# 摄像头和真实画面反了,要调整,图片翻转# 大于0,左右翻转;等于0,上下翻转;小于0,左右上下都翻转img = cv2.flip(img, 1)# 检测手,返回手和检测的图片,返回的手是一个列表(字典类型),在lmList里面,里面是手的坐标# 因为我们在摄像头就反转了,这里就不用了# 注意要先检测手,后按键hands, img = detector.findHands(img, flipType=False)# 如果flag为True,显示图片if flag:# 调用buttonfor button in button_list:button.draw(img)# 创建显示结果的窗口cv2.rectangle(img, (800, 70), (800 + 400, 70 + 80), (225, 225, 225), -1)cv2.rectangle(img, (800, 70), (800 + 400, 70 + 80), (50, 50, 50), 3)if hands:# 取出食指和中指的点,并计算两者的距离lmList = hands[0]['lmList']# lmList[8], lmList[12]代表的是食指和中指的点# 返回距离,线的描述,图片# # 最新版本的cvzone中,lmList坐标是三个值x,y,z,取出前两个值。lmList = [x[:2] for x in lmList]length, _, img = detector.findDistance(lmList[8], lmList[12], img)# 取出手指的坐标x, y = lmList[8]# 如果食指和中指之间的距离小于50,我们认为进行了点击操作# 为了防止频繁输入,设置延缓delay_countif length < 50 and delay_count == 0:for i, button in enumerate(button_list):if button.check_click(x, y):# 如果正确点击,把点中的数字显示在窗口上# 我们用枚举得到的i来算values的索引values = button_values[int(i % 4)][int(i / 4)]# 如果是'='说明要计算了# eval可以直接把字符串里面的公式或者变量,通过整合或者计算变成数字# eval计算结果 如:'1 + 2',eval后得到3if values == '=':try:equation = str(eval(equation))except Exception:# 非法数学公式,重新输出equation = ''else:# 字符串拼接equation += values# 不要频繁的输入,睡眠一下# time.sleep(0.5) 但睡眠不能完全解决问题还会导致卡顿delay_count = 1# 重置delay_count,避免重复点击if delay_count != 0:delay_count += 1if delay_count > 10:delay_count = 0# 计数器的计算公式cv2.putText(img, equation, (810, 130), cv2.FONT_HERSHEY_PLAIN, 3, (0, 0, 0), 3)cv2.imshow('img', img)# 1ms,1帧key = cv2.waitKey(1)if key == ord('q'):breakelif key == ord('c'):# 清空输出框equation = ''else:print('摄像头打开失败')breakcap.release()
cv2.destroyAllWindows()

http://www.ppmy.cn/server/150093.html

相关文章

Docker安装MySQL5.5版本数据库(图文教程)

本章教程,介绍如何使用Docker安装MySQL低版本5.5版本的数据库。 一、拉取镜像 docker pull mysql:5.5二、启动容器 docker run -d --name mysql5.5 --restart=always

一键找出图像中物体的角点

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

关于消息队列性能是否能接收 5 万个 MQ

影响性能的因素 消息队列本身的性能&#xff1a; 不同的消息队列系统&#xff08;如 RabbitMQ、Kafka、RocketMQ 等&#xff09;有不同的性能特点。例如&#xff0c;Kafka 是高吞吐量的分布式消息队列&#xff0c;能够处理大规模的消息流。它的性能在设计上可以通过分区&…

deepin下载mysql教程

官方下载 Mysql 8.2 支持 here 解压到需要的文件夹去 (建议放到 /opt/mysql/mysql8) 建立 mysql 的用户与组 &#xff08;groupadd mysql && useradd -r -g mysql mysql&#xff09; 创建软链接到系统中,后继服务与配置中会使用到 cd /usr/local &&…

12.13 深度学习-空间注意力仿射变换STN

# 就是对图像做一个仿射 变换 仿射变换的参数要去学习 直接用nn.Linear()就行 # 仿射变换的原理就是 线性变换 # 这个仿射变换要加在模型最开始的地方 import torch import torch.nn as nn import torch.nn.functional as F class STN(nn.Module): def __init__(self, c, …

【Unity高级】如何获取着色器(Shader)的关键词

在动态设置Shader时&#xff0c;会需要通过EnableKeyword, DisableKeyword来完成。但一个Shader有哪些关键词呢&#xff1f;Unity的文档中并没有列出来&#xff0c;但我们可以通过遍历Shader的KeywordSpace来查看。 1. 代码如下 using UnityEngine;public class KeywordExamp…

中信建投张青减持交易课堂:金融智慧与公益的交响曲

在当今瞬息万变的金融市场中&#xff0c;中信建投张青减持交易课堂如同一股清流&#xff0c;不仅以其专业的金融培训体系引领行业风向&#xff0c;更将公益精神深深融入教育之中&#xff0c;谱写了一曲金融智慧与公益情怀的华美乐章。张青&#xff0c;这位在金融界享有盛誉的投…

游戏引擎学习第44天

仓库: https://gitee.com/mrxiao_com/2d_game 向量数学的重要性 矢量数学非常重要&#xff0c;因为 它在某种程度上类似于将C和C视为高于汇编语言的语言&#xff0c;从而使得我们能够以略高的层次思考问题&#xff0c;同时保留大部分性能好处和直接访问的类型。这种思维方式就…