Skip to content

Instantly share code, notes, and snippets.

@pgaijin66
Last active March 1, 2023 09:36
Show Gist options
  • Save pgaijin66/f0f65f2e4fc078635496ed4cf735d682 to your computer and use it in GitHub Desktop.
Save pgaijin66/f0f65f2e4fc078635496ed4cf735d682 to your computer and use it in GitHub Desktop.
Draw on screen using OpenCV and Handgesture.
# DO NOT REMOVE THESE TWO LINES.
# Disabling hardward transform flag for OpenCV package. This needs to be done before importing OpenCV package.
# This will stop slow startup and initialization behaviour effectively making webcam initialize faster.
# See more: https://github.com/opencv/opencv/issues/17687
import os
os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0"
# Now import openCV package
import cv2
import mediapipe as mp
import numpy as np
import time
from cvzone.HandTrackingModule import HandDetector
from threading import Thread
class WebcamStream:
""" WebcamStream captures frames from the web cam."""
def __init__(self, stream_id=0):
self.stream_id = stream_id # default is 0 for main camera
self.vcap = cv2.VideoCapture(self.stream_id)
if self.vcap.isOpened() is False :
print("[Exiting]: Error accessing webcam stream.")
exit(0)
fps_input_stream = int(self.vcap.get(5)) # hardware fps
print("FPS of input stream: {}".format(fps_input_stream))
# reading a single frame from vcap stream for initializing
self.grabbed , self.frame = self.vcap.read()
if self.grabbed is False :
print('[Exiting] No more frames to read')
exit(0)
# self.stopped is initialized to False
self.stopped = True
# thread instantiation
self.t = Thread(target=self.update, args=())
self.t.daemon = True # daemon threads run in background
def start(self):
self.stopped = False
self.t.start()
def update(self):
while True :
if self.stopped is True :
break
self.grabbed , self.frame = self.vcap.read()
if self.grabbed is False :
print('[Exiting] No more frames to read')
self.stopped = True
break
self.vcap.release()
def read(self):
return self.frame
def stop(self):
self.stopped = True
class HandGestureDetector:
""" HandGestureDetector detects hand and draws on the x and y co-ordinates of the index finger """
def __init__(self, cap, hands, mpHands, detector, canvas):
self.mpHands = mpHands
self.hands = hands
self.cap = cap
self.detector = detector
self.canvas = canvas
self.canvas.fill(255)
self.canvas= cv2.flip(canvas, 1)
self.x = 0
self.y = 0
self.drawing = False
self.tool= None
self.thickness= 3
self.input_size= (1200, 1080)
self.pTime = 0
self.cTime = 0
def run_detection(self):
num_frames_processed = 0
start = time.time()
while True:
img = self.cap.read()
img_resized= cv2.resize(img, self.input_size)
hand, img = self.detector.findHands(img_resized)
img= cv2.flip(img, 1)
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
results = self.hands.process(imgRGB)
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
index_finger_tip = hand_landmarks.landmark[self.mpHands.HandLandmark.INDEX_FINGER_TIP]
cx, cy = int(index_finger_tip.x * self.canvas.shape[1]), int(index_finger_tip.y * self.canvas.shape[0])
if hand:
handType = hand[0]['type']
if handType == "Left":
self.drawing = False
cv2.circle(self.canvas, (cx, cy), 200, (0), cv2.FILLED)
elif handType == 'Right':
if self.drawing:
cv2.line(self.canvas, (self.x, self.y), (cx, cy), 0, thickness=10)
self.x = cx
self.y = cy
self.drawing = True
# Adding some readability to the code to see how much frame per second we are getting ( FPS ). In general mac have
# FPS of around 50
self.cTime = time.time()
fps = 1/( self.cTime- self.pTime)
self.pTime = self.cTime
cv2.imshow("Canvas", self.canvas)
cv2.putText(img, f'FPS: {int(fps)}', (10,70), cv2.FONT_HERSHEY_PLAIN, 3, (255,0,255), 3)
cv2.imshow("image", img)
# This will gratefully quit the program when you press "ESC"
if cv2.waitKey(5) & 0XFF == 27:
break
end = time.time()
self.cap.stop() # stop the webcam stream
def __del__(self):
cap.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
# Moving out things that should not be inside the class constructor.
cap = WebcamStream(stream_id=0) # 0 id for main camera
cap.start()
# cap = cv2.VideoCapture(0)
# cap.set(cv2.CAP_PROP_FPS,40)
mpHands = mp.solutions.hands
hands = mpHands.Hands(static_image_mode=False,
max_num_hands=2,
min_detection_confidence=0.5,
min_tracking_confidence=0.5)
detector = HandDetector(detectionCon=0.8, maxHands=2)
canvas = np.zeros((1200, 1800, 3), np.uint8)
model = HandGestureDetector(cap, hands, mpHands, detector, canvas)
model.run_detection()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment