python 中用opencv开发虚拟键盘------可以只选择一个单词不会出现一下选择多个

一. 介绍

OpenCV是最流行的计算机视觉任务库,它是用于机器学习、图像处理等的跨平台开源库,用于开发实时计算机视觉应用程序。

CVzone 是一个计算机视觉包,它使用 OpenCV 和 Media Pipe 库作为其核心,使我们易于运行,如手部跟踪、人脸检测、面部标志检测、姿势估计等,以及图像处理和其他计算机视觉。

二. 效果

python 中用opencv开发虚拟键盘------可以只选择一个单词不会出现一下选择多个_第1张图片

三. 重点

多的我也就我讲了,网络上的其他博主写的也是非常好了,我这里就主要介绍那个避免一次输入多个相同的字母,以及如何一次输入相同的字母.

代码如下:


import cv2
import cvzone
from cvzone.HandTrackingModule import HandDetector
from time import sleep
import numpy as np
from pynput.keyboard import Controller

cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
cap.set(3, 1280)
cap.set(4, 720)

detector = HandDetector(detectionCon=0.8)
keyboard_keys = [["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"],
                 ["A", "S", "D", "F", "G", "H", "J", "K", "L", ";"],
                 ["Z", "X", "C", "V", "B", "N", "M", ",", ".", "/"]]

final_text = ""
a = [1]
keyboard = Controller()


def draw(img, buttonList):
    for button in buttonList:
        x, y = button.pos
        w, h = button.size
        cvzone.cornerRect(img, (button.pos[0], button.pos[1],
                                button.size[0], button.size[0]), 20, rt=0)
        cv2.rectangle(img, button.pos, (int(x + w), int(y + h)), (255, 144, 30), cv2.FILLED)
        cv2.putText(img, button.text, (x + 20, y + 65),
                    cv2.FONT_HERSHEY_PLAIN, 4, (0, 0, 0), 4)
    return img


def transparent_layout(img, buttonList):
    imgNew = np.zeros_like(img, np.uint8)
    for button in buttonList:
        x, y = button.pos
        cvzone.cornerRect(imgNew, (button.pos[0], button.pos[1],
                                   button.size[0], button.size[0]), 20, rt=0)
        cv2.rectangle(imgNew, button.pos, (x + button.size[0], y + button.size[1]),
                      (255, 144, 30), cv2.FILLED)
        cv2.putText(imgNew, button.text, (x + 20, y + 65),
                    cv2.FONT_HERSHEY_PLAIN, 4, (0, 0, 0), 4)

    out = img.copy()
    alpaha = 0.5
    mask = imgNew.astype(bool)
    print(mask.shape)
    out[mask] = cv2.addWeighted(img, alpaha, imgNew, 1 - alpaha, 0)[mask]
    return out


class Button():
    def __init__(self, pos, text, size=[85, 85]):
        self.pos = pos
        self.size = size
        self.text = text


buttonList = []
# mybutton = Button([100, 100], "Q")
for k in range(len(keyboard_keys)):
    for x, key in enumerate(keyboard_keys[k]):
        buttonList.append(Button([100 * x + 25, 100 * k + 50], key))

while True:
    success, img = cap.read()
    img = detector.findHands(img)
    lmList, bboxInfo = detector.findPosition(img)
    img = draw(img, buttonList)  # change the draw funtion to transparent_layout for transparent keys

    if lmList:
        for button in buttonList:
            x, y = button.pos
            w, h = button.size

            if x < lmList[8][0] < x + w and y < lmList[8][1] < y + h:
                cv2.rectangle(img, button.pos, (x + w, y + h),
                              (0, 255, 255), cv2.FILLED)
                cv2.putText(img, button.text, (x + 20, y + 65),
                            cv2.FONT_HERSHEY_PLAIN, 4, (0, 0, 0), 4)
                l, _, _ = detector.findDistance(8, 12, img, draw=False)

                if l < 15:
                    print(l, button.text)
                    a.append(button.text)
                    print(a)
                    if button.text == a[-2] or button.text == '/':
                        break
                    else:
                        keyboard.press(button.text)
                        cv2.rectangle(img, button.pos, (x + w, y + h),
                                      (0, 255, 0), cv2.FILLED)
                        cv2.putText(img, button.text, (x + 20, y + 65),
                                    cv2.FONT_HERSHEY_PLAIN, 4, (0, 0, 0), 4)
                        final_text += button.text
                        sleep(0.20)

    cv2.rectangle(img, (25, 350), (700, 450),
                  (255, 255, 255), cv2.FILLED)
    cv2.putText(img, final_text, (60, 425),
                cv2.FONT_HERSHEY_PLAIN, 4, (0, 0, 0), 4)

    cv2.imshow("output", img)
    cv2.waitKey(1)


四. 解释代码

主要就是增加了两个判断,如下,当两个手指的距离小于15才打印距离,减小了输出区的冗余,增加了一个列表来存储小于15距离的字母,当列表里面的最后一个字母与当前的字母相同的时候就不输出,直接跳出,只打印一个字母,这就是去重的思想.

第二个就是增加一个无意义的字母,当输入这个字母的时候,什么都不用做,用来可以输入重复的字母.这里我选择了==/==作为无意义的字母,当然你也可以选择其他的符号.


                if l < 15:
                    print(l, button.text)
                    a.append(button.text)
                    print(a)
                    if button.text == a[-2] or button.text == '/':
                        break
                    else:
                        keyboard.press(button.text)
                        cv2.rectangle(img, button.pos, (x + w, y + h),
                                      (0, 255, 0), cv2.FILLED)
                        cv2.putText(img, button.text, (x + 20, y + 65),
                                    cv2.FONT_HERSHEY_PLAIN, 4, (0, 0, 0), 4)
                        final_text += button.text
                        sleep(0.20)

五. 其他的说明

手指关节的对应的数字

python 中用opencv开发虚拟键盘------可以只选择一个单词不会出现一下选择多个_第2张图片

知识体系

python 中用opencv开发虚拟键盘------可以只选择一个单词不会出现一下选择多个_第3张图片

六. 这个就是我自己改进后的代码,希望大家共同学习提高.

你可能感兴趣的:(python,opencv,计算机外设)