Update app.py
Browse files
app.py
CHANGED
@@ -24,25 +24,37 @@ mp_hands = mp.solutions.hands
|
|
24 |
hands = mp_hands.Hands(max_num_hands=1, min_detection_confidence=0.5)
|
25 |
mp_drawing = mp.solutions.drawing_utils
|
26 |
|
27 |
-
#
|
28 |
-
keys = [
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
class Button:
|
34 |
def __init__(self, pos, text, size=[100, 100]):
|
35 |
self.pos = pos
|
36 |
self.size = size
|
37 |
self.text = text
|
38 |
-
|
|
|
39 |
|
40 |
class Detection(NamedTuple):
|
41 |
label: str
|
42 |
score: float
|
43 |
box: np.ndarray
|
44 |
|
45 |
-
|
46 |
# Global variables
|
47 |
result_queue: "queue.Queue[List[Detection]]" = queue.Queue()
|
48 |
indexImg = 0
|
@@ -82,8 +94,29 @@ def video_frame_callback(frame: av.VideoFrame) -> av.VideoFrame:
|
|
82 |
for button in buttonList:
|
83 |
x, y = button.pos
|
84 |
bw, bh = button.size
|
85 |
-
|
86 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
|
88 |
detections = []
|
89 |
if result.multi_hand_landmarks:
|
@@ -128,19 +161,23 @@ def video_frame_callback(frame: av.VideoFrame) -> av.VideoFrame:
|
|
128 |
else:
|
129 |
output_text += ' ' # Add space
|
130 |
|
131 |
-
#
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
cv2.rectangle(img,
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
|
|
|
|
|
|
|
|
144 |
|
145 |
result_queue.put(detections)
|
146 |
return av.VideoFrame.from_ndarray(img, format="bgr24")
|
|
|
24 |
hands = mp_hands.Hands(max_num_hands=1, min_detection_confidence=0.5)
|
25 |
mp_drawing = mp.solutions.drawing_utils
|
26 |
|
27 |
+
# Improved keyboard layout with better styling
|
28 |
+
keys = [
|
29 |
+
["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"],
|
30 |
+
["A", "S", "D", "F", "G", "H", "J", "K", "L", ";"],
|
31 |
+
["Z", "X", "C", "V", "B", "N", "M", ",", ".", "/"]
|
32 |
+
]
|
33 |
+
|
34 |
+
# Enhanced colors and styling
|
35 |
+
COLORS = {
|
36 |
+
'KEY_IDLE': (75, 75, 75), # Darker gray for idle keys
|
37 |
+
'KEY_HOVER': (100, 100, 255), # Blue highlight for hover
|
38 |
+
'KEY_PRESS': (50, 200, 50), # Green for pressed keys
|
39 |
+
'TEXT_NORMAL': (255, 255, 255), # White text
|
40 |
+
'TEXT_PRESS': (0, 0, 0), # Black text when pressed
|
41 |
+
'OUTPUT_BG': (45, 45, 45), # Dark gray for output background
|
42 |
+
}
|
43 |
+
|
44 |
+
# Modified Button class with hover state
|
45 |
class Button:
|
46 |
def __init__(self, pos, text, size=[100, 100]):
|
47 |
self.pos = pos
|
48 |
self.size = size
|
49 |
self.text = text
|
50 |
+
self.is_hover = False
|
51 |
+
self.is_pressed = False
|
52 |
|
53 |
class Detection(NamedTuple):
|
54 |
label: str
|
55 |
score: float
|
56 |
box: np.ndarray
|
57 |
|
|
|
58 |
# Global variables
|
59 |
result_queue: "queue.Queue[List[Detection]]" = queue.Queue()
|
60 |
indexImg = 0
|
|
|
94 |
for button in buttonList:
|
95 |
x, y = button.pos
|
96 |
bw, bh = button.size
|
97 |
+
|
98 |
+
# Draw key background with rounded corners
|
99 |
+
if button.is_pressed:
|
100 |
+
color = COLORS['KEY_PRESS']
|
101 |
+
text_color = COLORS['TEXT_PRESS']
|
102 |
+
elif button.is_hover:
|
103 |
+
color = COLORS['KEY_HOVER']
|
104 |
+
text_color = COLORS['TEXT_NORMAL']
|
105 |
+
else:
|
106 |
+
color = COLORS['KEY_IDLE']
|
107 |
+
text_color = COLORS['TEXT_NORMAL']
|
108 |
+
|
109 |
+
# Draw rounded rectangle
|
110 |
+
cv2.rectangle(img, (x, y), (x + bw, y + bh), color, -1, cv2.LINE_AA)
|
111 |
+
cv2.rectangle(img, (x, y), (x + bw, y + bh), (100, 100, 100), 1, cv2.LINE_AA)
|
112 |
+
|
113 |
+
# Center text
|
114 |
+
text_size = cv2.getTextSize(button.text, cv2.FONT_HERSHEY_SIMPLEX, font_scale, font_thickness)[0]
|
115 |
+
text_x = x + (bw - text_size[0]) // 2
|
116 |
+
text_y = y + (bh + text_size[1]) // 2
|
117 |
+
|
118 |
+
cv2.putText(img, button.text, (text_x, text_y),
|
119 |
+
cv2.FONT_HERSHEY_SIMPLEX, font_scale, text_color, font_thickness)
|
120 |
|
121 |
detections = []
|
122 |
if result.multi_hand_landmarks:
|
|
|
161 |
else:
|
162 |
output_text += ' ' # Add space
|
163 |
|
164 |
+
# Improved output display
|
165 |
+
output_bg_height = int(0.15 * h)
|
166 |
+
output_y = int(0.8 * h)
|
167 |
+
|
168 |
+
# Draw output background with rounded corners
|
169 |
cv2.rectangle(img,
|
170 |
+
(int(0.05 * w), output_y - output_bg_height),
|
171 |
+
(int(0.95 * w), output_y),
|
172 |
+
COLORS['OUTPUT_BG'], -1, cv2.LINE_AA)
|
173 |
+
|
174 |
+
# Add text with better positioning
|
175 |
+
text_size = cv2.getTextSize(output_text, cv2.FONT_HERSHEY_SIMPLEX, 1, 2)[0]
|
176 |
+
text_x = int(0.07 * w)
|
177 |
+
text_y = output_y - output_bg_height//2 + text_size[1]//2
|
178 |
+
|
179 |
+
cv2.putText(img, output_text, (text_x, text_y),
|
180 |
+
cv2.FONT_HERSHEY_SIMPLEX, 1, COLORS['TEXT_NORMAL'], 2)
|
181 |
|
182 |
result_queue.put(detections)
|
183 |
return av.VideoFrame.from_ndarray(img, format="bgr24")
|