import numpy as np
import cv2
from cvzone.HandTrackingModule import HandDetector
import math
import time
import cvzone
from pynput.keyboard import Controller
cap = cv2.VideoCapture(2)
cap.set(3, 1280)
cap.set(4, 720)
cap.set(10, 150)
detector = HandDetector(detectionCon=0.8,maxHands=1)
keys = [['1','2','3','4','5','6','7','8','9','0','-','+'],
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P','[',']'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';','ENTER'],
['Z', 'X', 'C', 'V', 'B', 'N', 'M', ',', '.', '/','BACK']]
finalText=''
keyboard=Controller()
num_text = 0 # 记录finalText中的字符个数,为了保证能每60个字符换一次行
def drawAll(img, buttonlist):
imgNew=np.zeros_like(img,np.uint8)
# 根据每个矩形框中心点的位置,在一帧图像中画上每个矩形框
for button in buttonlist:
x, y = button.pos #获取按键位置
w, h = button.size #获取按键大小
cvzone.cornerRect(imgNew,(button.pos[0],button.pos[1],button.size[0],button.size[1]),rt=20,colorC=(0,0,255),colorR=(255,255,0))
cv2.rectangle(imgNew, button.pos, (x + w, y + h), (255, 0, 0), cv2.FILLED)
cv2.putText(imgNew, button.text, (x + 20, y + 65), cv2.FONT_HERSHEY_PLAIN, 4, (255, 255, 255), 4)
#制作透明图片
out=img.copy()
alpha=0.5
mask=imgNew.astype(bool)
# print(mask.shape)
out[mask]=cv2.addWeighted(img,alpha,imgNew,1-alpha,0)[mask]
return out
class Button():
def __init__(self, pos, text, size=[85, 85]):
self.pos = pos #起始点
self.text = text
self.size = size #终点
buttonlist = []
for i in range(len(keys)):
for j, key in enumerate(keys[i]):
if len(key)>3:
buttonlist.append(Button([100 * j + 25, 100 * i + 25], key,size=[190,85]))
else:
buttonlist.append(Button([100 * j + 25, 100 * i + 25], key))
while True:
success, img = cap.read()
img = cv2.flip(img, 1) # 因为摄像头是镜像的,所以需要将摄像头水平翻转
#旋转类型说明:
# flipCode = 0:x轴方向旋转
# flipCode > 0:y轴方向旋转
# flipCode < 0:x轴y轴方向同时旋转
hands,img = detector.findHands(img)
img = drawAll(img, buttonlist)
if hands:
lmList = hands[0]['lmList']
for button in buttonlist:
x, y = button.pos
w, h = button.size
if x
cv2.putText(img, button.text, (x + 20, y + 65), cv2.FONT_HERSHEY_PLAIN, 4, (255, 255, 255), 4)
x1 = lmList[8][0]
x2 = lmList[12][0]
y1 = lmList[8][1]
y2 = lmList[12][1]
l, _, _ = detector.findDistance((x1, y1), (x2, y2), img)
if l< 30:
if button.text == "BACK":
finalText = finalText[0:-1] # 删除最后的字符
num_text = num_text - 1
keyboard.press(button.text)
time.sleep(0.2)
if button.text == "ENTER":
finalText += (50 - num_text % 50) * " " # 添加空格进行换行
for i in range(50 - num_text % 50):
num_text += 1
# keyboard.press(button.text)
time.sleep(0.2)
if button.text != "BACK" and button.text != "ENTER":
cv2.rectangle(img, button.pos, (x + w, y + h), (255,0,0), cv2.FILLED)
cv2.putText(img, button.text, (x + 20, y + 65), cv2.FONT_HERSHEY_PLAIN, 4, (255, 255, 255), 4)
finalText+=button.text
keyboard.press(button.text)
num_text += 1
time.sleep(0.2)
#输出框
cv2.rectangle(img, (50,450), (700,500) ,(255, 0, 255), cv2.FILLED)
cv2.putText(img, finalText, (60,500), cv2.FONT_HERSHEY_PLAIN, 5, (255, 255, 255), 5)
# 显示字符;
# 实现换行:当遇到Enter按键时,直接换行;每行满50个字
times = num_text // 50
if times !=0:
for i in range(times+1):
cv2.rectangle(img, (50, 500 + i * 40), (700, 550 + i * 40), (255, 0, 255), cv2.FILLED)
cv2.putText(img, finalText[50 * i:50 * (i + 1)], (60, 550 + 25 * i), cv2.FONT_HERSHEY_PLAIN, 2, (255, 255, 255),
thickness=2)
cv2.imshow('Img', img)
cv2.waitKey(1)