虚拟键盘(不是软键盘)——科幻世界!!!

        

目录

流程说明

导入所需的库

初始化Mediapipe的手部检测模块

键盘控制器

打开摄像头

定义虚拟键盘的按键布局

记录每个按键的上次按压时间

显示虚拟键盘的函数

检测手指是否按压按键的函数

主循环

释放资源

总结

代码实现

效果展示


        这段代码展示了如何使用摄像头、Mediapipe和OpenCV创建一个虚拟键盘,用户可以通过手部动作来“按压”虚拟键盘上的按键。代码通过检测手部位置和动作来确定哪个按键被按压,然后模拟实际的键盘输入。


流程说明

导入所需的库
import cv2
import mediapipe as mp
import time
from pynput.keyboard import Controller
  • cv2:OpenCV库,用于图像处理和计算机视觉。
  • mediapipe:Mediapipe库,用于手部检测和跟踪。
  • time:Python内置的时间库,用于记录和计算时间。
  • pynput.keyboard.Controller:用于模拟键盘输入。

 初始化Mediapipe的手部检测模块
# 初始化Mediapipe的手部检测模块
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(min_detection_confidence=0.7, min_tracking_confidence=0.7)
mp_drawing = mp.solutions.drawing_utils
  • mp_hands:初始化Mediapipe的手部检测模块。
  • hands:创建一个手部检测对象,设置最小检测和跟踪置信度为0.7。
  • mp_drawing:用于在图像上绘制手部关键点和连接线。

键盘控制器
keyboard = Controller()
  • keyboard:创建一个键盘控制器对象,用于模拟键盘输入。

打开摄像头
cap = cv2.VideoCapture(0)
  • cap:打开默认摄像头。

定义虚拟键盘的按键布局
# 定义虚拟键盘的按键布局
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'],
    ['Z', 'X', 'C', 'V', 'B', 'N', 'M'],
    [' ', 'BACKSPACE']
]
  • keys:定义虚拟键盘的按键布局,每个元素表示一行按键。

记录每个按键的上次按压时间
key_press_times = {key: 0 for row in keys for key in row}
  • key_press_times:记录每个按键的上次按压时间,以防止在短时间内重复按压。

