%% Simulovana data - chodce
% Program (nahodne) vytvari video o zadanych parametrech, ktere obsahuje
% nizkohodnostni slozku, ridkou slozku, a muze byt zatizeno bilym sumem.

%% Inicializace
clear
clc

frameSize = 128; % Vyska a sirka videa
frameCount = 90; % Pocet snimku

Video = zeros(frameSize*frameSize, frameCount); % Snimek = sloupec

Background = zeros(size(Video));
Foreground = zeros(size(Video));
Noise = zeros(size(Video));

%% Pozadi
vertLineCount = 2;  % Pocet rozmezi barev pozadi v horizontalnim/vertikalnim smeru
horLineCount = 2;

frameBG = ones(frameSize, frameSize) * 0.5; % Sede pozadi

% Vysledkem nasledujiciho cyklu je nalezeni polohy rozmezi (v horizontalnim
% smeru), zmena barvy na jedne strane od rozmezi o hodnotu color1, 
% na jine - o hodnotu color2.
for i = 1:vertLineCount
    linePos = round(frameSize*0.125 + (rand(1) * frameSize*0.75));
    color1 = randcolor1;
    color2 = randcolor1;
    for j = 1 : linePos
        frameBG(:,j) = frameBG(:,j) + color1;
    end
    for j = linePos+1 : frameSize
        frameBG(:,j) = frameBG(:,j) + color2;
    end
end

% Analogicky pro vertikalni smer.
for i = 1:horLineCount
    linePos = round(frameSize*0.125 + (rand(1) * frameSize*0.75));
    color1 = randcolor1;
    color2 = randcolor1;
    for j = 1 : linePos
        frameBG(j,:) = frameBG(j,:) + color1;
    end
    for j = linePos+1 : frameSize
        frameBG(j,:) = frameBG(j,:) + color2;
    end
end

% Vytvoreni videa z obrazku pozadi
for i = 1:frameCount
    Background(:,i) = frameBG(:);
    Video(:,i) = Video(:,i) + frameBG(:);
end

%% Popredi
vertPedCount = 8; % Pocet chodcu, pohybujicich se ve vertikalnim/horizontalnim smeru.
horPedCount = 6;

% Nasleducici blok vygeneruje potrebny pocet vertikalnich chodcu a jejich 
% potrebnych vlastnosti (velikost, pocatecni poloha, rychlost apod.) a
% ulozi do matice.
vertPeds = zeros(vertPedCount,8);
for i = 1:vertPedCount
    pedCord = round( frameSize * (rand(1,2).*[1, 0.7] + [0, 0.15]) ); % Poloha
    pedSize = ceil(rand(1)*5 + 2); % Velikost
    pedDir = (double(rand(1)<0.5) * 2) - 1; % Smer pohybu (-1 nebo 1)
    pedColor = randcolor2; % Barva
    pedSpeed = ceil(rand(1)*2); % Rychlost
    vertPeds(i,:) = [pedCord(1), pedCord(1)+pedSize, pedCord(2), pedCord(2)+pedSize, pedDir, pedColor, pedSize, pedSpeed];
end

% Analogicky pro horizontalni chodce
horPeds = zeros(horPedCount,8);
for i = 1:horPedCount
    pedCord = round( frameSize * (rand(1,2).*[0.7, 1] + [0.15, 0]) );
    pedSize = ceil(rand(1)*5 + 2);
    pedDir = (double(rand(1)<0.5) * 2) - 1;
    pedColor = randcolor2;
    pedSpeed = ceil(rand(1)*2);
    horPeds(i,:) = [pedCord(1), pedCord(1)+pedSize, pedCord(2), pedCord(2)+pedSize, pedDir, pedColor, pedSize, pedSpeed];
end

