clear;
close all;
%% mex-C compilation
mex CgetMAX1.c;
mex CgetMAX1_DoG.c;
mex sparseFeatureExtraction.c;
mex MatchingPursuit.c;
mex grad_U_sparse.c;
mex sparseFRAME_SUM2_logZ.c;
mex CgetMAX1_trace.c;
mex filterTiling.c;

mex mexc_ComputeMAX2MP.cpp
mex mexc_TemplateAffineTransform.cpp
mex mexc_CropInstance_FRAME.cpp

para=parametersList()

if (exist('./output','dir'))%experimental results
    delete('./output/*.*'); 
else
    mkdir('output');
end

seed = 1;
rng(seed); % set the seed so that experiments are reproducible

imgPath = '../dataset/scene_categories/';

categoryNames = {'bedroom','CALsuburb','industrial','kitchen',....
               'livingroom','MITcoast','MITforest','MIThighway',....
                'MITinsidecity','MITmountain','MITopencountry','MITstreet',...
                'MITtallbuilding','PARoffice','store'};

numClass = length(categoryNames);
sy = 200;
[trainImgs, testImgs, trainLabels,testLabels]=splitData(imgPath,categoryNames, numClass, sy);

codeBook = [];

for iClass = 1:numClass
    
        idx = find(trainLabels==iClass);
        
        savingFolder=['./Class' num2str(iClass) '/'];
        if exist(savingFolder)
            rmdir(savingFolder,'s'); 
            mkdir(savingFolder);
        else
            mkdir(savingFolder);
        end
            
        codeWords =LearnDictionary(trainImgs(idx), savingFolder, para);
        
        save(sprintf('./output/codeWork%d.mat',iClass),'codeWords');
        
        codeBook = [codeBook;codeWords];

end

save(sprintf('./output/AllcodeBook.mat'),'codeBook');
% extract features for training and testing images
disp(['Extracting features for training images:']);
trainFeatures = BatchExtractFeatures(trainImgs,codeBook,para);
    
disp(['Extracting features for testing images:']);
testFeatures = BatchExtractFeatures(testImgs,codeBook,para);

% train the model using muli-class svm
addpath('./liblinear/matlab');
    %{ 
Details of liblinar options
    -s type : set type of solver (default 1)
      for multi-class classification
             0 -- L2-regularized logistic regression (primal)
             1 -- L2-regularized L2-loss support vector classification (dual)
             2 -- L2-regularized L2-loss support vector classification (primal)
             3 -- L2-regularized L1-loss support vector classification (dual)
             4 -- support vector classification by Crammer and Singer
             5 -- L1-regularized L2-loss support vector classification
             6 -- L1-regularized logistic regression
             7 -- L2-regularized logistic regression (dual)
      for regression
            11 -- L2-regularized L2-loss support vector regression (primal)
            12 -- L2-regularized L2-loss support vector regression (dual)
            13 -- L2-regularized L1-loss support vector regression (dual)
    -c cost : set the parameter C (default 1)
    -p epsilon : set the epsilon in loss function of epsilon-SVR (default 0.1)
    -e epsilon : set tolerance of termination criterion
            -s 0 and 2
                    |f'(w)|_2 <= eps*min(pos,neg)/l*|f'(w0)|_2,
                    where f is the primal function and pos/neg are # of
                    positive/negative data (default 0.01)
            -s 11
                    |f'(w)|_2 <= eps*|f'(w0)|_2 (default 0.001) 
            -s 1, 3, 4 and 7
                    Dual maximal violation <= eps; similar to libsvm (default 0.1)
            -s 5 and 6
                    |f'(w)|_inf <= eps*min(pos,neg)/l*|f'(w0)|_inf,
                    where f is the primal function (default 0.01)
            -s 12 and 13\n"
                    |f'(alpha)|_1 <= eps |f'(alpha0)|,
                    where f is the dual function (default 0.1)
    -B bias : if bias >= 0, instance x becomes [x; bias]; if < 0, no bias term added (default -1)
    -wi weight: weights adjust the parameter C of different classes (see README for details)
    -v n: n-fold cross validation mode
    -q : quiet mode (no outputs)
%}
libLinearOptions = ['-s 4 -c 10 -B 0 -q'];
model = train(trainLabels,sparse(trainFeatures),libLinearOptions);

% test the model, and get confusion matrix
[testLabelsHat, acc]= predict(testLabels,sparse(testFeatures),model);
save('accuracy.mat','acc');
T = zeros(max(testLabels),length(testLabels));
Y = T;
for iSample = 1:length(testLabels)
        T(testLabels(iSample),iSample)=1;
        Y(testLabelsHat(iSample),iSample)=1;
end
[~,confMat,~,~] =confusion(T,Y);
datestr(clock)
    
%end
