Code covered by the BSD License  

Highlights from
Accurate Eye center location

from Accurate Eye center location by GAGAN
The following code can be used to accurately determine eye center of any image.

eyepoint(input,kernelsize,sigma,minrad,maxrad,varargin)
function [ro,c] = eyepoint(input,kernelsize,sigma,minrad,maxrad,varargin)
%Finds the center of a human eye in
%a grayscale or rgb image using isophote curvature
%Reference: Accurate Eye Center Location and Tracking Using Isophote
%Curvature, Roberto Valenti and Theo Gevers





% %%%%%% Input Arguments
% input = Either Grayscale or RGB image.
% kernelsize = size of Gaussian kernel used for smoothing and filtering the
% image.
% sigma = Standard deviation of gaussian filter.
% minrad = minimum value of magnitude of displacement vector estimated using the method that
% should be used for voting. Values below it are not used for voting.
% maxrad = maximum value of magnitude of displacement vector estimated
% using  the method that should be used for voting. Values above it are not
% used for center voting.
% thresh (Not required when using curved method. but required during using
% canny method
%)= threshhold value as required for Canny operator in Edge method. Default
%is 0.37
%scale(optional)=To specify which scale to use. Default is 1.
% method(optional)= Method to be used for determinin center. can be string named
% 'canny' or 'curved'. default is 'curved'.


% %%%%%% Output Arguments
% r = y-coordinates of estimated center.
% c =x-coordinates of estimated center.


