12- 虚拟计算机项目 (OpenCV及手部追踪) (项目十二)

项目要点

  • 不使用摄像头, 通过将视频聊天的方式实现
  • detector = HandDetector(maxHands = 1, detectionCon= 0.8)  # 创建hand detector 追踪手
    • hands, img = detector.findHands(img, flipType=False)
      • hands: 检测到的手部信息,包含:21个关键点坐标,检测框坐标及宽高,检测框中心坐标,检测出是哪一只手。

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

    • lmlist = hands[0]['lmList']    # 找到食指和中指,计算两者的距离

    • length, _, img = detector.findDistance(lmlist[8], lmlist[12], img)  # 计算手指的距离

  • 翻转视频: img = cv2.flip(img, 1)  # 1 > 0, 表示左右反转
  • 如何在没有摄像头的情况下进行视频截取(通过qq视频, 然后进行截图), 通过将视频聊天窗口放置于桌面某个位置, 然后对某个位置进行实时截图, 然后实现虚拟计算机的项目.

核心代码 (qq视频截图显示):

import numpy as np
from PIL import ImageGrab
import cv2

# 屏幕截图, 然后显示, 打开摄像头,显示每一帧图片
img = np.array(ImageGrab.grab(bbox = (1500, 600, 1850, 1080)))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
print(img.shape)  # (480, 350, 3)

cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 项目难点:
    • 存在重复点击的问题,
    • 距离检测不方便


1  实现虚拟计算机 (项目代码)

class Button:      # 创建类button:
    def __init__(self, pos, width, height, value):
        self.pos = pos
        self.width = width
        self.height = height
        self.value = value
        
    def draw(self, img):
        # 绘制计算器的小格子 先画灰色的矩形,再画矩形的边框
        cv2.rectangle(img, (self.pos[0], self.pos[1]), (self.pos[0] + self.width, self.pos[1] + self.height), (255, 255, 255), 1)
        cv2.putText(img, self.value, (self.pos[0] + 10, self.pos[1] + 25), cv2.FONT_HERSHEY_PLAIN, 1, (255, 255, 255), 1)
        
    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] + 5, self.pos[1] + 20), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 0), 3)
            return True
        else:
            return False

 1.1 执行部分

import numpy as np
from PIL import ImageGrab
import cv2
from cvzone.HandTrackingModule import HandDetector

button_values = [['7', '8', '9', '*'],
                 ['4', '5', '6', '-'],
                 ['1', '2', '3', '+'],
                 ['0', '/', '.', '=']]
button_list = []
for x in range(4):
    for y in range(4):
        x_pos = 180 + x * 30
        y_pos = 200 + y * 40
        # 调函数 botton
        button = Button((x_pos, y_pos), 30, 40, button_values[y][x])   
        button_list.append(button)

# 创建hand detector 追踪手
detector = HandDetector(maxHands = 1, detectionCon= 0.8)

my_equation = ''
delay_counter = 0
my_value = 0
        
while True:
    # 获取截图,通过视频的方式进行实现要求
    screen = np.array(ImageGrab.grab(bbox = (1500, 620, 1850, 1080)))
    img = cv2.cvtColor(screen, cv2.COLOR_BGR2RGB)
    # 显示窗口太小 显示的视角与实际相反
    img = cv2.flip(img, 1) # 1 > 0, 表示左右反转
    
    # 检测手
    hands, img = detector.findHands(img, flipType=False)
    # print(img.shape)   # (460, 350, 3)
    
    for button in button_list:
        button.draw(img)

    # 创建显示结果的窗口
    w1 = 180
    h1 = 160
    cv2.rectangle(img, (w1, h1), (w1 + 120, h1 + 40), (255, 255, 255), 1)
    
    if hands:
        # 找到食指和中指,计算两者的距离
        lmlist = hands[0]['lmList']
        length, _, img = detector.findDistance(lmlist[8], lmlist[12], img)
        # 根据食指和中指的距离判断
        x, y = lmlist[8]    # 得到的是x, y的位置
        print(lmlist[8])
        # 外部定义一个true 
        
        if length < 10 and delay_counter == 0:
            if my_value == '=':
                my_equation = ''
            delay_counter = 1
            love = False
            for i, button in enumerate(button_list):   # 调函数 Button
                print(button)
                if button.check_click(x, y):
                    # 说明是正确点击,显示点击数字
                    my_value = button_values[int(i % 4)][int(i / 4)]
                    # 如果是等号,要计算,如果不是,一直显示
                    if my_value == '=':
                        try:
                            my_equation = str(eval(my_equation))[:11]   # [:11] 结果值只取前11位
                        except Exception:
                            # 非法的数学逻辑
                            # 重新输入
                            my_equation = ''
                    else:
                        # 字符串的拼接
                        my_equation += my_value

    # 重置delay_counter
    if delay_counter != 0:
        # print(delay_counter)  # 有手势动作会增加
        delay_counter += 1
        if  delay_counter > 10:   # 间隔10帧视频后重新计数
            delay_counter = 0

    cv2.putText(img, my_equation, (190 ,190), cv2.FONT_HERSHEY_PLAIN, 1, (255, 255, 255), 1)  # 显示计算过程
    cv2.imshow('img', img)
    key = cv2.waitKey(1)
    if key == ord('q'):
        break
    elif key == ord('c'):
        # 清空输出
        my_equation = ''

cv2.waitKey(0)
cv2.destroyAllWindows()

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值