forked from UCSD-TIES/DVS-Python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlatestPupilDetection.py
More file actions
220 lines (181 loc) · 6.63 KB
/
latestPupilDetection.py
File metadata and controls
220 lines (181 loc) · 6.63 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
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
""" A class to perform actions on a eye. A eye can get its own pupil and
its own keypoints or sclera (depending on the algorithm)
"""
from Pupil import *
import cv2.cv as cv
import cv2
import numpy as np
from PIL import Image
import PIL.ImageOps
import math
from sys import maxint
DEBUG = True
########## Descriptive Variables for tweakable constants ###############
# Threshold parameters
LOWER_RED_RANGE = np.array((100,0,0))
UPPER_RED_RANGE = np.array((255,255,255))
# Erode and dilate parameters
ERODE_ITERATIONS = 1
DILATE_ITERATIONS = 1
# NOTE: tweaking any or all of these vars seems to only eliminate
# erroneous circles, not move the position of the circles detected
# Circle detection parameters
CIRCLE_RESOLUTION_RATIO = 1
# The minimum distance between circle centerpoints
CIRCLE_MIN_DISTANCE = 32
# I'm not exactly sure what the THRESHOLD ones do. See link for more info:
# http://www.adaptive-vision.com/en/technical_data/documentation/3.0/filters/FeatureDetection/cvHoughCircles.html
# You will need to look at the above url on archive.org. The actual site no longer has that page.
CIRCLE_THRESHOLD_1 = 10
# The accumulator threshold. The higher this is the less circles you get.
CIRCLE_THRESHOLD_2 = 2
CIRCLE_MIN_RADIUS = 10
CIRCLE_MAX_RADIUS = 500
# Circle drawing parameters
CIRCLE_COLOR = (0, 0, 255)
THICKNESS = 3
LINE_TYPE = 8
SHIFT = 0
# Smooth parameters
APERTURE_WIDTH = 9
APERTURE_HEIGHT = 9
# Canny parameters
CANNY_THRESHOLD_1 = 32
CANNY_THRESHOLD_2 = 2
############## Utility Methods ###################
def draw_circles(storage, output):
if DEBUG:
print "We are in draw_circles"
radius = storage[2]
center = (storage[0], storage[1])
if DEBUG:
print "Radius: " + str(radius)
print "Center: " + str(center)
cv.Circle(output, center, radius, CIRCLE_COLOR,
THICKNESS, LINE_TYPE, SHIFT)
################# Utility Methods #########################################
def findPupil(eyePhoto):
""" Detects a pupil in a photo of an eye and constructs a Pupil object
Uses opencv libarary methods to detect a pupil. Algorithm found here:
http://opencv-code.com/tutorials/pupil-detection-from-an-eye-image/
Algorithm Overview:
Load the source image.
Threshold based on a range of red.
Invert the photo.
Erode and dilate to reduce noise.
Find the contours.
Smooth to improve canny edge detection.
Canny edge detection.
Hough circle detection.
Choose the most central circle.
Then initializes eyePupil by constructing a new pupil object.
Returns false if no pupil is found
Args:
None
Return:
bool - True if there were no issues. False for any error
"""
# Load the source image and convert to cv mat
# eyePhoto is already stored as a mat. There is no need to convert
#eye = cv.GetMat(eyePhoto)
if DEBUG:
print "We're here in findPupil()"
print "EYE: " + str(eyePhoto)
print "The type of eyePhoto is: " + str(type(eyePhoto))
# Convert to a numpy array
eyeArr = eyePhoto
# Find the red in the photo
thresh = cv2.inRange(eyeArr,LOWER_RED_RANGE,UPPER_RED_RANGE)
if DEBUG:
cv.ShowImage("Binary", cv.fromarray(thresh))
cv.WaitKey(0)
cv.DestroyWindow("Binary")
# Invert the threshholded photo
rows = len(thresh)
for i in range(0,rows):
for j in range(0,len(thresh[i])):
thresh[i][j] = 255 - thresh[i][j]
if DEBUG:
cv.ShowImage("Inverted Thresh", cv.fromarray(thresh))
cv.WaitKey(0)
cv.DestroyWindow("Inverted Thresh")
# Erode and dilate the image to get rid of noise
erode = cv2.erode(thresh,None,iterations = ERODE_ITERATIONS)
if DEBUG:
cv.ShowImage("Erode", cv.fromarray(erode))
cv.WaitKey(0)
cv.DestroyWindow("Erode")
dilate = cv2.dilate(erode,None,iterations = DILATE_ITERATIONS)
if DEBUG:
cv.ShowImage("Dilate", cv.fromarray(dilate))
cv.WaitKey(0)
cv.DestroyWindow("Dilate")
# Find countours in the image
contours, hierarchy = cv2.findContours(dilate,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
# Draw the contours in white
cv2.drawContours(dilate,contours,-1,(255,255,255),-1)
if DEBUG:
cv.ShowImage("Contours", cv.fromarray(dilate))
cv.WaitKey(0)
cv.DestroyWindow("Contours")
print "type of dilate: " + str(type(dilate))
print "size of dilate: " + str(dilate.size)
cv2.imwrite("dilate.jpg", dilate )
big = bigContinWC(dilate)
print "Big is " + str(big)
eye = cv.fromarray(eyePhoto)
#draw_circles((big[0],big[1],3), eye)
cv2.line(eyePhoto, (big[0],big[1]),(big[0],big[1]+big[2]),CIRCLE_COLOR,THICKNESS,LINE_TYPE)
if DEBUG:
cv.ShowImage("Biggest", eye)
cv.WaitKey(0)
cv.DestroyWindow("Biggest")
def swap_dims(arr):
'''
swap the dimension of a 2d array
'''
newArr = np.empty([len(arr[0]),len(arr)])
for x in range(len(arr)):
for y in range(len(arr[x])):
newArr[y][x] = arr[x][y]
return newArr
def bigContinWC(photo):
'''
Method to find the line in the photo with the largest
continguous set of white pixels along that line.
Will be optimized to use sampling (hopefully) so we don't
need to loop through every coordinate of the photo
Expects photo to be a numpy.ndarray
Return:
stuff
'''
bigWC = -1
bigX = -1
bigY = -1
lineX = -1
lineY = -1
print "y goes from 0 to " + str(len(photo) -1 )
print "x goes from 0 to " + str(len(photo[0]) -1 )
for y in range(len(photo[0])):
lineWC = 0
wc =0
tempCount = 0
for x in range(len(photo)):
pixel = photo[x][y]
if pixel == 255:
tempCount = tempCount + 1
elif tempCount > wc:
wc = tempCount
lineX = x
lineY = y-wc
tempCount =0
lineWC = wc
if lineWC > bigWC:
bigWC = lineWC
bigX = lineX
bigY = lineY
return (bigX, bigY, bigWC)
#new code ladies and gentlemen
im = cv2.imread('C:/Users/Shannon/Documents/GitHub/DVS-Python/src/eyePhoto.png')
print type(im)
findPupil(im)