% %%%%% Example:
% eyepoint('C:\Singh\Data\faces\BioID\ftp.uni-erlangen.de\pub\facedb\BioID_
% 1152.png',8,3,4,30,0.37,'canny');

% eyepoint('C:\Singh\Data\faces\BioID\ftp.uni-erlangen.de\pub\facesdb\BioID
% _1152.png',8,5,4,30);
%eyepoint('C:\highres\008\008_01.jpg',8,1,4,50,0.5)
%eyepoint('C:\highres\032\032_01.jpg',8,1,5,50,0.43,'canny')

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Validate the input arguments
strarray{1}='curved';
strarray{2}='canny';
error(nargchk(5,8,nargin));
% If number of input arguments is 8.
if(nargin==8)
method=validatestring(varargin{3},strarray);
thresh=varargin{1}(:);
scale=varargin{2}(:);
end
if(nargin==7)
    if(ischar(varargin{2}(:)))
        method=validatestring(varargin{2},strarray);
    if(strmatch(method,'curved','exact'))
        scale=varargin{1}(:);
    else 
        thresh=varargin{1}(:);
        scale=1;
    end
    else
        method='curved';
        thresh=varargin{1}(:);
        scale=varargin{2}(:);
    end
end
if(nargin==6)
    if(ischar(varargin{1}(:)))
        method=validatestring(varargin{1},strarray);
        if(strmatch(method,'curved','exact'))
            scale=1;
        else
            thresh=0.37;
            scale=1;
        end
    else
    method='curved';
    scale=varargin{1}(:);
    end
end
% Read the image
I=imread(input);
iptsetpref('useIPPL',false);
scale
if(scale~=1)
I=imresize(I,scale,'lanczos3');
end
% If the image is rgb then convert it into grayscale
if(size(I,3)==3)
I=rgb2gray(I);
end
imagesc(I),title('Original Image'),impixelinfo,colormap('gray');
hold on;
% Crop the image and adjust it. It saves computation and makes sure that only relevant areas
% of the Image are used.
K=imadjust(I,stretchlim(I),[]);
[J,rect]=imcrop(K);
hold off;
m=[rect(1) rect(1)+rect(3)];
n=[rect(2) rect(2)+rect(4)];
% Display the cropped image
figure,imagesc(J,'XData',m,'YData',n),title('Original Cropped Image'),impixelinfo,colormap('gray');
% Obtain the kernel for smoothing the image using the given arguments 
sz=2*kernelsize-1;
h=zeros(2*sz-1,2*sz-1);
for y=-(sz-1):1:(sz-1)
    for x=-(sz-1):1:(sz-1)
      a=x+sz;
      b=y+sz;
      h(b,a)=exp(-((x*x) + (y*y))/(2*sigma*sigma))/(2*pi*sigma*sigma);
    end
end
% smooth the image using imfilter function and kernel obtained above
% Apply the canny operator on the image if specified
if(strmatch(method,'canny','exact'))
J=imfilter(J,h,'replicate','conv');
J=edge(J,'canny',thresh,sigma);
end
% Convert the data type of the image to double. Now divide the cropped
% image into two parts. One for each eye. Store it in variable cel
cel{1}=J(1:1:size(J,1),1:1:round(0.50*size(J,2)));
cel{2}=J(1:1:size(J,1),round(0.50*size(J,2)):1:size(J,2));
ro=zeros(2);
c=zeros(2);
%for each eye apply the algorithm based on the method specified.
for gagan=1:1:2
cel{gagan}=im2double(cel{gagan});
% Smooth the image.
cel{gagan}=imfilter(cel{gagan},h,'replicate','conv');
% Display the image obtained after
% smoothing
figure,imagesc(cel{gagan},'XData',m,'YData',n),title('Image after Blurring with Gaussian'),impixelinfo,colormap('gray');
% Calculate the gradient using the 7-tap Coefficients given by Farid and
% Simoncelli given in their paper "Differentiation of Discrete
% Multi-Dimensional Signals".If scale is les than or equal to 1. Otherwise
% compute using gradient method of MATLAB.
if(scale<=1)
 p = [ 0.004711  0.069321  0.245410  0.361117  0.245410  0.069321  0.004711];
  d1 = [ 0.018708  0.125376  0.193091  0.000000 -0.193091 -0.125376 -0.018708];
  d2 = [ 0.055336  0.137778 -0.056554 -0.273118 -0.056554  0.137778  0.055336];
 FX=conv2(p,d1,cel{gagan},'same');
 FY=conv2(d1,p,cel{gagan},'same');
 FXX=conv2(p,d2,cel{gagan},'same');
 FYY=conv2(d2,p,cel{gagan},'same');
 FXY=conv2(d1,p,FX,'same');
else
[FX,FY]=gradient(cel{gagan});
[FXX,FXY]=gradient(FX);
[FYX,FYY]=gradient(FY);
end
% Calculate the curvedness
curved=sqrt(im2double(FXX.^2 + 2*FXY.^2 + FYY.^2));
% Display the curvedness
figure,imagesc(abs(curved),'XData',m,'YData',n),title('Curvedness'),impixelinfo,colormap('gray');
% Calculate the displacement vectors
G1=FX.^2 + FY.^2;
G2=((FY.^2).*FXX) - (2*(FX.*FXY).*FY) + ((FX.^2).*FYY);
G2=round(G1./G2);
G2=-1*G2;
% Clear the redundant variables to free some space
clear FXX;
clear FXY;
clear FYY;
G4=G2.*FX;
G5=G2.*FY;
G1=G1.^(1.5);
G8=round(G2./G1);
G8=-1*G8;
clear FX;
clear FY;
D_vector=zeros(size(cel{gagan},1),size(cel{gagan},2),2);
for y=1:1:size(cel{gagan},1)
for x=1:1:size(cel{gagan},2)
        D_vector(y,x,1)=G4(y,x);
        D_vector(y,x,2)=G5(y,x);
end
end
D_vector=round(D_vector);
Mag_D_vector=sqrt(D_vector(:,:,1).^2 + D_vector(:,:,1).^2);
% Create the weight array.Make curvedness as the voting scheme if method
% specified is curved otherwise use 1 for canny.
weight=zeros(size(cel{gagan},1),size(cel{gagan},2));
for y=1:1:size(cel{gagan},1)
    for x=1:1:size(cel{gagan},2)
        if(strmatch(method,'canny','exact'))
            weight(y,x)=1;
        else
      weight(y,x)=abs(curved(y,x));
    end
    end
end
% Create the accumulator that will store the result
mapped=zeros(size(cel{gagan},1),size(cel{gagan},2));
Used_D_Vector=zeros(size(cel{gagan},1),size(cel{gagan},2),2);
for y=1:1:size(cel{gagan},1)
    for x=1:1:size(cel{gagan},2)
        if((D_vector(y,x,1)~=0) || (D_vector(y,x,2)~=0))
        if((x+D_vector(y,x,1)>0) &&  (y+D_vector(y,x,2)>0))
        if((x+D_vector(y,x,1)<=size(cel{gagan},2)) &&  (y+D_vector(y,x,2)<=size(cel{gagan},1)) && (G8(y,x)<0))
            if((Mag_D_vector(y,x)>=minrad)&&(Mag_D_vector(y,x)<=maxrad))
                % use only those displacement vectors which are within the
                % specified range
            Used_D_Vector(y,x,1)=D_vector(y,x,1);
            Used_D_Vector(y,x,2)=D_vector(y,x,2);  
        mapped(y+D_vector(y,x,2),x+D_vector(y,x,1))=mapped(y+D_vector(y,x,2),x+D_vector(y,x,1)) + weight(y,x);
            end
        end
        end
        end
    end
end
% plot the used displacement vectors
quiver(Used_D_Vector(:,:,1),Used_D_Vector(:,:,2),0),title('Displacement Vector');
% smooth the accumulator
mapped=imfilter(mapped,h,'replicate','conv');
% plot the mapped image obtained after smoothing
figure,imagesc(mapped,'XData',m,'YData',n),title('Mapped Image after Blurring with Gaussian'),impixelinfo,colormap('gray');
% Find the maximum isocenter
[ro(gagan),c(gagan)]=find(mapped==max(mapped(:)));
mapped(mapped<max(mapped(:)))=0;
% plot the result
figure,imagesc(mapped,'XData',m,'YData',n),title('Result'),impixelinfo,colormap('gray');
% Back project to see who voted for the center
radiusmap{gagan}=zeros(size(cel{gagan},1),size(cel{gagan},2));
for y=1:1:size(cel{gagan},1)
    for x=1:1:size(cel{gagan},2)
            if(((ro(gagan)-2)<=(y+Used_D_Vector(y,x,2)))&&((ro(gagan)+2)>=(y+Used_D_Vector(y,x,2))) && ((c(gagan)-2)<=(x+Used_D_Vector(y,x,1)))&&((c(gagan)+2)>=(x+Used_D_Vector(y,x,1))))
                radiusmap{gagan}(y,x)=radiusmap{gagan}(y,x) + abs(curved(y,x));
            end
    end
 end
figure,imagesc(abs(curved),'XData',m,'YData',n),title('Curvedness'),impixelinfo,colormap('gray');
% plot the back projected image
figure,imagesc(radiusmap{gagan},'XData',m,'YData',n),title('Radiusmap'),impixelinfo,colormap('gray');
end
c(1)=c(1)+m(1);
ro(1)=ro(1)+n(1);
c(2)=c(2)+m(1)+0.50*size(J,2);
ro(2)=ro(2)+n(1);
% Display the resulting image.
figure;imshow(I,[],'initialMagnification','fit');impixelinfo;hold on;
plot(c(1),ro(1),'r*');
plot(c(2),ro(2),'r*');
c(1),ro(1)
c(2),ro(2)
hold off;
end

Contact us at files@mathworks.com