显示虚拟键盘的函数
def draw_keyboard(image):
    """
    在图像上绘制虚拟键盘
    """
    for i, row in enumerate(keys):
        for j, key in enumerate(row):
            # 计算按键的x坐标
            x = j * 60 + 50
            # 计算按键的y坐标
            y = i * 60 + 150
            # 绘制按键矩形
            cv2.rectangle(image, (x, y), (x + 50, y + 50), (255, 255, 255), -1)
            # 绘制按键文本
            cv2.putText(image, key, (x + 15, y + 35), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
  • draw_keyboard(image):在图像上绘制虚拟键盘。
    • 遍历每一行的按键,计算每个按键的位置并绘制按键矩形和文字。

检测手指是否按压按键的函数
def detect_key_press(landmarks, image):
    """
    检测手指是否按压按键
    """
    # 食指指尖
    index_finger_tip = landmarks[8]
    # 其他手指指尖
    other_fingers_tips = [landmarks[i] for i in [4, 12, 16, 20]]

    # 食指指尖的z坐标
    index_z = index_finger_tip.z
    # 其他手指指尖的z坐标
    other_z = [tip.z for tip in other_fingers_tips]

    # 检测食指是否显著低于其他手指(z轴坐标显著不同)
    if all(index_z < z - 0.004 for z in other_z):
        # 转换食指坐标到图像坐标
        x, y = int(index_finger_tip.x * image.shape[1]), int(index_finger_tip.y * image.shape[0])
        # 获取当前时间
        current_time = time.time()
        for i, row in enumerate(keys):
            for j, key in enumerate(row):
                # 计算按键的x坐标
                key_x = j * 60 + 50
                # 计算按键的y坐标
                key_y = i * 60 + 150
                # 检查食指坐标是否在按键范围内
                if key_x < x < key_x + 50 and key_y < y < key_y + 50:
                    # 检查按键是否在1秒内被按压过
                    if current_time - key_press_times[key] > 1:
                        # 更新按键的上次按压时间
                        key_press_times[key] = current_time
                        # 绘制按压效果
                        cv2.rectangle(image, (key_x, key_y), (key_x + 50, key_y + 50), (0, 255, 0), -1)
                        cv2.putText(image, key, (key_x + 15, key_y + 35), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
                        print(f'Key {key} pressed')
                        # 模拟键盘输入
                        if key == ' ':
                            keyboard.press(' ')
                            keyboard.release(' ')
                        elif key == 'BACKSPACE':
                            keyboard.press('\b')
                            keyboard.release('\b')
                        else:
                            keyboard.press(key)
                            keyboard.release(key)
  • detect_key_press(landmarks, image):检测手指是否按压按键。
    • index_finger_tip:获取食指指尖的位置。
    • other_fingers_tips:获取其他手指指尖的位置。
    • 通过比较食指和其他手指的z轴坐标,检测食指是否显著低于其他手指(表示按压动作)。
    • 计算食指在图像上的位置,遍历按键,检查食指是否在某个按键的范围内。
    • 如果按键在1秒内未被按压过,绘制按压效果并模拟键盘输入。

主循环
while True:
    # 读取摄像头图像
    success, image = cap.read()
    if not success:
        break

    # 翻转图像
    image = cv2.flip(image, 1)
    # 转换为RGB格式
    image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    # 处理图像,检测手部
    results = hands.process(image_rgb)

    if results.multi_hand_landmarks:
        for hand_landmarks in results.multi_hand_landmarks:
            # 绘制手部连接线
            mp_drawing.draw_landmarks(image, hand_landmarks, mp_hands.HAND_CONNECTIONS)
            landmarks = hand_landmarks.landmark
            # 检测按压
            detect_key_press(landmarks, image)

    # 绘制虚拟键盘
    draw_keyboard(image)
    # 显示图像
    cv2.imshow('Virtual Keyboard', image)

    # 按下ESC键退出
    if cv2.waitKey(1) & 0xFF == 27:
        break
  • 在主循环中,代码不断读取摄像头图像并翻转图像以获得镜像效果。
  • 将图像从BGR格式转换为RGB格式,以便Mediapipe处理。
  • 使用Mediapipe检测手部位置,并绘制手部连接线。
  • 检测手指是否按压按键,并绘制虚拟键盘。
  • 显示图像,并检查是否按下ESC键以退出循环。

释放资源
cap.release() # 释放摄像头 cv2.destroyAllWindows() # 销毁所有窗口
  • 释放摄像头资源并销毁所有OpenCV窗口。

总结

        这段代码展示了如何使用摄像头捕捉手部动作,通过手部检测和位置跟踪来模拟按压虚拟键盘上的按键。代码通过OpenCV绘制虚拟键盘,并通过pynput模拟实际的键盘输入。这种技术可以用于各种交互式应用,如虚拟输入设备和手势控制系统。        

        还是挺简单的嘛。


代码实现

        下面的是完整的全部代码,下载完对应的Python包即可运行。

import cv2
import mediapipe as mp
import time
from pynput.keyboard import Controller

# 初始化Mediapipe的手部检测模块
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(min_detection_confidence=0.7, min_tracking_confidence=0.7)
mp_drawing = mp.solutions.drawing_utils

# 键盘控制器,用于模拟键盘输入
keyboard = Controller()

# 打开摄像头
cap = cv2.VideoCapture(0)

# 定义虚拟键盘的按键布局
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'],
    ['Z', 'X', 'C', 'V', 'B', 'N', 'M'],
    [' ', 'BACKSPACE']
]

# 记录每个按键的上次按压时间,以防止在1秒内重复按压
key_press_times = {key: 0 for row in keys for key in row}

# 显示虚拟键盘的函数
def draw_keyboard(image):
    """
    在图像上绘制虚拟键盘
    """
    for i, row in enumerate(keys):
        for j, key in enumerate(row):
            # 计算按键的x坐标
            x = j * 60 + 50  
            # 计算按键的y坐标
            y = i * 60 + 150  
            # 绘制按键矩形
            cv2.rectangle(image, (x, y), (x + 50, y + 50), (255, 255, 255), -1)  
            # 绘制按键文本
            cv2.putText(image, key, (x + 15, y + 35), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)  

# 检测手指是否按压按键的函数
def detect_key_press(landmarks, image):
    """
    检测手指是否按压按键
    """
    # 食指指尖
    index_finger_tip = landmarks[8]  
    # 其他手指指尖
    other_fingers_tips = [landmarks[i] for i in [4, 12, 16, 20]]  

    # 食指指尖的z坐标
    index_z = index_finger_tip.z  
    # 其他手指指尖的z坐标
    other_z = [tip.z for tip in other_fingers_tips]  

    # 检测食指是否显著低于其他手指(z轴坐标显著不同)
    if all(index_z < z - 0.004 for z in other_z):
        # 转换食指坐标到图像坐标
        x, y = int(index_finger_tip.x * image.shape[1]), int(index_finger_tip.y * image.shape[0])  
        # 获取当前时间
        current_time = time.time()  
        for i, row in enumerate(keys):
            for j, key in enumerate(row):
                # 计算按键的x坐标
                key_x = j * 60 + 50  
                # 计算按键的y坐标
                key_y = i * 60 + 150  
                # 检查食指坐标是否在按键范围内
                if key_x < x < key_x + 50 and key_y < y < key_y + 50:
                    # 检查按键是否在1秒内被按压过
                    if current_time - key_press_times[key] > 1:
                        # 更新按键的上次按压时间
                        key_press_times[key] = current_time  
                        # 绘制按压效果
                        cv2.rectangle(image, (key_x, key_y), (key_x + 50, key_y + 50), (0, 255, 0), -1)
                        cv2.putText(image, key, (key_x + 15, key_y + 35), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
                        print(f'Key {key} pressed')
                        # 模拟键盘输入
                        if key == ' ':
                            keyboard.press(' ')
                            keyboard.release(' ')
                        elif key == 'BACKSPACE':
                            keyboard.press('\b')
                            keyboard.release('\b')
                        else:
                            keyboard.press(key)
                            keyboard.release(key)

while True:
    # 读取摄像头图像
    success, image = cap.read()  
    if not success:
        break

    # 翻转图像
    image = cv2.flip(image, 1)  
    # 转换为RGB格式
    image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)  
    # 处理图像,检测手部
    results = hands.process(image_rgb)  

    if results.multi_hand_landmarks:
        for hand_landmarks in results.multi_hand_landmarks:
            # 绘制手部连接线
            mp_drawing.draw_landmarks(image, hand_landmarks, mp_hands.HAND_CONNECTIONS)  
            landmarks = hand_landmarks.landmark
            # 检测按压
            detect_key_press(landmarks, image)  

    # 绘制虚拟键盘
    draw_keyboard(image)  
    # 显示图像
    cv2.imshow('Virtual Keyboard', image)  

    # 按下ESC键退出
    if cv2.waitKey(1) & 0xFF == 27:  
        break

# 释放摄像头
cap.release()  
# 销毁所有窗口
cv2.destroyAllWindows()  

效果展示

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WenJGo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值