% Nasleduci cyklus vypocita novou polohu chodcu v zavislosti na jejich
% aktualnich polohach, rychlosti apod. a vytvori obrazek popredi. Dany 
% obrazek nahradi odpovidajici pixely na pozadi, cimz se vytvori spojeni
% pozadi a popredi.
for i = 1:frameCount
    frameFG = zeros(frameSize, frameSize);
    
    % Vypocet polohy vertikalnich chodcu
    for j = 1:vertPedCount
        vertPeds(j,1) = vertPeds(j,1) + vertPeds(j,8) * vertPeds(j,5); % nova poloha
        vertPeds(j,2) = vertPeds(j,2) + vertPeds(j,8) * vertPeds(j,5);
        if vertPeds(j,5) > 0 % kontrola, zda je chodec stale v zaberu (pohybuje se dolu)
            if vertPeds(j,2) >= frameSize % pokud prekrocil - vratit chodce nahoru
                vertPeds(j,1) = 1; vertPeds(j,2) = 1 + vertPeds(j,7);
            end  
        else % analogicky pro opacny smer pohybu
            if vertPeds(j,1) <= 1
                vertPeds(j,1) = frameSize - vertPeds(j,7); vertPeds(j,2) = frameSize;
            end   
        end
    end
    
    % Analogicky pro horizontalni chodce
    for j = 1:horPedCount
        horPeds(j,3) = horPeds(j,3) + horPeds(j,8) * horPeds(j,5);
        horPeds(j,4) = horPeds(j,4) + horPeds(j,8) * horPeds(j,5);
        if horPeds(j,5) > 0
            if horPeds(j,4) >= frameSize
                horPeds(j,3) = 1; horPeds(j,4) = 1 + horPeds(j,7);
            end  
        else
            if horPeds(j,3) <= 1
                horPeds(j,3) = frameSize - horPeds(j,7); horPeds(j,4) = frameSize;
            end   
        end
    end
    
    % Prideleni odpovidajici barvy pixelum snimku, jez odpovidaji aktualni poloze chodce. 
    for j = 1:vertPedCount
        frameFG( [vertPeds(j,1):vertPeds(j,2)], [vertPeds(j,3):vertPeds(j,4)] ) = vertPeds(j,6);
    end
    for j = 1:horPedCount
        frameFG( [horPeds(j,1):horPeds(j,2)], [horPeds(j,3):horPeds(j,4)] ) = horPeds(j,6);
    end
    
    % Override barvy pixelu pozadi na barvu chodce, ulozeni snimku do videa
    ind = find(frameFG(:) ~= 0);
    Foreground(ind,i) = frameFG(ind);
    Video(ind,i) = frameFG(ind);
end

%% Sum
% Generovani matice bileho sumu N s danou hodnotou rozptylu var(N)
Variance = 1e-4;

for i = 1:frameCount
    frameNoise = sqrt(Variance)*randn(frameSize, frameSize);
    Noise(:,i) = frameNoise(:);
end

%% Zasumene video
VideoNoise = Video + Noise;


%% Ulozeni
% AVI
makeVideoFromColumn( Background*255, 'pedestrian_video\pedestrian_BG.avi' , frameSize, frameSize )
makeVideoFromColumn( Foreground*255, 'pedestrian_video\pedestrian_FG.avi' , frameSize, frameSize )
makeVideoFromColumn( Noise*255, 'pedestrian_video\pedestrian_N.avi' , frameSize, frameSize )
makeVideoFromColumn( Video*255, 'pedestrian_video\pedestrian.avi' , frameSize, frameSize );
makeVideoFromColumn( VideoNoise*255, 'pedestrian_video\pedestrian_noisy.avi' , frameSize, frameSize );

% MAT
video = struct;
video.arrays = struct;
video.parameters = struct;

video.arrays.A = Video;             % Video bez sumu
video.arrays.A_noise = VideoNoise;  % -//- se sumem
video.arrays.L = Background;        % Pouze pozadi
video.arrays.S = Foreground;        % Pouze popredi
video.arrays.N = Noise;             % Pouze sum
    
video.parameters.width = frameSize;
video.parameters.height = frameSize;
video.parameters.frames = frameCount;
    
save(['pedestrian_video\pedestrian.mat'], 'video');

%% Funkce
function result = randcolor1
% nahodna hodnota z intervalu (-0.125, 0.125) pro generaci pozadi
result = (rand(1)-0.5)*0.25;
end

function result = randcolor2
% nahodna hodnota z intervalu (0, 0.25) nebo (0.75, 1) pro generaci chodcu
result = rand(1);
    while result >= 0.25 && result <= 0.75
        result = rand(1);
    end
end