-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhandTrack.py
More file actions
116 lines (97 loc) · 3.74 KB
/
handTrack.py
File metadata and controls
116 lines (97 loc) · 3.74 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
# handtracking stuff
import cv2
import mediapipe as mp
import numpy as np
import pyautogui
import time
import threading
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(
static_image_mode=False,
max_num_hands=1,
min_detection_confidence=0.7,
min_tracking_confidence=0.7,
model_complexity=1
)
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
if not ret:
print("Failed to capture video")
exit(1)
pyautogui.FAILSAFE = False
pyautogui.PAUSE = 0
screen_width, screen_height = pyautogui.size()
inner_area_percent = 0.7
def calculate_margins(frame_width, frame_height, inner_area_percent):
margin_width = frame_width * (1 - inner_area_percent) / 2
margin_height = frame_height * (1 - inner_area_percent) / 2
return margin_width, margin_height
def convert_to_screen_coordinates(x, y, frame_width, frame_height, margin_width, margin_height):
screen_x = np.interp(x, (margin_width, frame_width - margin_width), (0, screen_width))
screen_y = np.interp(y, (margin_height, frame_height - margin_height), (0, screen_height))
return screen_x, screen_y
def get_landmark_distance(landmark1, landmark2):
x1, y1 = landmark1.x, landmark1.y
x2, y2 = landmark2.x, landmark2.y
distance = np.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
return distance
class CursorMovementThread(threading.Thread):
def __init__(self):
super().__init__()
self.daemon = True
self.current_x, self.current_y = pyautogui.position()
self.target_x, self.target_y = self.current_x, self.current_y
self.running = True
self.active = False
self.jitter_threshold = 0.003
def run(self):
while self.running:
if self.active:
distance = np.hypot(self.target_x - self.current_x, self.target_y - self.current_y)
screen_diagonal = np.hypot(screen_width, screen_height)
if distance / screen_diagonal > self.jitter_threshold:
step = max(0.0001, distance / 12) # Smoother movement
if distance != 0:
step_x = (self.target_x - self.current_x) / distance * step
step_y = (self.target_y - self.current_y) / distance * step
self.current_x += step_x
self.current_y += step_y
pyautogui.moveTo(self.current_x, self.current_y, _pause=False)
time.sleep(0)
else:
time.sleep(0.1)
def update_target(self, x, y):
self.target_x, self.target_y = x, y
def activate(self):
self.active = True
def deactivate(self):
self.active = False
def stop(self):
self.running = False
class ScrollThread(threading.Thread):
def __init__(self):
super().__init__()
self.daemon = True
self.scroll_queue = []
self.scroll_lock = threading.Lock()
self.running = True
self.inertia = 0.95
self.scroll_step = 0.01
self.inertia_threshold = 0.01
def run(self):
while self.running:
if self.scroll_queue:
with self.scroll_lock:
scroll_amount = self.scroll_queue.pop(0)
pyautogui.scroll(scroll_amount)
if len(self.scroll_queue) == 0 and abs(scroll_amount) > self.inertia_threshold:
scroll_amount *= self.inertia
if abs(scroll_amount) > self.scroll_step:
with self.scroll_lock:
self.scroll_queue.append(scroll_amount)
time.sleep(0.005)
def add_scroll(self, scroll_amount):
with self.scroll_lock:
self.scroll_queue.append(scroll_amount)
def stop(self):
self.running = False