Skip to content

Instantly share code, notes, and snippets.

@BenjaminPoilve
Created August 22, 2016 08:45
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save BenjaminPoilve/c946c4505a9b1c92fa4d5fd116c802e2 to your computer and use it in GitHub Desktop.
Save BenjaminPoilve/c946c4505a9b1c92fa4d5fd116c802e2 to your computer and use it in GitHub Desktop.
Fabian Timm eye center location algorithm in python
import operator
import numpy as np
import math
import cv2
from config import config
kGradientThreshold = 10.0
kWeightBlurSize = 5;
maxEyeSize=8;
def computeGradient(img):
out = np.zeros((img.shape[0],img.shape[1]),dtype=np.float32) #create a receiver array
if img.shape[0] < 2 or img.shape[1] < 2: # TODO I'm not sure that secure out of range
print "EYES too small"
return out
for y in xrange(0,out.shape[0]):
out[y][0]=img[y][1]-img[y][0]
for x in xrange(1,out.shape[1]-1):
out[y][x]=(img[y][x+1]-img[y][x-1])/2.0
out[y][out.shape[1]-1]=img[y][out.shape[1]-1]-img[y][out.shape[1]-2]
return out
def testPossibleCentersFormula(x, y, weight, gx, gy, out):
for cy in xrange(0,out.shape[0]):
for cx in xrange(0,out.shape[1]):
if x==cx and y==cy :
continue
dx= x-cx
dy= y-cy
magnitude= math.sqrt(dx*dx+dy*dy)
dx=dx/magnitude
dy=dy/magnitude
dotProduct=dx*gx+dy*gy
dotProduct=max(0.0, dotProduct)
out[cy][cx]+=dotProduct*dotProduct*weight[cy][cx]
def findEyeCenter(eyeImage, offset):
eyeImg = cv2.cvtColor(eyeImage, cv2.COLOR_BGR2GRAY)
eyeImg = eyeImg.astype(np.float32)
scaleValue=1.0;
if(eyeImg.shape[0]>maxEyeSize or eyeImg.shape[0]>maxEyeSize ):
scaleValue=max(maxEyeSize/float(eyeImg.shape[0]),maxEyeSize/float(eyeImg.shape[1]))
eyeImg=cv2.resize(eyeImg,None, fx=scaleValue,fy= scaleValue, interpolation = cv2.INTER_AREA)
gradientX= computeGradient(eyeImg)
gradientY= np.transpose(computeGradient(np.transpose(eyeImg)))
gradientMatrix=matrixMagnitude(gradientX, gradientY)
gradientThreshold=computeDynamicThreshold(gradientMatrix,kGradientThreshold)
#Normalisation
for y in xrange(0,eyeImg.shape[0]): #Iterate through rows
for x in xrange(0,eyeImg.shape[1]): #Iterate through columns
if(gradientMatrix[y][x]>gradientThreshold):
gradientX[y][x]=gradientX[y][x]/gradientMatrix[y][x]
gradientY[y][x]=gradientY[y][x]/gradientMatrix[y][x]
else:
gradientX[y][x]=0.0
gradientY[y][x]=0.0
#Invert and blur befor algo
weight = cv2.GaussianBlur(eyeImg,(kWeightBlurSize,kWeightBlurSize),0)
for y in xrange(0,weight.shape[0]): #Iterate through rows
for x in xrange(0,weight.shape[1]): #Iterate through columns
weight[y][x]=255-weight[y][x]
outSum = np.zeros((eyeImg.shape[0],eyeImg.shape[1]),dtype=np.float32) #create a receiver array
for y in xrange(0,outSum.shape[0]): #Iterate through rows
for x in xrange(0,outSum.shape[1]): #Iterate through columns
if(gradientX[y][x]==0.0 and gradientY[y][x]==0.0):
continue
testPossibleCentersFormula(x, y, weight, gradientX[y][x], gradientY[y][x], outSum)
#scale all the values down, basically averaging them
numGradients = (weight.shape[0]*weight.shape[1]);
out= np.divide(outSum, numGradients*10)
if config.gui:
cv2.imshow("eyeGradient", out)
#find maxPoint
(minval, maxval,mincoord,maxcoord) = cv2.minMaxLoc(out)
maxcoord=(int(maxcoord[0]/scaleValue),int(maxcoord[1]/scaleValue))
return tuple(map(operator.add, maxcoord, offset))
def matrixMagnitude(gradX,gradY):
mags = np.zeros((gradX.shape[0],gradX.shape[1]),dtype=np.float32) #create a receiver array
for y in xrange(0,mags.shape[0]):
for x in xrange(0,mags.shape[1]):
gx=gradX[y][x]
gy=gradY[y][x]
magnitude=math.sqrt(gx*gx+gy*gy)
mags[y][x]=magnitude
return mags
def computeDynamicThreshold(gradientMatrix,DevFactor ):
(meanMagnGrad, meanMagnGrad) = cv2.meanStdDev(gradientMatrix)
stdDev=meanMagnGrad[0]/math.sqrt(gradientMatrix.shape[0]*gradientMatrix.shape[1])
return DevFactor*stdDev+meanMagnGrad[0]
@asanchez19
Copy link

is it work ? Im trying to do something like this for an university project.

Thanks.

@TimBluesWin
Copy link

Hello, I already tried to run the code, but nothing happens (no error message either, and I have installed config module for python). Is there something that I miss?

I am currently using Trisquel 8.0, Python version 2.7.12, and also opencv-contrib-python version 3.4.2.16 and opencv-python version 3.4.2.16 installed.

Any help will be really appreciated.

@BenjaminPoilve
Copy link
Author

Hi,
Sorry for the delay, for some reason, Github does not show notification for comment on gists. I am working on a rework of the code for gaze estimation, might be more legible. Not over, but see here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment