% Demo, scene recognition
%
% This script trains a SVM for classification.
%
% You can use any SVM code. 
%
% Here, the code assumes you have installed the next toolbox:
% Support Vector Machine toolbox
% Version 2.51, January 2002
% available at: http://ida.first.fraunhofer.de/~anton/software.html

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Parameters
HOMEIMAGES = 'yourPathHere\spatial_envelope_256x256_static_8outdoorcategories'
categories = {'tallbuilding','insidecity','street','highway','coast','opencountry','mountain','forest'};
imageSize = 256; 
orientationsPerScale = [8 8 8 8];
numberBlocks = 4;
fc_prefilt = 4;
NtrainingPerClass = 100;

Nclasses = length(categories);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Compute global features
scenes = dir(fullfile(HOMEIMAGES, '*.jpg'));
scenes = {scenes(:).name};
Nscenes = length(scenes);

% Precompute filter transfert functions (only need to do this once, unless
% image size is changes):
G = createGabor(orientationsPerScale, imageSize);
Nfeatures = size(G,3)*numberBlocks^2;

% Loop: Compute global features for all scenes
F = zeros([Nscenes Nfeatures]);
C = zeros([Nscenes 1]);
for n = 1:Nscenes
    disp([n Nscenes])
    img = imread(fullfile(HOMEIMAGES, scenes{n}));
    img = mean(img,3);
    if size(img,1) ~= imageSize
        img = imresize(img, [imageSize imageSize], 'bilinear');
    end
    
    output = prefilt(img, fc_prefilt);
    g = gistGabor(output, numberBlocks, G);
    
    F(n,:) = g;
    C(n) = strmatch(scenes{n}(1), categories);
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Split training/test (train = index training samples, test = index test)
train = [];
for c = 1:Nclasses
    j = find(C==c);
    t = randperm(length(j));
    train = [train; j(t(1:NtrainingPerClass))];
end
test = setdiff(1:Nscenes, train)';

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Train SVM
% train one versus all and then take maximal score

fig = figure;
for c = 1:Nclasses
    netc = svm(Nfeatures, 'rbf', 0.003, 100);
    netc = svmtrain(netc, F(train,:), 2*(C(train)==c)-1, [], 1);

    [Y, scores(c,:)] = svmfwd(netc, F(test,:));
    
    figure(fig)
    clf
    plot(Y==1,'.')
    hold on
    plot(C(test)==c);
    title(100*sum((C(test)==c).*(Y==1))/sum(C(test)==c));
    xlabel(c)
    drawnow
end
for k = 1:length(test)
    [foo, ctest_hat(k)] = max(scores(:,k));
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Plot performance
% Confusion matrix:
Nclasses = length(categories);
Cm = zeros(Nclasses, Nclasses);
for j = 1:Nclasses
    for i = 1:Nclasses
        % row i, col j is the percentage of images from class i that
        % were missclassified as class j.
        Cm(i,j) = 100*sum((C(test)==i) .* (ctest_hat'==j))/sum(C(test)==i);
    end
end

figure
subplot(121)
imagesc(Cm); axis('square'); colorbar
subplot(122)
bar(diag(Cm))
title(mean(diag(Cm)))
axis('square')
