Skip to content

Gesture Volume Control #25

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions Gesture-Volume-Control/VolumeHandControl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import cv2
import time
import numpy as np
import handTrackingModule as htm
import math

from ctypes import cast, POINTER
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume

################################
wCam, hCam = 640, 480
################################

cap = cv2.VideoCapture(0)
cap.set(3, wCam)
cap.set(4, hCam)
pTime = 0

detector = htm.handDetector(detectionCon=0.7)

devices = AudioUtilities.GetSpeakers()
interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
volume = cast(interface, POINTER(IAudioEndpointVolume))
# volume.GetMute()
# volume.GetMasterVolumeLevel()
volRange = volume.GetVolumeRange()
minVol = volRange[0]
maxVol = volRange[1]
vol = 0
volBar = 400
volPer = 0

while True:
success, img = cap.read()
img = detector.findHands(img)
lmList = detector.findPosition(img, draw=False)
if len(lmList) != 0:
# print(lmList[4], lmList[8])
x1, y1 = lmList[4][1], lmList[4][2]
x2, y2 = lmList[8][1], lmList[8][2]

cv2.circle(img, (x1, y1), 15, (0, 255, 255), cv2.FILLED)
cv2.circle(img, (x2, y2), 15, (0, 255, 255), cv2.FILLED)
cv2.line(img, (x1, y1), (x2, y2), (100, 255, 255), 3)
cx, cy = (x1 + x2) // 2, (y1 + y2) // 2
cv2.circle(img, (cx, cy), 10, (0, 255, 255), cv2.FILLED)

length = math.hypot(x2 - x1, y2 - y1)
# print(length)

#Hand range 50 - 260
#volume range -63.5 to 0
vol = np.interp(length, [50,260], [minVol, maxVol])
volBar = np.interp(length, [50,270], [400, 150])
volPer = np.interp(length, [50, 270], [0,100])
print(vol)
volume.SetMasterVolumeLevel(vol, None)

if length < 50:
cv2.circle(img, (cx, cy), 10, (0, 255, 0), cv2.FILLED)

cv2.rectangle(img, (50,150), (85,400), (0,255,0), 3)
cv2.rectangle(img, (50,int(volBar)), (85,400), (0,255,0), cv2.FILLED)
cv2.putText(img, f'FPS: {int(volPer)} %', (40, 450), cv2.FONT_HERSHEY_COMPLEX, 1, (255,0 , 0), 2)


cTime = time.time()
fps = 1 / (cTime - pTime)
pTime = cTime

cv2.putText(img, f'FPS: {int(fps)}', (30, 50), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2)
cv2.imshow("Img", img)
cv2.waitKey(1)
80 changes: 80 additions & 0 deletions Gesture-Volume-Control/handTrackingModule.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# converting handTracking.py to a module so that we can use in any project

import cv2 as cv
import mediapipe as mp
import time


class handDetector():
def __init__(self, mode=False, maxHands=2, modelComplexity=1, detectionCon=0.5, trackCon=0.5): # mpHands variable
self.mode = mode # create an object with own variable, self.mode is variable,
self.maxHands = maxHands
self.modelComplexity = modelComplexity
self.detectionCon = detectionCon
self.trackCon = trackCon

self.mpHands = mp.solutions.hands
self.hands = self.mpHands.Hands(self.mode, self.maxHands, self.modelComplexity,
self.detectionCon, self.trackCon) # using default values #only uses rgb img
self.mpDraw = mp.solutions.drawing_utils

def findHands(self, img, draw=True):
# converting img to rgb
imgRGB = cv.cvtColor(img, cv.COLOR_BGR2RGB)
self.results = self.hands.process(imgRGB)
# print(results.multi_hand_landmarks) #print none if hand is not in video else prints coordinates of hand

if self.results.multi_hand_landmarks:
for handLms in self.results.multi_hand_landmarks:
if draw:
self.mpDraw.draw_landmarks(img, handLms,
self.mpHands.HAND_CONNECTIONS) # draws all 21 points in hands
# mpHands.HAND_CONNECTIONS --> this connects the dots
return img

def findPosition(self, img, handNo=0, draw=True):
lmList = []

# extracting id and landmark(x,y,z) coordinate
if self.results.multi_hand_landmarks:
myHand = self.results.multi_hand_landmarks[handNo] # getting which hand
for id, lm in enumerate(myHand.landmark):
# print(id, lm) #values of x,y,z are in float
# we will convert them to pixels
h, w, c = img.shape
cx, cy = int(lm.x * w), int(lm.y * h)
# print(cx,cy) #now we don't know which value is for which point so we have to use id
# print(id, cx, cy)
lmList.append([id, cx, cy])
if draw:
cv.circle(img, (cx, cy), 7, (255, 0, 0), cv.FILLED)

return lmList


def main():
#dummy code to use in any other project
pTime = 0 # previous time
cTime = 0 # current rime
cap = cv.VideoCapture(0)
detector = handDetector() # calling the class
while True:
success, img = cap.read()
img = detector.findHands(img)
lmList = detector.findPosition(img)
if len(lmList) != 0:
print(lmList[4])

cTime = time.time()
fps = 1 / (cTime - pTime)
pTime = cTime

# display fps on screen
cv.putText(img, str(int(fps)), (10, 70), cv.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 3)

cv.imshow('Image', img)
cv.waitKey(1)


if __name__ == "__main__":
main()