当前位置: 首页> 新闻> 资讯 > 虚拟键盘(不是软键盘)——科幻世界!!!

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

时间:2025/9/10 17:34:37来源:https://blog.csdn.net/DDDDWJDDDD/article/details/140612593 浏览次数:0次

        

目录

流程说明

导入所需的库

初始化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()  

效果展示

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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: