def GetGlints(gray, thr): tempResultImg = cv2.cvtColor( gray, cv2.COLOR_GRAY2BGR) #used to draw temporary results props = RegionProps() val, binI = cv2.threshold( gray, thr, 255, cv2.THRESH_BINARY) #Using non inverted binary image #Combining opening and dialiting seems to be the best but is it ok that other glints are visible two?????!!!!! st7 = cv2.getStructuringElement(cv2.MORPH_CROSS, (7, 7)) st9 = cv2.getStructuringElement(cv2.MORPH_CROSS, (7, 7)) binI = cv2.morphologyEx(binI, cv2.MORPH_OPEN, st7) binI = cv2.morphologyEx(binI, cv2.MORPH_DILATE, st9, iterations=2) cv2.imshow("ThresholdGlints", binI) #Calculate blobs sliderVals = getSliderVals() #Getting slider values contours, hierarchy = cv2.findContours( binI, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) #Finding contours/candidates for pupil blob glints = [] glintEllipses = [] for cnt in contours: values = props.CalcContourProperties( cnt, ['Area', 'Length', 'Centroid', 'Extend', 'ConvexHull' ]) #BUG - Add cnt.astype('int') in Windows if values['Area'] < sliderVals['maxSizeGlints'] and values[ 'Area'] > sliderVals['minSizeGlints']: glints.append(values) centroid = (int(values['Centroid'][0]), int(values['Centroid'][1])) cv2.circle(tempResultImg, centroid, 2, (0, 0, 255), 4) glintEllipses.append(cv2.fitEllipse(cnt)) cv2.imshow("TempResults", tempResultImg) return glintEllipses
def GetPupil(gray, thr): #tempResultImg = cv2.cvtColor(gray,cv2.COLOR_GRAY2BGR) props = RegionProps() val, binI = cv2.threshold(gray, thr, 255, cv2.THRESH_BINARY_INV) st3 = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3)) binI = cv2.morphologyEx(binI, cv2.MORPH_CLOSE, st3) binI = cv2.morphologyEx(binI, cv2.MORPH_OPEN, st3) cv2.imshow("ThresholdPupil", binI) #display result in a window with sliders sliderVals = getSliderVals() contours, hierarchy = cv2.findContours(binI, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) pupils = [] pupilEllipses = [] for cnt in contours: if len(cnt) >= 5: values = props.CalcContourProperties( cnt, ['Area', 'Length', 'Centroid', 'Perimiter', 'Extend']) ellipse = cv2.fitEllipse( cnt) # fitEllipse([center][height,width],[angle]) if values['Area'] < sliderVals['maxSizePupil'] and values[ 'Area'] > sliderVals['minSizePupil']: pupils.append(values) pupilEllipses.append(ellipse) #centroid = (int(values['Centroid'][0]),int(values['Centroid'][1])) #cv2.circle(tempResultImg,centroid, 2, (0,0,255),4) #cv2.imshow("TempResults",tempResultImg)#display the temporary image return pupils, pupilEllipses
def GetGlints(gray, thr, maxSize): ''' Given a gray level image, gray and threshold value return a list of glint locations''' # YOUR IMPLEMENTATION HERE !!!! tempResultImg = cv2.cvtColor( gray, cv2.COLOR_GRAY2BGR) #used to draw temporary results props = RegionProps() val, binI = cv2.threshold(gray, thr, 255, cv2.THRESH_BINARY) cv2.imshow("TempResults", tempResultImg) #kernel = np.ones((4, 4), np.uint8) #binI = cv2.dilate(binI, kernel, iterations = 1) #binI = cv2.erode(binI, kernel, iterations = 1) #cv2.imshow("Threshold",binI) #Calculate blobs contours, hierarchy = cv2.findContours(binI, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) glints = [] # YOUR IMPLEMENTATION HERE !!! for con in contours: p = props.CalcContourProperties(con, ["Centroid", "Area"]) if p["Area"] < maxSize: glints.append(p['Centroid']) return glints
def GetGlints(gray, thr): #tempResultImg = cv2.cvtColor(gray,cv2.COLOR_GRAY2BGR) props = RegionProps() val, binI = cv2.threshold(gray, thr, 255, cv2.THRESH_BINARY) st7 = cv2.getStructuringElement(cv2.MORPH_CROSS, (7, 7)) binI = cv2.morphologyEx(binI, cv2.MORPH_OPEN, st7) binI = cv2.morphologyEx(binI, cv2.MORPH_DILATE, st7, iterations=2) cv2.imshow("ThresholdGlints", binI) sliderVals = getSliderVals() contours, hierarchy = cv2.findContours(binI, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) glints = [] for cnt in contours: values = props.CalcContourProperties( cnt, ['Area', 'Length', 'Centroid', 'Extend', 'ConvexHull']) if values['Area'] < sliderVals['maxSizeGlints'] and values[ 'Area'] > sliderVals['minSizeGlints']: centroid = (int(values['Centroid'][0]), int(values['Centroid'][1])) glints.append(centroid) #cv2.circle(tempResultImg,centroid, 2, (0,0,255),4) #cv2.imshow("TempResults",tempResultImg) return glints
def GetPupil(gray, thr, minSize, maxSize): '''Given a gray level image, gray and threshold value return a list of pupil locations''' tempResultImg = cv2.cvtColor( gray, cv2.COLOR_GRAY2BGR) #used to draw temporary results #cv2.imshow("TempResults",tempResultImg) props = RegionProps() val, binI = cv2.threshold(gray, thr, 255, cv2.THRESH_BINARY_INV) # Custom Morphology -- kernel = np.ones((10, 10), np.uint8) binI = cv2.dilate(binI, kernel, iterations=1) binI = cv2.erode(binI, kernel, iterations=1) #cv2.imshow("Threshold",binI) #Calculate blobs contours, hierarchy = cv2.findContours(binI, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) pupils = [] # YOUR IMPLEMENTATION HERE !!! for con in contours: if len(con) >= 5: p = props.CalcContourProperties( con, ["Area", "Boundingbox", "Centroid", "Extend"]) if minSize < p["Area"] < maxSize \ and p["Extend"] > 0.5: pupils.append(cv2.fitEllipse(con)) return pupils
def detectPupilKMeans(gray, K=2, distanceWeight=2, reSize=(40, 40)): ''' Detects the pupil in the image, gray, using k-means gray : grays scale image K : Number of clusters distanceWeight : Defines the weight of the position parameters reSize : the size of the image to do k-means on ''' #Resize for faster performance smallI = cv2.resize(gray, reSize) M, N = smallI.shape #Generate coordinates in a matrix X, Y = np.meshgrid(range(M), range(N)) #Make coordinates and intensity into one vectors z = smallI.flatten() x = X.flatten() y = Y.flatten() O = len(x) #make a feature vectors containing (x,y,intensity) features = np.zeros((O, 3)) features[:, 0] = z features[:, 1] = y / distanceWeight #Divide so that the distance of position weighs less than intensity features[:, 2] = x / distanceWeight features = np.array(features, 'f') # cluster data centroids, variance = kmeans(features, K) #use the found clusters to map label, distance = vq(features, centroids) # re-create image from labelIm = np.uint8(np.array(np.reshape(label, (M, N)))) props = RegionProps() val, binI = cv2.threshold(labelIm, 2, 255, cv2.THRESH_BINARY_INV) contours, hierarchy = cv2.findContours(binI, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) pupils = [] # YOUR IMPLEMENTATION HERE !!! for con in contours: p = props.CalcContourProperties( con, ["Area", "Boundingbox", "Centroid", "Extend"]) if len(con > 5): pupils.append(con) labelIm = np.zeros((M, N)) for pupil in pupils: for p in pupil: labelIm[p[0][0]][p[0][1]] = 1 f = figure(1) imshow(labelIm) f.canvas.draw() f.show()
def GetGlints(gray, thr): tempResultImg = cv2.cvtColor( gray, cv2.COLOR_GRAY2BGR) #used to draw temporary results props = RegionProps() # Do inverted thresholding: val, binI = cv2.threshold( gray, thr, 255, cv2.THRESH_BINARY) #Using non inverted binary image # Do morphological operations open, dilate(to increase the area size from opening) st7 = cv2.getStructuringElement(cv2.MORPH_CROSS, (7, 7)) st9 = cv2.getStructuringElement(cv2.MORPH_CROSS, (7, 7)) binI = cv2.morphologyEx(binI, cv2.MORPH_OPEN, st7) binI = cv2.morphologyEx(binI, cv2.MORPH_DILATE, st9, iterations=2) cv2.imshow("ThresholdGlints", binI) # Calculate blobs sliderVals = getSliderVals() #Getting slider values contours, hierarchy = cv2.findContours( binI, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) #Finding contours/candidates for pupil blob glints = [] glintEllipses = [] for cnt in contours: values = props.CalcContourProperties( cnt.astype('int'), ['Area', 'Length', 'Centroid', 'Extend', 'ConvexHull' ]) #BUG - Add cnt.astype('int') in Windows if len(cnt) >= 5: # Calculate the ellipse the blob best fits in using cv2 tools ellipse = cv2.fitEllipse(cnt.astype( 'int')) # fitEllipse([center][height,width],[angle]) # Filter blobs on area size #+/-: we haven't found the actual glints, but we get a very good list of candidates if values['Area'] < sliderVals['maxSizeGlints'] and values[ 'Area'] > sliderVals['minSizeGlints']: glints.append(values) centroid = (int(values['Centroid'][0]), int(values['Centroid'][1])) #cv2.circle(tempResultImg,centroid, 2, (0,0,255),4) glintEllipses.append(cv2.fitEllipse(cnt.astype('int'))) cv2.imshow("TempResults", tempResultImg) return glintEllipses
def GetIrisUsingThreshold(gray, thr): # #NOTE: Detecting Iris uses GlintsDetection UI for adjusting parameters. You eather run glints or iris detection in 'update' method. # #Assignment 1 part2 (2.1) #It is almost impossible to detect iris using threshold because I can't get threshold so that Iris becomes an ellipse. It always looks like croissant ;P. # tempResultImg = cv2.cvtColor( gray, cv2.COLOR_GRAY2BGR) #used to draw temporary results props = RegionProps() val, binI = cv2.threshold( gray, thr, 255, cv2.THRESH_BINARY) #Using non inverted binary image # #Applying morphology #Nothing seems to work here!! st7 = cv2.getStructuringElement(cv2.MORPH_CROSS, (13, 13)) st9 = cv2.getStructuringElement(cv2.MORPH_CROSS, (7, 7)) binI = cv2.morphologyEx(binI, cv2.MORPH_OPEN, st7) #binI= cv2.morphologyEx(binI, cv2.MORPH_CLOSE, st7) #binI = cv2.morphologyEx(binI, cv2.MORPH_DILATE, st9, iterations=2) cv2.imshow("ThresholdGlints", binI) #Calculate blobs sliderVals = getSliderVals() #Getting slider values contours, hierarchy = cv2.findContours( binI, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) #Finding contours/candidates for pupil blob irises = [] irisEllipses = [] for cnt in contours: values = props.CalcContourProperties( cnt, ['Area', 'Length', 'Centroid', 'Extend', 'ConvexHull' ]) #BUG - Add cnt.astype('int') in Windows if values['Area'] < sliderVals['maxSizeGlints'] and values[ 'Area'] > sliderVals['minSizeGlints']: irises.append(values) centroid = (int(values['Centroid'][0]), int(values['Centroid'][1])) cv2.circle(tempResultImg, centroid, 2, (0, 0, 255), 4) irisEllipses.append(cv2.fitEllipse(cnt)) cv2.imshow("TempResults", tempResultImg) return irisEllipses
def GetIrisUsingThreshold(gray, thr): ''' Given a gray level image, gray and threshold value return a list of iris locations''' props = RegionProps() val, binI = cv2.threshold(gray, thr, 255, cv2.THRESH_BINARY_INV) cv2.imshow("Threshold", binI) #Calculate blobs contours, hierarchy = cv2.findContours(binI, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) iris = [] for con in contours: if len(con) >= 5: p = props.CalcContourProperties( con, ["Area", "Boundingbox", "Centroid", "Extend"]) if 200 < p["Area"] \ and p["Extend"] > 0.3: iris.append(cv2.fitEllipse(con)) return iris
def GetPupil(gray, thr): tempResultImg = cv2.cvtColor( gray, cv2.COLOR_GRAY2BGR) #used to draw temporary results props = RegionProps() val, binI = cv2.threshold(gray, thr, 255, cv2.THRESH_BINARY_INV) #Combining Closing and Opening to the thresholded image st7 = cv2.getStructuringElement(cv2.MORPH_CROSS, (7, 7)) st9 = cv2.getStructuringElement(cv2.MORPH_CROSS, (9, 9)) st15 = cv2.getStructuringElement(cv2.MORPH_CROSS, (15, 15)) binI = cv2.morphologyEx(binI, cv2.MORPH_CLOSE, st9) #Close binI = cv2.morphologyEx(binI, cv2.MORPH_OPEN, st15) #Open binI = cv2.morphologyEx(binI, cv2.MORPH_DILATE, st7, iterations=2) #Dialite cv2.imshow("ThresholdPupil", binI) #Calculate blobs sliderVals = getSliderVals() #Getting slider values contours, hierarchy = cv2.findContours( binI, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) #Finding contours/candidates for pupil blob pupils = [] pupilEllipses = [] for cnt in contours: values = props.CalcContourProperties( cnt, ['Area', 'Length', 'Centroid', 'Extend', 'ConvexHull' ]) #BUG - Add cnt.astype('int') in Windows if values['Area'] < sliderVals['maxSizePupil'] and values[ 'Area'] > sliderVals['minSizePupil'] and values['Extend'] < 0.9: pupils.append(values) centroid = (int(values['Centroid'][0]), int(values['Centroid'][1])) cv2.circle(tempResultImg, centroid, 2, (0, 0, 255), 4) pupilEllipses.append(cv2.fitEllipse(cnt)) cv2.imshow("TempResults", tempResultImg) return pupilEllipses
def detectPupilKMeans(gray, K, distanceWeight, reSize): ''' Detects the pupil in the image, gray, using k-means gray : grays scale image K : Number of clusters distanceWeight : Defines the weight of the position parameters reSize : the size of the image to do k-means on ''' #Resize for faster performance smallI = cv2.resize(gray, reSize) M, N = smallI.shape #Generate coordinates in a matrix X, Y = np.meshgrid(range(M), range(N)) #Make coordinates and intensity into one vectors z = smallI.flatten() x = X.flatten() y = Y.flatten() O = len(x) #make a feature vectors containing (x,y,intensity) features = np.zeros((O, 3)) features[:, 0] = z features[:, 1] = y / distanceWeight #Divide so that the distance of position weighs lessthan intensity features[:, 2] = x / distanceWeight features = np.array(features, 'f') # cluster data centroids, variance = kmeans(features, K) centroids.sort( axis=0) # Sorting clusters according to intensity (ascending) pupilCluster = centroids[ 0] #Choosing the lowest intesity cluster. pupilCluster[0] is threshold for finding pupil for later #Wiktor's way of BLOB detection which is not that accurate----------------------------------- tempResultImg = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR) val, binI = cv2.threshold(gray, pupilCluster[0], 255, cv2.THRESH_BINARY_INV) #Appplying morphology st7 = cv2.getStructuringElement(cv2.MORPH_CROSS, (7, 7)) st15 = cv2.getStructuringElement(cv2.MORPH_CROSS, (15, 15)) binI = cv2.morphologyEx(binI, cv2.MORPH_CLOSE, st15) #Close binI = cv2.morphologyEx(binI, cv2.MORPH_OPEN, st7) #binI = cv2.morphologyEx(binI, cv2.MORPH_DILATE, st7, iterations=2) #Dialite cv2.imshow("ThresholdPupil", binI) sliderVals = getSliderVals() #Getting slider values props = RegionProps() contours, hierarchy = cv2.findContours( binI, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) #Finding contours/candidates for pupil blob pupils = [] pupilEllipses = [] for cnt in contours: values = props.CalcContourProperties( cnt, ['Area', 'Length', 'Centroid', 'Extend', 'ConvexHull' ]) #BUG - Add cnt.astype('int') in Windows if values['Area'] < sliderVals['maxSizePupil'] and values[ 'Area'] > sliderVals['minSizePupil'] and values['Extend'] < 0.9: pupils.append(values) centroid = (int(values['Centroid'][0]), int(values['Centroid'][1])) cv2.circle(tempResultImg, centroid, 2, (0, 0, 255), 4) pupilEllipses.append(cv2.fitEllipse(cnt)) cv2.imshow("TempResults", tempResultImg) #return pupilEllipses #--------------------------------------This snippet belongs to function detectPupilKmeans if there were any doubts------- #use the found clusters to map label, distance = vq(features, centroids) # re-create image from labelIm = np.array(np.reshape(label, (M, N))) '''This snippet is my try of applying BLOB detection on labelIm (ex 1.7) . I give up and I see no sense in doing that to be honest. Maybe I don't unerstand that.''' #Very ugly way of extracting pupil cluster on labelIm. It can be done in two lines I'm sure. I have no Idea why they made us do blob detection on labelIm anyway. I can have perfectly fine result on gray image using data I laready have #labelCopy = [] #for a in labelIm: # newBlock = [] # for b in a: # if b !=0: # b=255 # newBlock.append(b) # labelCopy.append(newBlock) #Applying some morphology #labelCopy = np.array(labelCopy) #Here I get binary image showing only cluster containing pixels which intensity equals pupil intensity. Here we should continue with blob detection... ''' end snippet''' f = figure(1) imshow(labelIm) #labelIm f.canvas.draw() f.show()
def run(fileName, resultFile='eyeTrackingResults.avi'): ''' MAIN Method to load the image sequence and handle user inputs''' global imgOrig, frameNr, drawImg setupWindowSliders() props = RegionProps() cap, imgOrig, sequenceOK = getImageSequence(fileName) videoWriter = 0 frameNr = 0 if (sequenceOK): update(imgOrig) printUsage() frameNr = 0 saveFrames = False while (sequenceOK): sliderVals = getSliderVals() frameNr = frameNr + 1 ch = cv2.waitKey(1) #Select regions if (ch == ord('m')): if (not sliderVals['Running']): roiSelect = ROISelector(imgOrig) pts, regionSelected = roiSelect.SelectArea( 'Select left eye corner', (400, 200)) if (regionSelected): leftTemplate = imgOrig[pts[0][1]:pts[1][1], pts[0][0]:pts[1][0]] if ch == 27: break if (ch == ord('s')): if ((saveFrames)): videoWriter.release() saveFrames = False print "End recording" else: imSize = np.shape(imgOrig) videoWriter = cv2.VideoWriter(resultFile, cv.CV_FOURCC('D', 'I', 'V', '3'), 15.0, (imSize[1], imSize[0]), True) #Make a video writer saveFrames = True print "Recording..." if (ch == ord('q')): break if (ch == 32): #Spacebar sliderVals = getSliderVals() cv2.setTrackbarPos('Stop/Start', 'ThresholdGlints', not sliderVals['Running']) cv2.setTrackbarPos('Stop/Start', 'ThresholdPupil', not sliderVals['Running']) if (ch == ord('r')): frameNr = 0 sequenceOK = False cap, imgOrig, sequenceOK = getImageSequence(fileName) update(imgOrig) sequenceOK = True sliderVals = getSliderVals() if (sliderVals['Running']): sequenceOK, imgOrig = cap.read() if (sequenceOK): #if there is an image update(imgOrig) if (saveFrames): videoWriter.write(drawImg) videoWriter.release
def detectPupilKMeans(gray, K, distanceWeight, reSize): ''' Detects the pupil in the image, gray, using k-means gray : grays scale image K : Number of clusters distanceWeight : Defines the weight of the position parameters reSize : the size of the image to do k-means on ''' gray2 = np.copy(gray) #Resize for faster performance smallI = cv2.resize(gray2, reSize) M, N = smallI.shape #Generate coordinates in a matrix X, Y = np.meshgrid(range(M), range(N)) #Make coordinates and intensity into one vectors z = smallI.flatten() x = X.flatten() y = Y.flatten() O = len(x) #Make feature vectors containing (x,y,intensity) features = np.zeros((O, 3)) features[:, 0] = z features[:, 1] = y / distanceWeight #Divide so that the distance of position weighs less than intensity features[:, 2] = x / distanceWeight features = np.array(features, 'f') #Cluster data centroids, variance = kmeans(features, K) centroids.sort( axis=0) # Sorting clusters according to intensity (ascending) pupilCluster = centroids[ 0] #Choosing the lowest intensity cluster. pupilCluster[0] is threshold for finding pupil for later # use the found clusters to map #label,distance = vq(features,centroids) # re-create image from #labelIm = np.array(np.reshape(label,(M,N))) # display the labeling #f = figure(1); imshow(labelIm); f.canvas.draw(); f.show() '''This snippet applies BLOB detection on labelIm (ex 1.7) .''' #labelCopy = [] #for a in labelIm: # newBlock = [] # for b in a: # if b !=0: # b=255 # newBlock.append(b) # labelCopy.append(newBlock) #Applying some morphology #labelCopy = np.array(labelCopy) #Here I get binary image showing only cluster containing pixels which intensity equals pupil intensity. Here we should continue with blob detection... ''' end snippet''' #Do BLOB detection tempResultImg = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR) val, binI = cv2.threshold(gray, pupilCluster[0], 255, cv2.THRESH_BINARY_INV) #Appplying morphology st3 = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3)) binI = cv2.morphologyEx(binI, cv2.MORPH_CLOSE, st3) binI = cv2.morphologyEx(binI, cv2.MORPH_OPEN, st3) cv2.imshow("ThresholdPupil", binI) sliderVals = getSliderVals() props = RegionProps() contours, hierarchy = cv2.findContours( binI, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) #Finding contours/candidates for pupil blob pupils = [] pupilEllipses = [] for cnt in contours: values = props.CalcContourProperties(cnt.astype('int'), [ 'Area', 'Length', 'Perimiter', 'Centroid', 'Extend', 'ConvexHull' ]) if len(cnt) >= 5 and values['Area'] < sliderVals[ 'maxSizePupil'] and values['Area'] > sliderVals['minSizePupil']: centroid = (int(values['Centroid'][0]), int(values['Centroid'][1])) pupils.append(values) pupilEllipses.append(cv2.fitEllipse(cnt.astype('int'))) cv2.circle(tempResultImg, centroid, 2, (0, 0, 255), 4) cv2.imshow("TempResults", tempResultImg) return pupils, pupilEllipses
def GetPupil(gray, thr): tempResultImg = cv2.cvtColor( gray, cv2.COLOR_GRAY2BGR) #used to draw temporary results # Blur the image (with a gausian filter, but ideally box filter (all 1s)), then apply histogram equalization to increase the contrast #+/-: threshold works better, but relying on the angle of ellipses decreases # grayBlured=cv2.GaussianBlur(gray, (41,41),0) # grayBlured=cv2.equalizeHist(grayBlured) # Do inverted thresholding: props = RegionProps() val, binI = cv2.threshold(gray, thr, 255, cv2.THRESH_BINARY_INV) #use grayBlurred? # Do morphological operations close, open and dialite(to increase the area size from opening) #+/-: remove noise or small objects, but remaining objects will be rounder and relying on the angle of the ellipses decreases #Combining Closing and Opening to the thresholded image st7 = cv2.getStructuringElement(cv2.MORPH_CROSS, (7, 7)) st9 = cv2.getStructuringElement(cv2.MORPH_CROSS, (9, 9)) st15 = cv2.getStructuringElement(cv2.MORPH_CROSS, (15, 15)) binI = cv2.morphologyEx(binI, cv2.MORPH_CLOSE, st9) #Close binI = cv2.morphologyEx(binI, cv2.MORPH_OPEN, st15) #Open binI = cv2.morphologyEx(binI, cv2.MORPH_DILATE, st7, iterations=2) #Dialite cv2.imshow("ThresholdPupil", binI) #Calculate blobs sliderVals = getSliderVals() #Getting slider values # Gather the remaining blobs for analysis contours, hierarchy = cv2.findContours( binI, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) #Finding contours/candidates for pupil blob pupils = [] #used to store center of blobs pupilEllipses = [] #used to store ellipses for cnt in contours: if len(cnt) >= 5: values = props.CalcContourProperties(cnt, [ 'Area', 'Length', 'Centroid', 'Perimiter', 'Extend', 'ConvexHull' ]) #BUG - Add cnt.astype('int') in Windows # Calculate circularity to eliminate pupil candidates... unfortunately, the perimeter using a function from SIGBTools seems inaccurate and calculating it might be hard, therefore improvise by using the angle of the ellipse # circularity=values['Perimiter']/(2*math.sqrt(math.pi*values['Area'])) #print circularity # Calculate the ellipse the blob best fits in using cv2 tools ellipse = cv2.fitEllipse(cnt.astype( 'int')) # fitEllipse([center][height,width],[angle]) #print ellipse,ellipse[2] # Filter blobs both on area size and angle of the ellipse #+/- we filter ellipses with angle between 80-100 degrees, but this doesn't mean circularity (e.g. a blob in the form of a cat/snake eye has also 90 degrees), but it suffices in our case... even circularity doesn't mean 100% correctness if values['Area'] < sliderVals['maxSizePupil'] and values[ 'Area'] > sliderVals['minSizePupil'] and ellipse[ 2] > 80 and ellipse[2] < 100: pupils.append(values) centroid = (int(values['Centroid'][0]), int(values['Centroid'][1])) pupilEllipses.append(ellipse) cv2.imshow("TempResults", tempResultImg) return pupilEllipses