% Introduction to matCNN
% necessary steps to use the simulator:
% 1) download and unpack it,
%   - if you have Win/linux: http://users.itk.ppke.hu/~horan/CNN/matCNN.zip
%   - if you have OS X: http://users.itk.ppke.hu/~horan/CNN/os_x_matcnn.zip
% 2) download and save temlib_plus from the gyak4.zip package to the root
%    folder of your matCNN directory
% 3) on the main ribbon, inside Home tab: Set Path
%   - in the pop-up select 'Add with Subfolders...'
%   - select your unpacked matcnn folder
%   - Save, then Close
%   - comments to the lab-machines: you won't have writing permission on the lab machine, so
%     you should say 'No' to the root authentication, then save elsewhere
%     your pathdef.m file (eg. in your Documents folder or in the MATLAB
%     dir inside it).
% 4) the ultimate template-catalog, called Software Library:
%    http://cnn-technology.itk.ppke.hu/ eg v3.1 fits most of our needs


% as a good routine at the beginning of every script:
%close all;
%clear all;

% set the CNN environment:
cnn_setenv;
% this will create the mCNN structure in your Workspace, you can check out
% the different fields of it

% set the template library file: 
mCNN.TemGroup = 'temlib_plus';
% this is an extended text-file containing the definitions of A and B 
% templates (and the bias 'z' of course, which is called 'I' in this 
% environment. you can find this file in the root of the matCNN directory 
% you have unpacked. later on we will use an other template definition 
% file, called 'temlib_plus': this can not be found in the matCNN folder, 
% we will attach it to the labratory initial code


% in the followings there will be more examples, each of them in separate
% block comment. the biginning of block comment: '%{' and the end: '%}'.
% these should be written in separate line, you can deactivate them either
% with plus percentage-sign in the first place (like '%%{' and '%%}'), or
% simply just deleting it.


%{
% example 1: gradient - marks the regions/places which have high gradient in
% the local neighborhood
load('madonna.mat');
img = TESTPIC;
%in_pic = lbmp2cnn('piclib/BABOON.bmp');
mCNN.INPUT1 = 1.* img; %in_pic; % multiplying elementwise with the number one 
% will force the system to allocate new memory-space to the copied variable
%init_state = lbmp2cnn('piclib/BABOON.bmp');
mCNN.STATE = 1.* img; %init_state;
mCNN.Boundary = 2; % [-1 ... 1] --> const, 2 --> zeroflux, 3 --> periodic
mCNN.TimeStep = 0.1;
mCNN.IterNum = 20;
loadtem('GRADT'); % loads the template-values from the previously given
% textual library file ('temlib') to the simulator
runtem; % run the simulator

% and plot the results:
figure;
subplot(1, 3, 1);
cnnshow(img); %in_pic);
title('input', 'FontSize', 12, 'FontWeight', 'bold');
subplot(1, 3, 2);
cnnshow(img); %init_state);
title('initial state', 'FontSize', 12, 'FontWeight', 'bold');
subplot(1, 3, 3);
cnnshow(mCNN.OUTPUT);
title('output', 'FontSize', 12, 'FontWeight', 'bold');
%}

%{
% example 2: diffusion - cleaning the high spatial frequencies; compression
% Template Library v3.1 p27
init_state = lbmp2cnn('piclib/BABOON.bmp');
mCNN.STATE = 1.* init_state;
in_pic = zeros(size(init_state)); % there is no template B, it is autonomous
mCNN.INPUT1 = 1.* in_pic;
mCNN.Boundary = 2; % const. 0 in the literature
mCNN.TimeStep = 0.1;
mCNN.IterNum = 10; % try different number of iterations: 10, 100, 1000
loadtem('DIFFUS');
runtem;

figure;
subplot(1, 3, 1);
cnnshow(in_pic);
title('input', 'FontSize', 12, 'FontWeight', 'bold');
subplot(1, 3, 2);
cnnshow(init_state);
title('initial state', 'FontSize', 12, 'FontWeight', 'bold');
subplot(1, 3, 3);
cnnshow(mCNN.OUTPUT);
title('output', 'FontSize', 12, 'FontWeight', 'bold');
%}





