-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhand gestrue.py
More file actions
94 lines (75 loc) · 3.46 KB
/
Copy pathhand gestrue.py
File metadata and controls
94 lines (75 loc) · 3.46 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
import cv2
import numpy as np
import mediapipe as mp
from ctypes import cast, POINTER
from comtypes import CLSCTX_ALL
from pycaw.pycaw import IAudioEndpointVolume
import comtypes
from comtypes import GUID
from pycaw.pycaw import IMMDeviceEnumerator
# Function to get default audio endpoint device with Activate method
def get_default_audio_endpoint(eRender=0, eMultimedia=1):
CLSID_MMDeviceEnumerator = GUID('{BCDE0395-E52F-467C-8E3D-C4579291692E}')
IID_IMMDeviceEnumerator = GUID('{A95664D2-9614-4F35-A746-DE8DB63617E6}')
device_enumerator = comtypes.CoCreateInstance(
CLSID_MMDeviceEnumerator, interface=IMMDeviceEnumerator)
device = device_enumerator.GetDefaultAudioEndpoint(eRender, eMultimedia)
return device
# Access audio endpoint volume interface
device = get_default_audio_endpoint()
interface = device.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
volume = cast(interface, POINTER(IAudioEndpointVolume))
vol_range = volume.GetVolumeRange()
min_vol = vol_range[0]
max_vol = vol_range[1]
# MediaPipe hands setup
mp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils
hands = mp_hands.Hands(
static_image_mode=False,
max_num_hands=1,
min_detection_confidence=0.7,
min_tracking_confidence=0.7
)
cap = cv2.VideoCapture(0)
cap.set(3, 640)
cap.set(4, 480)
def get_landmark_coords(lm_list, idx, img_w, img_h):
return int(lm_list[idx].x * img_w), int(lm_list[idx].y * img_h)
while True:
ret, frame = cap.read()
if not ret:
break
img_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = hands.process(img_rgb)
img_h, img_w, _ = frame.shape
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
lm = hand_landmarks.landmark
x1, y1 = get_landmark_coords(lm, 4, img_w, img_h) # Thumb tip
x2, y2 = get_landmark_coords(lm, 8, img_w, img_h) # Index tip
cv2.circle(frame, (x1, y1), 10, (255, 0, 255), cv2.FILLED)
cv2.circle(frame, (x2, y2), 10, (255, 0, 255), cv2.FILLED)
cv2.line(frame, (x1, y1), (x2, y2), (255, 0, 255), 3)
length = np.hypot(x2 - x1, y2 - y1)
min_len, max_len = 30, 200 # Tune these values to your setup
length_clamped = np.clip(length, min_len, max_len)
vol_db = np.interp(length_clamped, [min_len, max_len], [min_vol, max_vol])
vol_percent = np.interp(length_clamped, [min_len, max_len], [0, 100])
volume.SetMasterVolumeLevel(vol_db, None)
vol_bar = np.interp(length_clamped, [min_len, max_len], [400, 150])
cv2.rectangle(frame, (50, 150), (85, 400), (0, 255, 0), 2)
cv2.rectangle(frame, (50, int(vol_bar)), (85, 400), (0, 255, 0), cv2.FILLED)
cv2.putText(frame, f'{int(vol_percent)} %', (40, 430),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
if length < min_len + 5:
cv2.circle(frame, ((x1 + x2)//2, (y1 + y2)//2), 15, (0, 0, 255), cv2.FILLED)
cv2.putText(frame, "Pinch Thumb-Index to Control Volume", (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
cv2.imshow("Hand Gesture Volume Control", frame)
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
hands.close()