%% Problem statement: In exam key image, 
% try to tell green text
% from black text

%% What's Machine Learning?
% Just automating this process
% Supervised Machine Learning
%  - Neural Nets (Deep learning)
%  - SVM (Support Vector Machines)
%  - AdaBoost (face detection)
% Learn the output from provided input-output pairs
%
% There are other forms of machine learning
% Unsupervised learning
%  - clustering
% Semi-supervised learning
%  - only some data has labels
% Reinforcement Learning
%  - Instead of giving proper outputs, we have "rewards" for
%    better outputs -- algorithm seeks outputs
%    that maximize rewards

%% Load image and select green and black text
% and plot in RGB space

% Load image
I = imread('ExamKey.jpg');

% select green text
% imshow(I)
% shg
% % (zoom in)
% p = ginput
p = [615        1085];
jrange = p(1)-10:p(1)+10;
irange = p(2)-10:p(2)+10;

% Plot color values of green text window
% in RGB space
Ismall = I(irange,jrange,:);
red = Ismall(:,:,1);
green = Ismall(:,:,2);
blue = Ismall(:,:,3);
red = red(:);
green = green(:);
blue = blue(:);

% select black text and plot in RGB
% imshow(I)
% shg
% % zoom in
% ginput
% blackPoint = ans;
% blackPoint = round(blackPoint)
blackPoint = [337   947];
blackJRange = blackPoint(1)+(-10:10);
blackIRange = blackPoint(2)+(-10:10);
Iblack = I(blackIRange,blackJRange,:);
% Plot color values of black text image
redBlack = Iblack(:,:,1);
greenBlack = Iblack(:,:,2);
blueBlack = Iblack(:,:,3);
redBlack = redBlack(:);
greenBlack = greenBlack(:);
blueBlack = blueBlack(:);

% Plot the two samples together
clf
plot3(red,green,blue,'g.');
hold on
plot3(redBlack,greenBlack,blueBlack,'k.');
hold off
shg
xlabel('red');\
ylabel('green');
zlabel('blue')

%% Look at our classifier in 3 dimensions
[rr,gg,bb] = meshgrid(0:255,0:255,0:255);
maskVolume = gg > rr + 25;
clf
isosurface(rr,gg,bb,maskVolume,0.5);
hold on
plot3(red,green,blue,'g.');
plot3(redBlack,greenBlack,blueBlack,'k.');
hold off
shg
xlabel('red');
ylabel('green');
zlabel('blue')

%% Machine learning
% Reshape data into form needed by machine learning algorithm
doc fit data with a neural network
% Look before the GUI stuff
inputs = double([red',redBlack';green',greenBlack';blue',blueBlack']);
targets = [ones(size(red')),zeros(size(redBlack'))];
%% Train the network
% Look after the GUI stuff
hiddenLayerSize = 3;
net = fitnet(hiddenLayerSize);
net.divideParam.trainRatio = 70/100;
net.divideParam.valRatio = 15/100;
net.divideParam.testRatio = 15/100;
[net,tr] = train(net,inputs,targets);

%% Test network on training set
outputs = net(inputs);
errors = gsubtract(outputs,targets);
performance = perform(net,targets,outputs);
disp(['Performance: ' num2str(performance)])
view(net)
%% Plot targets vs. outputs
% outputs are real-valued, rather than just 0 or 1
plot(targets,outputs,'r.')
shg
%% Apply Neural Net to whole image
redWhole = I(:,:,1);
redWhole = redWhole(:)';
greenWhole = I(:,:,2);
greenWhole = greenWhole(:)';
blueWhole = I(:,:,3);
blueWhole = blueWhole(:)';
inputsWhole = [redWhole;greenWhole;blueWhole];
outputsWhole = net(inputsWhole);
squareOutputs = reshape(outputsWhole,size(I,1),size(I,2));
imshow(squareOutputs)
shg
%% Threshold whole image
threshold = .9;
imshow(squareOutputs > threshold)
shg
%% Compute NN output on all possible pixel values
% meshgrid is like ndgrid, but it swaps x and y, sort of.
[rr,gg,bb] = meshgrid(0:255,0:255,0:255);

% TODO compute outputsRgbVolume

isosurface(rr,gg,bb,outputsRgbVolume,threshold);
xlabel('red');
ylabel('green');
zlabel('blue')
shg
%% Plot green and black points as well.
hold on
plot3(red,green,blue,'g.');
plot3(redBlack,greenBlack,blueBlack,'k.');
hold off
shg