%{
% example 3: anisotropic diffusion -- not isotrope, not homogenous
% similar to gradient controlled diffusion (Template Lib v3.1 p146), but in
% only one non-linear template
% the edges and contrast-full parts are preserved, while similar regions /
% parts are diffused; key-application: compression, object-identification
init_state = lbmp2cnn('piclib/BABOON.bmp');
mCNN.STATE = 1.* init_state;
in_pic = zeros(size(init_state)); % there is no template B, it is autonomous
mCNN.INPUT1 = 1.* in_pic;
mCNN.Boundary = 2;
mCNN.TimeStep = 0.1;
mCNN.IterNum = 10; % try different number of iterations: 10, 30, 100
loadtem('ANISO');
runtem;

figure;
subplot(1, 3, 1);
cnnshow(in_pic);
title('input', 'FontSize', 12, 'FontWeight', 'bold');
subplot(1, 3, 2);
cnnshow(init_state);
title('initial state', 'FontSize', 12, 'FontWeight', 'bold');
subplot(1, 3, 3);
cnnshow(mCNN.OUTPUT);
title('output', 'FontSize', 12, 'FontWeight', 'bold');
%}





%{
% example 4: local maxima finder -- 'interesting' regions in binary
% TempLib v3.1 p52 - nonlinear template
in_pic = lbmp2cnn('piclib/avergra1.bmp');
mCNN.INPUT1 = 1.* in_pic;
init_state = zeros(size(in_pic));
mCNN.STATE = 1.* init_state;
mCNN.Boundary = 2;
mCNN.TimeStep = 0.1;
mCNN.IterNum = 50;
loadtem('LOCMAX');
runtem;

figure;
subplot(1, 3, 1);
cnnshow(in_pic);
title('input', 'FontSize', 12, 'FontWeight', 'bold');
subplot(1, 3, 2);
cnnshow(init_state);
title('initial state', 'FontSize', 12, 'FontWeight', 'bold');
subplot(1, 3, 3);
cnnshow(mCNN.OUTPUT);
title('output', 'FontSize', 12, 'FontWeight', 'bold');
%}





%{
% example 5: median filter -- to filter out impulse-like noises, like salt&pepper
% TempLib v3.1 p53 & p287 - nonlinear template
% in this simulator, technically it needs the input image at both of its
% input terminals
load('A_LETTER.mat');
in_pic = TESTPIC;
%in_pic = lbmp2cnn('piclib/MEDIAN.bmp');
mCNN.INPUT1 = 1.* in_pic;
mCNN.INPUT2 = 1.* in_pic;
init_state = ones(size(in_pic)); % although it does have template A, it can be arbitrary
mCNN.STATE = 1.* init_state;
mCNN.Boundary = 0;
mCNN.TimeStep = 0.1;
mCNN.IterNum = 100;
loadtem('SHADOWD');
runtem;

figure;
subplot(1, 3, 1);
cnnshow(in_pic);
title('input', 'FontSize', 12, 'FontWeight', 'bold');
subplot(1, 3, 2);
cnnshow(init_state);
title('initial state', 'FontSize', 12, 'FontWeight', 'bold');
subplot(1, 3, 3);
cnnshow(mCNN.OUTPUT);
title('output', 'FontSize', 12, 'FontWeight', 'bold');
%}





%{
% example 6: threshold -- from grayscale to binary; applying twice with
% different thresholds --> a bandpass filter can be constructed
% TempLib v3.1 p61
% with the bias we can define the 'threshold' itself -- but we have to
% apply the desired value with opposite sign. (Later, during
% template-design we will speak about the reason.)
load('madonna.mat');
init_state = TESTPIC;
%init_state = lbmp2cnn('piclib/avergra2.bmp');
mCNN.STATE = 1.* init_state;
in_pic = ones(size(init_state)).*-1; % there is no template B here
mCNN.INPUT1 = 1.* in_pic;
mCNN.Boundary = 3;
mCNN.TimeStep = 0.1;
mCNN.IterNum = 50;
loadtem('THRES');
mCNN.I = -0.7; % after loading the default thres-values, we can fine-tune
% the bias value to define the 'threshold' itself
runtem;
out1 = 1.* mCNN.OUTPUT;

mCNN.STATE = 1.* init_state;
mCNN.INPUT1 = 1.* in_pic;
mCNN.Boundary = 2;
mCNN.TimeStep = 0.1;
mCNN.IterNum = 50;
loadtem('THRES');
mCNN.I = +0.7;
runtem;
out2 = 1.* mCNN.OUTPUT;

figure;
subplot(2, 2, 1);
cnnshow(in_pic);
title('input', 'FontSize', 12, 'FontWeight', 'bold');
subplot(2, 2, 2);
cnnshow(init_state);
title('initial state', 'FontSize', 12, 'FontWeight', 'bold');
subplot(2, 2, 3);
cnnshow(out1);
title('output 1 -- with threshold=+0.7', 'FontSize', 12, 'FontWeight', 'bold');
subplot(2, 2, 4);
cnnshow(out2);
title('output 2 -- with threshold=-0.7', 'FontSize', 12, 'FontWeight', 'bold');
%}





