-
Notifications
You must be signed in to change notification settings - Fork 0
/
tut4.py
170 lines (147 loc) Β· 5.96 KB
/
tut4.py
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
import cv2
import numpy as np
import time
import pyautogui
# Constants
MOTION_UP = "Up"
MOTION_DOWN = "Down"
MOTION_LEFT = "Left"
MOTION_RIGHT = "Right"
NO_MOTION = "_"
def empty(a):
pass
def create_trackbars():
cv2.namedWindow('Trackbars')
cv2.resizeWindow('Trackbars', 700, 300)
cv2.createTrackbar('HueMin', 'Trackbars', 0, 179, empty)
cv2.createTrackbar('HueMax', 'Trackbars', 0, 179, empty)
cv2.createTrackbar('SatMin', 'Trackbars', 0, 255, empty)
cv2.createTrackbar('SatMax', 'Trackbars', 0, 255, empty)
cv2.createTrackbar('ValMin', 'Trackbars', 0, 255, empty)
cv2.createTrackbar('ValMax', 'Trackbars', 0, 255, empty)
def create_mask(img):
imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
hue_min = cv2.getTrackbarPos('HueMin', 'Trackbars')
hue_max = cv2.getTrackbarPos('HueMax', 'Trackbars')
sat_min = cv2.getTrackbarPos('SatMin', 'Trackbars')
sat_max = cv2.getTrackbarPos('SatMax', 'Trackbars')
val_min = cv2.getTrackbarPos('ValMin', 'Trackbars')
val_max = cv2.getTrackbarPos('ValMax', 'Trackbars')
lower = np.array([0,29,47])
upper = np.array([179,255 ,255])
mask = cv2.inRange(imgHSV, lower, upper)
return mask
def threshold(mask):
_,thresh = cv2.threshold(mask,127,255,cv2.THRESH_BINARY) # if pixel intensity <= 127 then set it as 0 and pixel intensity > 127 set it as 255
return thresh
def find_contours(thresh):
contours,heirarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) #give list of all essential boundary points
return contours
def max_contour(contours):
if len(contours) == 0:
return []
max_cntr = max(contours,key=lambda x: cv2.contourArea(x))
epsilon = 0.005*cv2.arcLength(max_cntr,True) # maximum distance from contour to approximated contour. It is an accuracy parameter
max_cntr = cv2.approxPolyDP(max_cntr,epsilon,True)
return max_cntr
def centroid(contour):
if len(contour) == 0: # if the array is empty return (-1,-1)
return (-1,-1)
M=cv2.moments(contour) # gives a dictionary of all moment values calculated
try:
x = int(M['m10']/M['m00']) # Centroid is given by the relations, πΆπ₯ =π10/π00 and πΆπ¦ =π01/π00
y = int(M['m01']/M['m00'])
except ZeroDivisionError:
return (-1,-1)
return (x,y)
def clean_image(mask):
img_eroded = cv2.erode(mask,(3,3), iterations=1)
img_dilated = cv2.dilate(img_eroded,(3,3),iterations = 1)
return img_dilated
def detect_hand(mask):
return np.average(mask) > 50
def velocity(x1,x2,t):
return (x2 - x1)/t
def detect_motion(x1,y1,x2,y2,t):
vel_x = int(velocity(x1,x2,t))
vel_y = int(velocity(y1,y2,t))
# print("The velocity of x is ",vel_x)
if vel_x > 15:
# print("Hello")
return MOTION_RIGHT
elif vel_x < -15:
return MOTION_LEFT
elif vel_y > 10:
return MOTION_DOWN
elif vel_y < -10:
return MOTION_UP
else:
return NO_MOTION
# performing actions based on hand motion
def performAction(hand_motion):
if hand_motion == MOTION_RIGHT:
pyautogui.press('right')
elif hand_motion == MOTION_LEFT:
pyautogui.press('left')
elif hand_motion == MOTION_UP:
pyautogui.press('up')
elif hand_motion == MOTION_DOWN:
pyautogui.press('down')
#################################################################################
########## Driver Code ##########################################################
#################################################################################
vid = cv2.VideoCapture(0);
create_trackbars()
frame_num = 4 # Counter for frame number
prev_x, prev_y, cur_x, cur_y = -1,-1,-1,-1 # Initializing the previous and current co-ordinates of the hand centroid
last_timestamp = 0 # Initializing the last recording timestamp
while(1):
_,frame = vid.read()
frame = cv2.flip(frame,1) # resolving mirror image issues
# For eye detection
fullScreenFrame=frame
frame = frame[:300, 300:] # only considering frame from row 0-300 and col from 300-end so that main focus is on our hands
frame = cv2.GaussianBlur(frame,(5,5),0) # to remove noise from frame
mask = create_mask(frame)
threshImg = threshold(mask)
cleaned_mask = clean_image(threshImg)
contours = find_contours(cleaned_mask)
frame = cv2.drawContours(frame,contours,-1,(255,0,0),2) # drawing all contours
max_cntr = max_contour(contours) # finding maximum contour of the thresholded area
(centroid_x,centroid_y) = centroid(max_cntr) # finding centroid of the maximum contour
if(centroid_x,centroid_y) != (-1,-1):
frame = cv2.circle(frame , (centroid_x,centroid_y) , 5 , (255,255,0) , -1) # drawing a circle on the identified centroid
# print(cv2.contourArea(max_cntr))
hand_detected = cv2.contourArea(max_cntr) >= 14000 # Max contour area must be greater than thois threshold
# print(type(hand_detected))
if hand_detected:
if prev_x == -1:
prev_x, prev_y = centroid_x, centroid_y
frame_num = 4
# print(prev_x,prev_y)
if frame_num == 0:
cur_time = time.time()
time_elapsed = cur_time - last_timestamp
hand_motion = detect_motion(prev_x, prev_y,
centroid_x, centroid_y, time_elapsed)
print(hand_motion)
performAction(hand_motion)
prev_x, prev_y = centroid_x, centroid_y
last_timestamp = time.time()
# Re-initializing the frame counter
if hand_motion != NO_MOTION:
frame_num = 4
else:
frame_num = 6
else:
frame_num -= 1
else:
prev_x, prev_y = -1, -1
frame_num = 4
cv2.imshow('video',frame)
cv2.imshow("mask",mask)
key = cv2.waitKey(6)
if key == ord('q'):
break
vid.release()
cv2.destroyAllWindows()