forked from lzane/Fingers-Detection-using-OpenCV-and-Python
-
Notifications
You must be signed in to change notification settings - Fork 0
/
new.py
139 lines (116 loc) · 4.9 KB
/
new.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
import cv2
import numpy as np
import copy
import math
#from appscript import app
# Environment:
# OS : Mac OS EL Capitan
# python: 3.5
# opencv: 2.4.13
# parameters
cap_region_x_begin=0.5 # start point/total width
cap_region_y_end=0.8 # start point/total width
threshold = 60 # BINARY threshold
blurValue = 41 # GaussianBlur parameter
bgSubThreshold = 50
learningRate = 0
# variables
isBgCaptured = 0 # bool, whether the background captured
triggerSwitch = False # if true, keyborad simulator works
def printThreshold(thr):
print("! Changed threshold to "+str(thr))
def removeBG(frame):
fgmask = bgModel.apply(frame,learningRate=learningRate)
# kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
# res = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
kernel = np.ones((3, 3), np.uint8)
fgmask = cv2.erode(fgmask, kernel, iterations=1)
res = cv2.bitwise_and(frame, frame, mask=fgmask)
return res
def calculateFingers(res,drawing): # -> finished bool, cnt: finger count
# convexity defect
hull = cv2.convexHull(res, returnPoints=False)
if len(hull) > 3:
defects = cv2.convexityDefects(res, hull)
if type(defects) != type(None): # avoid crashing. (BUG not found)
cnt = 0
for i in range(defects.shape[0]): # calculate the angle
s, e, f, d = defects[i][0]
start = tuple(res[s][0])
end = tuple(res[e][0])
far = tuple(res[f][0])
a = math.sqrt((end[0] - start[0]) ** 2 + (end[1] - start[1]) ** 2)
b = math.sqrt((far[0] - start[0]) ** 2 + (far[1] - start[1]) ** 2)
c = math.sqrt((end[0] - far[0]) ** 2 + (end[1] - far[1]) ** 2)
angle = math.acos((b ** 2 + c ** 2 - a ** 2) / (2 * b * c)) # cosine theorem
if angle <= math.pi / 2: # angle less than 90 degree, treat as fingers
cnt += 1
cv2.circle(drawing, far, 8, [211, 84, 0], -1)
return True, cnt
return False, 0
# Camera
camera = cv2.VideoCapture(0)
camera.set(10,200)
cv2.namedWindow('trackbar')
cv2.createTrackbar('trh1', 'trackbar', threshold, 100, printThreshold)
while camera.isOpened():
ret, frame = camera.read()
threshold = cv2.getTrackbarPos('trh1', 'trackbar')
frame = cv2.bilateralFilter(frame, 5, 50, 100) # smoothing filter
frame = cv2.flip(frame, 1) # flip the frame horizontally
cv2.rectangle(frame, (int(cap_region_x_begin * frame.shape[1]), 0),
(frame.shape[1], int(cap_region_y_end * frame.shape[0])), (255, 0, 0), 2)
cv2.imshow('original', frame)
# Main operation
if isBgCaptured == 1: # this part wont run until background captured
img = removeBG(frame)
img = img[0:int(cap_region_y_end * frame.shape[0]),
int(cap_region_x_begin * frame.shape[1]):frame.shape[1]] # clip the ROI
cv2.imshow('mask', img)
# convert the image into binary image
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (blurValue, blurValue), 0)
cv2.imshow('blur', blur)
ret, thresh = cv2.threshold(blur, threshold, 255, cv2.THRESH_BINARY)
cv2.imshow('ori', thresh)
# get the coutours
thresh1 = copy.deepcopy(thresh)
_,contours, hierarchy = cv2.findContours(thresh1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
length = len(contours)
maxArea = -1
if length > 0:
for i in range(length): # find the biggest contour (according to area)
temp = contours[i]
area = cv2.contourArea(temp)
if area > maxArea:
maxArea = area
ci = i
res = contours[ci]
hull = cv2.convexHull(res)
drawing = np.zeros(img.shape, np.uint8)
cv2.drawContours(drawing, [res], 0, (0, 255, 0), 2)
cv2.drawContours(drawing, [hull], 0, (0, 0, 255), 3)
isFinishCal,cnt = calculateFingers(res,drawing)
if triggerSwitch is True:
if isFinishCal is True and cnt <= 2:
print (cnt)
#app('System Events').keystroke(' ') # simulate pressing blank space
cv2.imshow('output', drawing)
# Keyboard OP
k = cv2.waitKey(10)
if k == 27: # press ESC to exit
camera.release()
cv2.destroyAllWindows()
break
elif k == ord('b'): # press 'b' to capture the background
bgModel = cv2.createBackgroundSubtractorMOG2(0, bgSubThreshold)
isBgCaptured = 1
print( '!!!Background Captured!!!')
elif k == ord('r'): # press 'r' to reset the background
bgModel = None
triggerSwitch = False
isBgCaptured = 0
print ('!!!Reset BackGround!!!')
elif k == ord('n'):
triggerSwitch = True
print ('!!!Trigger On!!!')