%{
% example 6b: threshold as timelapse
init_state = lbmp2cnn('piclib/avergra2.bmp');
mCNN.STATE = 1.* init_state;
in_pic = zeros(size(init_state));
mCNN.INPUT1 = 1.* in_pic;
mCNN.Boundary = 2;
mCNN.TimeStep = 0.1;
mCNN.IterNum = 1;
loadtem('THRES');
mCNN.I = -0.4;
total_iternum = 40;
outs = zeros(size(init_state, 1), size(init_state, 2), total_iternum);
for idx = 1:total_iternum
    runtem;
    outs(:, :, idx) = 1.* mCNN.OUTPUT;
end

figure;
for idx = 1:total_iternum
    cnnshow(squeeze(outs(:, :, idx)));
    title(strcat('iternum: ', num2str(idx), '/', num2str(total_iternum)));
    pause(0.1);
end
%}





%{
% example 7: recall marked objects as timelapse
% extracts marked objects 
% TempLib v3.1 p35
init_state = lbmp2cnn('piclib/figrec.bmp'); % marked objects as initstate
mCNN.STATE = 1.* init_state;
in_pic = lbmp2cnn('piclib/figdel.bmp');% all of the orig. obj. as input
mCNN.INPUT1 = 1.* in_pic;
mCNN.Boundary = 2; % const. 0 in the literature
mCNN.TimeStep = 0.1;
mCNN.IterNum = 1;
loadtem('RECALL');
total_iternum = 60;
outs = zeros(size(init_state, 1), size(init_state, 2), total_iternum);
for idx = 1:total_iternum
    runtem;
    outs(:, :, idx) = 1.* mCNN.OUTPUT;
end

figure;
subplot(1, 3, 1);
cnnshow(in_pic);
title('input -- whole objects', 'FontSize', 12, 'FontWeight', 'bold');
subplot(1, 3, 2);
cnnshow(init_state);
title('initial state -- marked objects', 'FontSize', 12, 'FontWeight', 'bold');
for idx = 1:total_iternum
    subplot(1, 3, 3)
    cnnshow(squeeze(outs(:, :, idx)));
    title(strcat('output, iternum: ', num2str(idx), '/', num2str(total_iternum)), ...
        'FontSize', 12, 'FontWeight', 'bold');
    pause(0.5);
end
%}





%{
% example 8: edge detector -- like gradient, but in case of binary imgs
% TempLib v3.1 p28
in_pic = lbmp2cnn('piclib/HOLLOW.bmp');
mCNN.INPUT1 = 1.* in_pic;
init_state = zeros(size(in_pic)); % although it does have template A, it can be arbitrary
mCNN.STATE = 1.* init_state;
mCNN.Boundary = 2;
mCNN.TimeStep = 0.01;
mCNN.IterNum = 1;
loadtem('EDGE');
total_iternum = 80;
outs = zeros(size(init_state, 1), size(init_state, 2), total_iternum);
for idx = 1:total_iternum
    runtem;
    outs(:, :, idx) = 1.* mCNN.OUTPUT;
end
runtem;

figure;
subplot(1, 3, 1);
cnnshow(in_pic);
title('input', 'FontSize', 12, 'FontWeight', 'bold');
subplot(1, 3, 2);
cnnshow(init_state);
title('initial state', 'FontSize', 12, 'FontWeight', 'bold');
for idx = 1:total_iternum
    subplot(1, 3, 3)
    cnnshow(squeeze(outs(:, :, idx)));
    title(strcat('output, iternum: ', num2str(idx), '/', num2str(total_iternum)), ...
        'FontSize', 12, 'FontWeight', 'bold');
    pause(0.1);
end
%}





%{
% example 9: erosion -- peel one layer of object's outer surface
% TempLib v3.1 p62
in_pic = lbmp2cnn('piclib/Logic05.bmp');
mCNN.INPUT1 = 1.* in_pic;
init_state = zeros(size(in_pic)); % it does not have template A, the input
% just 'flows through' the system, without feedback-system ---
% that is the reason, why we have to 'reload' the system's input with a
% one-layer thinner image everytime we would like to peel multiple layers
mCNN.STATE = 1.* init_state;
mCNN.Boundary = 2;
mCNN.TimeStep = 1;
mCNN.IterNum = 1;
loadtem('EROSION');
total_iternum = 10;
outs = zeros(size(init_state, 1), size(init_state, 2), total_iternum);
for idx = 1:total_iternum
    runtem;
    outs(:, :, idx) = 1.* mCNN.OUTPUT;
    mCNN.INPUT1 = 1.* mCNN.OUTPUT;
end
runtem;

figure;
subplot(1, 3, 1);
cnnshow(in_pic);
title('input', 'FontSize', 12, 'FontWeight', 'bold');
subplot(1, 3, 2);
cnnshow(init_state);
title('initial state', 'FontSize', 12, 'FontWeight', 'bold');
for idx = 1:total_iternum
    subplot(1, 3, 3)
    cnnshow(squeeze(outs(:, :, idx)));
    title(strcat('output, iternum: ', num2str(idx), '/', num2str(total_iternum)), ...
        'FontSize', 12, 'FontWeight', 'bold');
    pause(1);
end

% how to make object 'thicker'? check out template DILATION

%}





