目录
这段代码展示了如何使用摄像头、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()
效果展示
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » 虚拟键盘(不是软键盘)——科幻世界!!!
发表评论 取消回复