-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvirtual_ketboard.py
More file actions
137 lines (116 loc) · 5.39 KB
/
Copy pathvirtual_ketboard.py
File metadata and controls
137 lines (116 loc) · 5.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import cv2
from cvzone.HandTrackingModule import HandDetector
from time import sleep
from pynput.keyboard import Controller, Key
# Initialize webcam
cap = cv2.VideoCapture(0)
cap.set(3, 1580) # Set width
cap.set(4, 720) # Set height
# Initialize hand detector
detector = HandDetector(detectionCon=0.8)
# Define the expanded keyboard layout
keys = [
["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "="],
["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "BS"],
["A", "S", "D", "F", "G", "H", "J", "K", "L", ";", "Shift"],
["Z", "X", "C", "V", "B", "N", "M", ",", ".", "/", "Enter"],
["Space"]
]
finalText = ""
keyboard = Controller()
# Function to draw all buttons on the image
def drawAll(img, buttonList):
for button in buttonList:
x, y = button.pos
w, h = button.size
# Draw button background with a slight shadow
cv2.rectangle(img, (x + 5, y + 5), (x + w + 5, y + h + 5), (30, 30, 30), cv2.FILLED) # Shadow
cv2.rectangle(img, button.pos, (x + w, y + h), (70, 70, 70), cv2.FILLED) # Button itself (dark gray)
# Center the text
text_size = cv2.getTextSize(button.text, cv2.FONT_HERSHEY_COMPLEX, 1.2, 2)[0] # Adjust text size
text_x = x + (w - text_size[0]) // 2
text_y = y + (h + text_size[1]) // 2
cv2.putText(img, button.text, (text_x, text_y), cv2.FONT_HERSHEY_COMPLEX, 1.2, (255, 255, 255), 2) # White text
return img
# Button class to define each key's properties
class Button:
def __init__(self, pos, text, size=[85, 65]): # Slightly smaller buttons
self.pos = pos
self.size = size
self.text = text
# Create a list of Button objects for the keyboard
buttonList = []
for i in range(len(keys)):
for j, key in enumerate(keys[i]):
# Adjust button width for Space, Enter, and Backspace
if key == "Space":
buttonList.append(Button([90 * j + 50, 90 * i + 150], key, size=[500, 65])) # Wider space bar
elif key == "Enter" or key == "BS" or key == "Shift":
buttonList.append(Button([90 * j + 50, 90 * i + 150], key, size=[170, 65])) # Wider Enter and Backspace
else:
buttonList.append(Button([90 * j + 50, 90 * i + 150], key)) # Default button size
# Main loop
while True:
success, img = cap.read() # Capture frame from webcam
# Detect hands in the image
hands, img = detector.findHands(img) # Detect hands and landmarks
# Initialize lmList to avoid NameError
lmList = []
# Check if any hands are detected
if hands:
# Get the first hand detected
hand = hands[0]
lmList = hand["lmList"] # List of 21 hand landmarks (x, y, z)
bbox = hand["bbox"]
# Draw buttons on the image
img = drawAll(img, buttonList)
# Check if a finger is over a button
if lmList:
for button in buttonList:
x, y = button.pos
w, h = button.size
# Check if the index finger tip (landmark 8) is over the button
if x < lmList[8][0] < x + w and y < lmList[8][1] < y + h:
# Highlight the button
cv2.rectangle(img, button.pos, (x + w, y + h), (100, 100, 255), cv2.FILLED) # Highlight color (light purple)
cv2.putText(img, button.text, (x + 25, y + 55), cv2.FONT_HERSHEY_COMPLEX, 1.2, (255, 255, 255), 2) # White text
# Get only x,y coordinates (ignore z-axis)
p8 = lmList[8][0:2] # Index finger tip (x, y)
p4 = lmList[4][0:2] # Thumb finger tip (x, y)
# Calculate distance between thumb and index finger tips
length, _, _ = detector.findDistance(p8, p4, img)
#print(f"Distance between thumb and index finger: {length}")
# Detect click when thumb and index finger tips are close enough
if length < 30: # Adjust this threshold as needed
# Handle special keys like Space, Enter, Shift, and Backspace separately
if button.text == "Space":
finalText += " "
keyboard.press(Key.space)
keyboard.release(Key.space)
elif button.text == "Enter":
finalText += "\n"
keyboard.press(Key.enter)
keyboard.release(Key.enter)
elif button.text == "BS":
finalText = finalText[:-1]
keyboard.press(Key.backspace)
keyboard.release(Key.backspace)
elif button.text == "Shift":
# Optional: Implement Shift key functionality, if needed
pass
else:
keyboard.press(button.text)
keyboard.release(button.text)
finalText += button.text
# Change button color to green after click
cv2.rectangle(img, button.pos, (x + w, y + h), (0, 255, 0), cv2.FILLED)
cv2.putText(img, button.text, (x + 25, y + 55), cv2.FONT_HERSHEY_COMPLEX, 1.2, (255, 255, 255), 2)
sleep(0.25)
# Display the image
cv2.imshow("Virtual Keyboard", img)
# Break the loop if 'q' is pressed
if cv2.waitKey(1) == 27:
break
# Release the camera and close all windows
cap.release()
cv2.destroyAllWindows()