% This main function is related to Face Recognition with occlusion (no partitioning) by
% using GSRC of our paper in ECCV 2010. 
% note:
% TrainDAT.mat  ----      the training data of AR disguise set or Extended yaleb
%               ----      tr_dat: 3d Training data matrix, each tr_dat(:,:,i) is an (downsampled) 
%                            image matrix.
%               ----      tr_lab: a row vector, each element is the label of each training sample
%               ----      im_w  : the width of image
%               ----      im_h  : the height of image
%
% TestDAT.mat   ----      the testing data of AR disguise set or Extended yaleb
%               ----      tt_dat: 3d Training data matrix, each tr_dat(:,:,i) is an (downsampled) 
%                            image matrix.
%               ----      tt_lab: a row vector, each element is the label
%               of each training sample
%
% Copyright. Mike Yang, PolyU, Hong Kong.
% reference:
% M. Yang and L. Zhang.  Gabor feature based sparse representation
% for face recognition with Gabor occlusion dictionary. In ECCV 2010.
% S.J. Kim, K. Koh, M. Lustig, S. Boyd, and D. Gorinevsky. A method
% for large-scale l1-regularized least squares. IEEE Journal on Selected Topics in Signal Processing, 1(4):606¨C617, 2007.

clear all
clc

path   =     cd;
addpath([path '\utilities']);

load TrainDAT.mat;
load TestDAT.mat;

tr_ipts.dat    =    tr_dat;
tt_ipts.dat    =    tt_dat;

setpara_occlu;  % the parameter seting

% create Gabor feature if you don't have
% [tr_opts]      =    Create_GaborF (tr_ipts, par);
% tr_gdat        =    tr_opts.gdat;
% tr_gdat        =    tr_gdat./ repmat(sqrt(sum(tr_gdat.*tr_gdat)),[size(tr_gdat,1) 1]); % unit norm 2
% save('GaborTrain','tr_gdat'); clear tr_opts
% [tt_opts]      =    Create_GaborF (tt_ipts, par);
% tt_gdat        =    tt_opts.gdat;
% tt_gdat        =    tt_gdat./ repmat(sqrt(sum(tt_gdat.*tt_gdat)),[size(tt_gdat,1) 1]); % unit norm 2
% save('GaborTest','tt_gdat');   clear tt_opts

% load Gabor feature if you have had
load GaborTrain;
load GaborTest;

% you'd better create the gabor feature of occlusion matrix before using
% the functin 'main_learn_occlusion' alone, because the original occlusion
% matrix is very big. After runing the fuction 'main_learn_occlusion', you
% can load the data.

load('Occlu_Lear_Dict');

classids       =    unique(tr_lab);
NumClass       =    length(classids);
tt_num         =    size(tt_dat,3);
tt_ID          =    [];
    
for i  =  1: tt_num
    
    [s,status] = l1_ls([tr_gdat D_Oclu], tt_gdat(:,i), par.lambda_t); % l1_ls toolbox
    gap        = zeros(1,NumClass);
    
    for j   =  1:NumClass
        temp_s        =   zeros(size(tr_gdat,2),1);
        temp_s(find(j==tr_lab))   =   s(find(j==tr_lab));
        add_coef      =   s(size(tr_gdat,2)+1:end,1);
        zz            =    tt_gdat(:,i)-tr_gdat *temp_s-D_Oclu*add_coef;
        gap(j)        =  zz(:)'*zz(:); 
    end
    
    index   =  find(gap==min(gap));
    tt_ID   =  [tt_ID classids(index(1))];
end

reco_ratio  =  (sum(tt_ID==tt_lab))/length(tt_lab); %output the recognition rate
