# All the imports go here
import cv2
import numpy as np
import mediapipe as mp
from collections import deque
# Giving different arrays to handle colour points of different colour
#The code initializes deques to store points for different colors (blue,
green, red, and yellow)
#with a maximum length of 1024.
bpoints = [deque(maxlen=1024)]
gpoints = [deque(maxlen=1024)]
rpoints = [deque(maxlen=1024)]
ypoints = [deque(maxlen=1024)]
# These indexes will be used to mark the points in particular arrays of
specific colour
blue_index = 0
green_index = 0
red_index = 0
yellow_index = 0
#The kernel to be used for dilation purpose
#A kernel is created for morphological operations (dilation) later in the
code.
kernel = np.ones((5,5),np.uint8)
colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (0, 255, 255)]
colorIndex = 0
# Here is code for Canvas setup
paintWindow = np.zeros((471,636,3)) + 255
paintWindow = cv2.rectangle(paintWindow, (40,1), (140,65), (0,0,0), 2)
paintWindow = cv2.rectangle(paintWindow, (160,1), (255,65), (255,0,0), 2)
paintWindow = cv2.rectangle(paintWindow, (275,1), (370,65), (0,255,0), 2)
paintWindow = cv2.rectangle(paintWindow, (390,1), (485,65), (0,0,255), 2)
paintWindow = cv2.rectangle(paintWindow, (505,1), (600,65), (0,255,255), 2)
cv2.putText(paintWindow, "CLEAR", (49, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,
0, 0), 2, cv2.LINE_AA)
cv2.putText(paintWindow, "BLUE", (185, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,
0, 0), 2, cv2.LINE_AA)
cv2.putText(paintWindow, "GREEN", (298, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
(0, 0, 0), 2, cv2.LINE_AA)
cv2.putText(paintWindow, "RED", (420, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,
0, 0), 2, cv2.LINE_AA)
cv2.putText(paintWindow, "YELLOW", (520, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
(0, 0, 0), 2, cv2.LINE_AA)
cv2.namedWindow('Paint', cv2.WINDOW_AUTOSIZE)
1. paintWindow = numpy.zeros((471,636,3)) + 255: This line creates an initial blank
canvas with dimensions 636 pixels wide and 471 pixels high. The numpy.zeros
function initializes the canvas with all pixels having a value of (0, 0, 0), which
represents black. The addition of + 255 is used to change the canvas to a white
background. The resulting paintWindow is an image represented as a NumPy
array with three color channels (RGB).
2. The next five lines use cv2.rectangle to draw five rectangles on the canvas. These
rectangles serve as color choices for drawing. Each rectangle is defined by its
top-left and bottom-right coordinates and is outlined with a thickness of 2
pixels. The rectangles have the following characteristics:
The first rectangle is black, representing the "CLEAR" button.
The second rectangle is blue.
The third rectangle is red.
The fourth rectangle is green.
The fifth rectangle is yellow.
3. Following the rectangle drawing, there are five lines that use cv2.putText to add
text labels to the canvas. Each text label corresponds to the color choice
represented by the rectangles and is positioned near its respective rectangle.
The text labels are "CLEAR," "BLUE," "GREEN," "RED," and "YELLOW." The text
is written in black (0, 0, 0) with a font size of 0.5 and a thickness of 2 pixels.
4. Finally, cv2.namedWindow('Paint', cv2.WINDOW_AUTOSIZE) creates a window
named 'Paint' and configures it to automatically adjust its size based on the
content. This window is used to display the paintWindow canvas to the user.
In summary, this code block sets up the initial graphical user interface (GUI) for a
painting application. It creates a canvas with color choices and labels for the user to
interact with, and the canvas is displayed in a resizable window named 'Paint'.
# initialize mediapipe
mpHands = mp.solutions.hands
hands = mpHands.Hands(max_num_hands=1, min_detection_confidence=0.7)
mpDraw = mp.solutions.drawing_utils
1. mediapipe_hands = mediapipe.solutions.hands : This line assigns the
mediapipe.solutions.hands module to the variable mediapipe_hands . The
mediapipe.solutions.hands module provides hand tracking functionality.
2. hands = mediapipe_hands.Hands(max_num_hands=1, min_detection_confidence=0.7) : This
line creates an instance of the Hands class from the mediapipe_hands module. It
sets several parameters:
max_num_hands=1 : This parameter specifies that the system should
detect a maximum of 1 hand. You can change this value to detect
multiple hands if needed.
min_detection_confidence=0.7 : This parameter sets the minimum
confidence level required for a hand to be detected. A value of 0.7
means that only hands with a confidence level greater than or equal to
0.7 will be detected.
3. mediapipe_draw = mediapipe.solutions.drawing_utils : This line assigns the
mediapipe.solutions.drawing_utils module to the variable mediapipe_draw. The
drawing_utils module provides functions for drawing landmarks and
connections on the image, making it easier to visualize the results of hand
tracking.
Overall, these lines of code set up the MediaPipe library for hand tracking, configure
the detection parameters, and prepare drawing utilities to visualize the hand
landmarks and connections on the images or frames you capture.
# Initialize the webcam
cap = cv2.VideoCapture(0)
ret = True
while ret:
# Read each frame from the webcam
ret, frame = cap.read()
x, y, c = frame.shape
# Flip the frame vertically
frame = cv2.flip(frame, 1)
#hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
framergb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame = cv2.rectangle(frame, (40,1), (140,65), (0,0,0), 2)
frame = cv2.rectangle(frame, (160,1), (255,65), (255,0,0), 2)
frame = cv2.rectangle(frame, (275,1), (370,65), (0,255,0), 2)
frame = cv2.rectangle(frame, (390,1), (485,65), (0,0,255), 2)
frame = cv2.rectangle(frame, (505,1), (600,65), (0,255,255), 2)
cv2.putText(frame, "CLEAR", (49, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,
0, 0), 2, cv2.LINE_AA)
cv2.putText(frame, "BLUE", (185, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,
0, 0), 2, cv2.LINE_AA)
cv2.putText(frame, "GREEN", (298, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,
0, 0), 2, cv2.LINE_AA)
cv2.putText(frame, "RED", (420, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0,
0), 2, cv2.LINE_AA)
cv2.putText(frame, "YELLOW", (520, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,
0, 0), 2, cv2.LINE_AA)
#frame = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
# Get hand landmark prediction
result = hands.process(framergb)
# post process the result
if result.multi_hand_landmarks:
landmarks = []
for handslms in result.multi_hand_landmarks:
for lm in handslms.landmark:
# # print(id, lm)
# print(lm.x)
# print(lm.y)
lmx = int(lm.x * 640)
lmy = int(lm.y * 480)
landmarks.append([lmx, lmy])
# Drawing landmarks on frames
mpDraw.draw_landmarks(frame, handslms, mpHands.HAND_CONNECTIONS)
fore_finger = (landmarks[8][0],landmarks[8][1])
center = fore_finger
thumb = (landmarks[4][0],landmarks[4][1])
cv2.circle(frame, center, 3, (0,255,0),-1)
print(center[1]-thumb[1])
if (thumb[1]-center[1]<30):
bpoints.append(deque(maxlen=512))
blue_index += 1
gpoints.append(deque(maxlen=512))
green_index += 1
rpoints.append(deque(maxlen=512))
red_index += 1
ypoints.append(deque(maxlen=512))
yellow_index += 1
elif center[1] <= 65:
if 40 <= center[0] <= 140: # Clear Button
bpoints = [deque(maxlen=512)]
gpoints = [deque(maxlen=512)]
rpoints = [deque(maxlen=512)]
ypoints = [deque(maxlen=512)]
blue_index = 0
green_index = 0
red_index = 0
yellow_index = 0
paintWindow[67:,:,:] = 255
elif 160 <= center[0] <= 255:
colorIndex = 0 # Blue
elif 275 <= center[0] <= 370:
colorIndex = 1 # Green
elif 390 <= center[0] <= 485:
colorIndex = 2 # Red
elif 505 <= center[0] <= 600:
colorIndex = 3 # Yellow
else :
if colorIndex == 0:
bpoints[blue_index].appendleft(center)
elif colorIndex == 1:
gpoints[green_index].appendleft(center)
elif colorIndex == 2:
rpoints[red_index].appendleft(center)
elif colorIndex == 3:
ypoints[yellow_index].appendleft(center)
# Append the next deques when nothing is detected to avois messing up
else:
bpoints.append(deque(maxlen=512))
blue_index += 1
gpoints.append(deque(maxlen=512))
green_index += 1
rpoints.append(deque(maxlen=512))
red_index += 1
ypoints.append(deque(maxlen=512))
yellow_index += 1
# Draw lines of all the colors on the canvas and frame
points = [bpoints, gpoints, rpoints, ypoints]
# for j in range(len(points[0])):
# for k in range(1, len(points[0][j])):
# if points[0][j][k - 1] is None or points[0][j][k] is None:
# continue
# cv2.line(paintWindow, points[0][j][k - 1], points[0][j][k],
colors[0], 2)
for i in range(len(points)):
for j in range(len(points[i])):
for k in range(1, len(points[i][j])):
if points[i][j][k - 1] is None or points[i][j][k] is None:
continue
cv2.line(frame, points[i][j][k - 1], points[i][j][k],
colors[i], 2)
cv2.line(paintWindow, points[i][j][k - 1], points[i][j][k],
colors[i], 2)
cv2.imshow("Output", frame)
cv2.imshow("Paint", paintWindow)
if cv2.waitKey(1) == ord('q'):
break
# release the webcam and destroy all active windows
cap.release()
cv2.destroyAllWindows()