%{
% example 10: logical difference -- binary subtraction: subtracts the input
% from the initial state
% TempLib v3.1 p82
% to remember: "result = init_state - input"
init_state = lbmp2cnn('piclib/figdel.bmp');
mCNN.STATE = 1.* init_state;
in_pic = lbmp2cnn('piclib/figrec.bmp');
mCNN.INPUT1 = 1.* in_pic;
mCNN.Boundary = 2;
mCNN.TimeStep = 0.1;
mCNN.IterNum = 20;
loadtem('LOGDIF');
runtem;

figure;
subplot(1, 3, 1);
cnnshow(in_pic);
title('input (U)', 'FontSize', 12, 'FontWeight', 'bold');
subplot(1, 3, 2);
cnnshow(init_state);
title('initial state (X(0))', 'FontSize', 12, 'FontWeight', 'bold');
subplot(1, 3, 3);
cnnshow(mCNN.OUTPUT);
title('output=X(0)-U', 'FontSize', 12, 'FontWeight', 'bold');
%}





%%{
% example 11: shadow left -- the output looks like you illuminate the image
% with a torch from right to left
% try 'shadow down' as well! (SHADOWD)
% TempLib v3.1 p58
load('A_LETTER.mat');
init_state = TESTPIC;
%in_pic = lbmp2cnn('piclib/A_LETTER.BMP');
in_pic = ones(size(init_state));
mCNN.INPUT1 = 1.* in_pic;
mCNN.STATE = 1.* init_state;
mCNN.Boundary = -1; % in contrast to the literature (const. 0), it works well with -1
mCNN.TimeStep = 0.1;
mCNN.IterNum = 10;
loadtem('SELECT');
total_iternum = max(size(in_pic)); % observe the transient: the necessary 
% number of iterations depends on the size of the image
outs = zeros(size(in_pic, 1), size(in_pic, 2), total_iternum);
for idx = 1:total_iternum
    runtem;
    outs(:, :, idx) = 1.* mCNN.OUTPUT;
    mCNN.STATE = 1.* mCNN.OUTPUT;
end
runtem;

figure;
subplot(1, 3, 1);
cnnshow(in_pic);
title('input', 'FontSize', 12, 'FontWeight', 'bold');
subplot(1, 3, 2);
cnnshow(init_state);
title('initial state', 'FontSize', 12, 'FontWeight', 'bold');
for idx = 1:total_iternum
    subplot(1, 3, 3)
    cnnshow(squeeze(outs(:, :, idx)));
    title(strcat('output, iternum: ', num2str(idx), '/', num2str(total_iternum)), ...
        'FontSize', 12, 'FontWeight', 'bold');
    pause(0.1);
end
%%}





%{
% example 12: hole filler -- fills the holes inside objects
% works similarly to the shadow templates
% TempLib v3.1 p44
in_pic = lbmp2cnn('piclib/A_LETTER.BMP');
mCNN.INPUT1 = 1.* in_pic;
init_state = ones(size(in_pic));
mCNN.STATE = 1.* init_state;
mCNN.Boundary = -1; % in contrast to the literature (const. 0), it works well with -1
mCNN.TimeStep = 1;
mCNN.IterNum = 1;
loadtem('HOLE');
total_iternum = floor(sqrt(sum(size(in_pic).^2))); % observe the transient: 
% the necessary number of iterations is in strong relation with the 
% diagonal size of the image
outs = zeros(size(init_state, 1), size(init_state, 2), total_iternum);
for idx = 1:total_iternum
    runtem;
    outs(:, :, idx) = 1.* mCNN.OUTPUT;
end
runtem;

figure;
subplot(1, 3, 1);
cnnshow(in_pic);
title('input', 'FontSize', 12, 'FontWeight', 'bold');
subplot(1, 3, 2);
cnnshow(init_state);
title('initial state', 'FontSize', 12, 'FontWeight', 'bold');
for idx = 1:total_iternum
    subplot(1, 3, 3)
    cnnshow(squeeze(outs(:, :, idx)));
    title(strcat('output, iternum: ', num2str(idx), '/', num2str(total_iternum)), ...
        'FontSize', 12, 'FontWeight', 'bold');
    pause(0.1);
end
%}



