-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathblinky.py
More file actions
94 lines (77 loc) · 2.86 KB
/
blinky.py
File metadata and controls
94 lines (77 loc) · 2.86 KB
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
"""
Extract a csv file out of video file representing eye blinks.
"""
__author__ = "Dilawar Singh"
__copyright__ = "Copyright 2015, Dilawar Singh and NCBS Bangalore"
__credits__ = ["NCBS Bangalore"]
__license__ = "GNU GPL"
__version__ = "1.0.0"
__maintainer__ = "Dilawar Singh"
__email__ = "[email protected]"
__status__ = "Development"
import cv2
import numpy as np
import os
def merge_contours(cnts, img):
"""Merge these contours together. And create an image"""
for c in cnts:
hull = cv2.convexHull(c)
cv2.fillConvexPoly(img, hull, 0)
return img
def accept_contour_as_possible_eye( contour, threshold = 0.1 ):
# The eye has a certain geometrical shape. If it can not be approximated by
# an ellipse which major/minor < 0.8, ignore it.
return True
if len(contour) < 5:
# Too tiny to be an eye
return True
ellipse = cv2.fitEllipse( contour )
axes = ellipse[1]
minor, major = axes
if minor / major > threshold:
# Cool, also the area of ellipse and contour area cannot ve very
# different.
cntArea = cv2.contourArea( contour )
ellipseArea = np.pi * minor * major
if cntArea < 1:
return False
return True
else:
return False
def find_blinks_using_pixals( frame ):
# Blur the frame to remove hair etc.
frame = cv2.GaussianBlur( frame, (13, 13), 1 )
x, y = frame.shape
newframe = np.zeros( shape = frame.shape )
m, s = frame.mean(), frame.std()
thres = max( 0, m - 1 * s )
newframe[ frame < thres ] = 255
# Read the signal from half of the boundbox.
rs, cs = newframe.shape
r0, c0 = rs / 2, cs / 2
signal = np.sum( newframe[r0-rs/4:r0+rs/4,c0-cs/4:c0+cs/4] )
return frame, newframe, 1.0 * signal / float(rs*cs/4), -1
def process_frame(frame, method = 0):
if method > 0:
# Find edge in frame
s = np.mean(frame)
edges = cv2.Canny(frame, 50, 250)
cnts = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_KCOS)
cntImg = np.ones(frame.shape)
if not cnts:
return frame, None, 0, 0
merge_contours(cnts[0], cntImg)
# cool, find the contour again and convert again. Sum up their area.
im = np.array((1-cntImg) * 255, dtype = np.uint8)
cnts = cv2.findContours(im, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
hullImg = np.ones(frame.shape)
res = []
for c in cnts[0]:
c = cv2.convexHull(c)
if accept_contour_as_possible_eye( c ):
cv2.fillConvexPoly(hullImg, c, 0, 8)
res.append(cv2.contourArea(c))
hullImg = np.array((1-hullImg) * 255, dtype = np.uint8)
return frame, hullImg, sum(res), s
else:
return find_blinks_using_pixals( frame )