使用说明:
利用opencv绘制键盘与输出栏;
利用mediapipe识别手掌关键点的坐标信息;
计算根据手掌关键点坐标与键盘按键坐标的位置关系确定出所选择的按键;
利用手掌关键点之间的坐标关系,控制按键按下。
实现代码如下:
0. 环境配置:
pycharm、python=3.7、opencv=4.5、mediapipe=0.8.9、cvzone=1.4.1
1. 导入需要的python库
import cv2 from cvzone.HandTrackingModule import HandDetector import cvzone # 包含opencv与mediapipe功能 import time
2. 开启摄像头并捕捉
# 开启摄像头,捕捉画面 cap = cv2.VideoCapture(0) # 设置窗口尺寸 cap.set(3, 2560) # 识别手势 detector = HandDetector(detectionCon=1)
3. 定义按键
# 键盘字符
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', ',', '.', '/']]
# 定义按键,包括按键的位置->画图,按键的值->输出,按键的尺寸->布局
class Button():
def __init__(self, pos, text, size=[50, 50]):
self.pos = pos
self.text = text
self.size = size
# 分配按键位置
buttonList = []
for i in range(len(keys)):
for j, key in enumerate(keys[i]):
buttonList.append(Button([80 * j + 20, 100 + i * 80], key))
4. 绘制按键
# 按键绘制函数
def draw_keyboard(img, buttonList):
for button in buttonList:
x, y = button.pos
w, h = button.size
cvzone.cornerRect(img, (x, y, w, h), 20, rt=0)
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 255), cv2.FILLED)
cv2.putText(img, button.text, (x + 10, y + 40),
cv2.FONT_HERSHEY_PLAIN, 3, (255, 255, 255), 2)
return img
5. 手掌关键点示意图
6. 虚拟键盘实现
# 定义输出文本,当达到一定长度后需清空,可以自行修改为写出
finalText = ''
while True:
# 读取摄像头内容
res, img = cap.read()
while not res:
break
# 图像反转,去除镜像
img = cv2.flip(img, 1)
cv2.rectangle(img, (20, 350), (800, 500), (0, 255, 0), cv2.FILLED)
# 检测手掌
img = detector.findHands(img)
lmList = detector.findPosition(img)[0]
img = draw_keyboard(img, buttonList)
# 键盘输出
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, (x - 5, y - 5), (x + w + 5, y + h + 5), (175, 0, 175), cv2.FILLED)
cv2.putText(img, button.text, (x + 10, y + 40),
cv2.FONT_HERSHEY_PLAIN, 3, (0, 0, 0), 2)
# 当长度大于10时,清空
if len(finalText) > 10:
finalText = ""
# 根据食指指尖和拇指指尖距离判断,是否按下数字
l, _, _ = detector.findDistance(8, 4, img, draw=False)
# 默认不判断,当需要判断时,需将5000改小
if l < 5000:
finalText += button.text
cv2.putText(img, finalText, (20, 465), cv2.FONT_HERSHEY_SIMPLEX, 3, (255, 255, 255), 4)
time.sleep(0.2)
# 输出按键并显示
cv2.putText(img, finalText, (20, 465), cv2.FONT_HERSHEY_SIMPLEX, 3, (255, 255, 255), 4)
cv2.imshow("Image", img)
# 按下q退出
if cv2.waitKey(1) == ord('q'):
break
7. 代码链接
liuweixue001/mediapipe (github.com)
8. 相关链接
1. Mediapipe 实现手势追踪_Zcc的博客-CSDN博客_mediapipe 手势
2. Mediapipe 手势识别_Zcc的博客-CSDN博客_mediapipe手势识别
3. Hands - mediapipe (google.github.io)



