Skip to content

Commit 9d381c0

Browse files
Gesture Volume Control
Using OpenCV python library to control the volume of windows using fingers
1 parent 59f54ed commit 9d381c0

File tree

2 files changed

+154
-0
lines changed

2 files changed

+154
-0
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import cv2
2+
import time
3+
import numpy as np
4+
import handTrackingModule as htm
5+
import math
6+
7+
from ctypes import cast, POINTER
8+
from comtypes import CLSCTX_ALL
9+
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
10+
11+
################################
12+
wCam, hCam = 640, 480
13+
################################
14+
15+
cap = cv2.VideoCapture(0)
16+
cap.set(3, wCam)
17+
cap.set(4, hCam)
18+
pTime = 0
19+
20+
detector = htm.handDetector(detectionCon=0.7)
21+
22+
devices = AudioUtilities.GetSpeakers()
23+
interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
24+
volume = cast(interface, POINTER(IAudioEndpointVolume))
25+
# volume.GetMute()
26+
# volume.GetMasterVolumeLevel()
27+
volRange = volume.GetVolumeRange()
28+
minVol = volRange[0]
29+
maxVol = volRange[1]
30+
vol = 0
31+
volBar = 400
32+
volPer = 0
33+
34+
while True:
35+
success, img = cap.read()
36+
img = detector.findHands(img)
37+
lmList = detector.findPosition(img, draw=False)
38+
if len(lmList) != 0:
39+
# print(lmList[4], lmList[8])
40+
x1, y1 = lmList[4][1], lmList[4][2]
41+
x2, y2 = lmList[8][1], lmList[8][2]
42+
43+
cv2.circle(img, (x1, y1), 15, (0, 255, 255), cv2.FILLED)
44+
cv2.circle(img, (x2, y2), 15, (0, 255, 255), cv2.FILLED)
45+
cv2.line(img, (x1, y1), (x2, y2), (100, 255, 255), 3)
46+
cx, cy = (x1 + x2) // 2, (y1 + y2) // 2
47+
cv2.circle(img, (cx, cy), 10, (0, 255, 255), cv2.FILLED)
48+
49+
length = math.hypot(x2 - x1, y2 - y1)
50+
# print(length)
51+
52+
#Hand range 50 - 260
53+
#volume range -63.5 to 0
54+
vol = np.interp(length, [50,260], [minVol, maxVol])
55+
volBar = np.interp(length, [50,270], [400, 150])
56+
volPer = np.interp(length, [50, 270], [0,100])
57+
print(vol)
58+
volume.SetMasterVolumeLevel(vol, None)
59+
60+
if length < 50:
61+
cv2.circle(img, (cx, cy), 10, (0, 255, 0), cv2.FILLED)
62+
63+
cv2.rectangle(img, (50,150), (85,400), (0,255,0), 3)
64+
cv2.rectangle(img, (50,int(volBar)), (85,400), (0,255,0), cv2.FILLED)
65+
cv2.putText(img, f'FPS: {int(volPer)} %', (40, 450), cv2.FONT_HERSHEY_COMPLEX, 1, (255,0 , 0), 2)
66+
67+
68+
cTime = time.time()
69+
fps = 1 / (cTime - pTime)
70+
pTime = cTime
71+
72+
cv2.putText(img, f'FPS: {int(fps)}', (30, 50), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2)
73+
cv2.imshow("Img", img)
74+
cv2.waitKey(1)
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# converting handTracking.py to a module so that we can use in any project
2+
3+
import cv2 as cv
4+
import mediapipe as mp
5+
import time
6+
7+
8+
class handDetector():
9+
def __init__(self, mode=False, maxHands=2, modelComplexity=1, detectionCon=0.5, trackCon=0.5): # mpHands variable
10+
self.mode = mode # create an object with own variable, self.mode is variable,
11+
self.maxHands = maxHands
12+
self.modelComplexity = modelComplexity
13+
self.detectionCon = detectionCon
14+
self.trackCon = trackCon
15+
16+
self.mpHands = mp.solutions.hands
17+
self.hands = self.mpHands.Hands(self.mode, self.maxHands, self.modelComplexity,
18+
self.detectionCon, self.trackCon) # using default values #only uses rgb img
19+
self.mpDraw = mp.solutions.drawing_utils
20+
21+
def findHands(self, img, draw=True):
22+
# converting img to rgb
23+
imgRGB = cv.cvtColor(img, cv.COLOR_BGR2RGB)
24+
self.results = self.hands.process(imgRGB)
25+
# print(results.multi_hand_landmarks) #print none if hand is not in video else prints coordinates of hand
26+
27+
if self.results.multi_hand_landmarks:
28+
for handLms in self.results.multi_hand_landmarks:
29+
if draw:
30+
self.mpDraw.draw_landmarks(img, handLms,
31+
self.mpHands.HAND_CONNECTIONS) # draws all 21 points in hands
32+
# mpHands.HAND_CONNECTIONS --> this connects the dots
33+
return img
34+
35+
def findPosition(self, img, handNo=0, draw=True):
36+
lmList = []
37+
38+
# extracting id and landmark(x,y,z) coordinate
39+
if self.results.multi_hand_landmarks:
40+
myHand = self.results.multi_hand_landmarks[handNo] # getting which hand
41+
for id, lm in enumerate(myHand.landmark):
42+
# print(id, lm) #values of x,y,z are in float
43+
# we will convert them to pixels
44+
h, w, c = img.shape
45+
cx, cy = int(lm.x * w), int(lm.y * h)
46+
# print(cx,cy) #now we don't know which value is for which point so we have to use id
47+
# print(id, cx, cy)
48+
lmList.append([id, cx, cy])
49+
if draw:
50+
cv.circle(img, (cx, cy), 7, (255, 0, 0), cv.FILLED)
51+
52+
return lmList
53+
54+
55+
def main():
56+
#dummy code to use in any other project
57+
pTime = 0 # previous time
58+
cTime = 0 # current rime
59+
cap = cv.VideoCapture(0)
60+
detector = handDetector() # calling the class
61+
while True:
62+
success, img = cap.read()
63+
img = detector.findHands(img)
64+
lmList = detector.findPosition(img)
65+
if len(lmList) != 0:
66+
print(lmList[4])
67+
68+
cTime = time.time()
69+
fps = 1 / (cTime - pTime)
70+
pTime = cTime
71+
72+
# display fps on screen
73+
cv.putText(img, str(int(fps)), (10, 70), cv.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 3)
74+
75+
cv.imshow('Image', img)
76+
cv.waitKey(1)
77+
78+
79+
if __name__ == "__main__":
80+
main()

0 commit comments

Comments
 (0)