%% METODA FQR - AUTOR: Daria Bashkatova

%% TENTO M-FILE SLOUŽÍ K POUŽÍVÁNÍ VÝPOČTU BEZ UŽIVATELSKÉHO PROSTŘEDÍ

clear all; clc;
%% PROMĚNNÉ
endframe = 0; % zadej poslední načtený frame ( <= 0 - všechny ve videu, jiné číslo = výběr uživatelem)
startframe = 1; % zadej počáteční frame (výběr uživatelem)
kolik = 30; % zadej, kolikátý každý frame se má hodnotit (zrychlení výpočtu)
ref_file = 'E:\škola\bakalářka\Testovaná videa\marie-544-1a\marie-544-1a.avi'; %referenční video
de_file = 'E:\škola\bakalářka\Testovaná videa\marie-544-1a\544_80_1-0_1a_mar.mp4'; %degradovane video
obr_matice='E:\škola\bakalářka\Testovaná videa\marie-544-1a\matice'; %slozka s maticema videa
vyber = 1; %zadej pro výběr metriky 0 == SSIM MATLAB, 1 == SSIM ORIGO

%% NACTENI VIDEA

ref_file = VideoReader(ref_file); %načtení referenční videosekvence funkcí videoreader
ref = read(ref_file); %nacteni referenční videosekvence do matice 4D

de_file = VideoReader(de_file); %načtení testované videosekvence funkcí videoreader
de = read(de_file); %nacteni referenční videosekvence do matice 4D

[Height Width Color nFrames] = size(de); %určení rozměrů 4D matice (VÝŠKA x ŠÍŘKA x BARVA x POČET SNÍMKŮ)
m=Height; % výška obrazu
n=Width; %šířka obrazu

%% ZAJISTENI PROTI CHYBAM

if startframe >= nFrames % zajištění proti chybám při chybném vstupu
   startframe = nFrames;
end

if startframe <= 0 % zajištění proti chybám při chybném vstupu
   startframe = 1;
end

if endframe >= nFrames || endframe <= 0 % zajištění proti chybám při chybném vstupu
   pomoc = nFrames;
   endframe = nFrames;
else
   pomoc = nFrames; % zajištění proti chybám při chybném vstupu
   nFrames=endframe;
end

if startframe >= endframe
   startframe = endframe;
end

if kolik <= 0 % zajištění proti chybám při chybném vstupu
   kolik = 1;
end

if kolik >= nFrames % zajištění proti chybám při chybném vstupu
   kolik = nFrames;
end

%% NACTENI MASEK (popis v m-filu kompletmaska.m)

[obr_ref1, obr_ref2, obr_ref3, obr_de1, obr_de2, obr_de3, framenorm, maska] = kompletmaska(Height, Width, nFrames, startframe, kolik, ref, de, obr_matice, pomoc);

%% ROI 1 (odstranění redundantní informace v každém POUŽITÉM snímku ROI1)
if vyber == 0 % VÝBĚR POČÍTANÉ METRIKY - SSIM MATLAB
    
parfor frame=1:framenorm %PARFOR cyklus - pro všechny HODNOCENÉ snímky
ymax=1; xmax=1; ymin=n; xmin=m;  %konstanty - nastavení pro výběr okna
for i=1:m %pro všechny pixely ve sloupci
    for ii=1:n %pro všechy pixely v řádku
        if obr_ref1(i,ii,1,frame)~=0; %pokud není daný pixel redundantní iformace = zapamatuj si jeho hodnotu
            if i>xmax
                xmax=i;
            end
            if ii>ymax
                ymax=ii;
            end
            if i<xmin
                xmin=i;
            end
            if ii<ymin
                ymin=ii;
            end
            X1{frame} = obr_ref1(xmin:xmax,ymin:ymax,:,frame); %vytvoření buněk - 1 bunka = nová ŠÍŘKA x nová VÝŠKA x BARVA
            Y1{frame} = obr_de1(xmin:xmax,ymin:ymax,:,frame); %počet buněk = počet HODNOCENYCH snímků
        end
    end
end
end

elseif vyber == 1 % VÝBĚR POČÍTANÉ METRIKY - SSIM ORIGO
    
parfor frame=1:framenorm % PARFOR cyklus - pro všechny HODNOCENÉ snímky
    X1{frame} = obr_ref1(:,:,:,frame); %vytvoření buněk - 1 bunka = ŠÍŘKA x VÝŠKA x BARVA
    Y1{frame} = obr_de1(:,:,:,frame); %počet buněk = počet HODNOCENYCH snímků
end

end

%% MSSIM 1 MATLAB výpočet pro ROI 1 (používá se SSIM origo)
if vyber == 0  % VÝBĚR POČÍTANÉ METRIKY - SSIM MATLAB
    
ssimval1M=NaN(framenorm,1); %připravení vektoru pro zápis hodnot
parfor i=1:framenorm %pro každý HODNOCENÝ  snímek
    [ssimvalM(i)] = ssimM(X1{i}(:,:,:),Y1{i}(:,:,:)); %SSIM index (viz ssimM.m)
    ssimval1M(i)=ssimvalM(i); %zapsat výsledek do připraveného vektoru
    ssimvalM(i)=NaN; %připravení pro nový výpočet
end

%% MSSIM 1 ORIGO výpočet pro ROI 1
elseif vyber == 1   % VÝBĚR POČÍTANÉ METRIKY - SSIM ORIGO

ssimval1O=NaN(framenorm,1); %připravení vektoru pro zápis hodnot
parfor i=1:framenorm %pro každý HODNOCENÝ  snímek
    XA{i}= 0.2126*X1{i}(:,:,1)+0.7152*X1{i}(:,:,2)+0.0722*X1{i}(:,:,3) % jasová rovnice - BARVA = JEDNA
    YA{i}= 0.2126*Y1{i}(:,:,1)+0.7152*Y1{i}(:,:,2)+0.0722*Y1{i}(:,:,3) % jasová rovnice - BARVA = JEDNA
    [ssimvalO(i)] = ssimO(XA{i}(:,:,:),YA{i}(:,:,:)); %SSIM index (viz ssimO.m)
    ssimval1O(i)=ssimvalO(i); %zapsat výsledek do připraveného vektoru
    ssimvalO(i)=NaN; %připravení pro nový výpočet
end

end

%% ROI 2 (odstranění redundantní informace v každém POUŽITÉM snímku ROI2)
if vyber == 0 % VÝBĚR POČÍTANÉ METRIKY - SSIM MATLAB
    
parfor frame=1:framenorm %PARFOR cyklus - pro všechny HODNOCENÉ snímky
ymax=1; xmax=1; ymin=n; xmin=m;  %konstanty - nastavení pro výběr okna
for i=1:m %pro všechny pixely ve sloupci
    for ii=1:n %pro všechy pixely v řádku
        if obr_ref2(i,ii,1,frame)~=0; %pokud není daný pixel redundantní iformace = zapamatuj si jeho hodnotu
            if i>xmax
                xmax=i;
            end
            if ii>ymax
                ymax=ii;
            end
            if i<xmin
                xmin=i;
            end
            if ii<ymin
                ymin=ii;
            end  
            X2{frame} = obr_ref2(xmin:xmax,ymin:ymax,:,frame); %vytvoření buněk - 1 bunka = nová ŠÍŘKA x nová VÝŠKA x BARVA
            Y2{frame} = obr_de2(xmin:xmax,ymin:ymax,:,frame); %počet buněk = počet HODNOCENYCH snímků
        end
    end
end
end

elseif vyber == 1 % VÝBĚR POČÍTANÉ METRIKY - SSIM ORIGO
    
parfor frame=1:framenorm % PARFOR cyklus - pro všechny HODNOCENÉ snímky
    X2{frame} = obr_ref2(:,:,:,frame); %vytvoření buněk - 1 bunka = ŠÍŘKA x VÝŠKA x BARVA
    Y2{frame} = obr_de2(:,:,:,frame); %počet buněk = počet HODNOCENYCH snímků
end

end

%% MSSIM 2 MATLAB výpočet pro ROI 2 (používá se SSIM origo)
if vyber == 0; % VÝBĚR POČÍTANÉ METRIKY - SSIM MATLAB
    
ssimval2M=NaN(framenorm,1); %připravení vektoru pro zápis hodnot 
parfor i=1:framenorm %pro každý HODNOCENÝ  snímek
       [ssimvalM(i)] = ssimM(X2{i}(:,:,:),Y2{i}(:,:,:));  %SSIM index (viz ssimM.m)
       ssimval2M(i)=ssimvalM(i); %zapsat výsledek do připraveného vektoru
       ssimvalM(i)=NaN; %připravení pro nový výpočet
end

%% MSSIM 2 ORIGO výpočet pro ROI 2
elseif vyber == 1 % VÝBĚR POČÍTANÉ METRIKY - SSIM ORIGO
    
ssimval20=NaN(framenorm,1); %připravení vektoru pro zápis hodnot 
parfor i=1:framenorm %pro každý HODNOCENÝ  snímek
       XB{i}= 0.2126*X2{i}(:,:,1)+0.7152*X2{i}(:,:,2)+0.0722*X2{i}(:,:,3) %jasová rovnice - BARVA = JEDNA
       YB{i}= 0.2126*Y2{i}(:,:,1)+0.7152*Y2{i}(:,:,2)+0.0722*Y2{i}(:,:,3) %jasová rovnice - BARVA = JEDNA
       [ssimvalO(i)] = ssimO(XB{i}(:,:,:),YB{i}(:,:,:)); %SSIM index (viz ssimO.m)
       ssimval2O(i)=ssimvalO(i); %zapsat výsledek do připraveného vektoru
       ssimvalO(i)=NaN; %připravení pro nový výpočet
end

end

%% ROI3 (u ROI3 nelze odstranit žádná redundantní informace)

parfor frame=1:framenorm % PARFOR cyklus - pro všechny HODNOCENÉ snímky
    X3{frame} = obr_ref3(:,:,:,frame); %vytvoření buněk - 1 bunka = ŠÍŘKA x VÝŠKA x BARVA
    Y3{frame} = obr_de3(:,:,:,frame); %počet buněk = počet HODNOCENYCH snímků
end

%% MSSIM 3 MATLAB výpočet pro ROI 3 (používá se SSIM origo)
if vyber == 0 % VÝBĚR POČÍTANÉ METRIKY - SSIM MATLAB
    
ssimval3M=NaN(framenorm,1); %připravení vektoru pro zápis hodnot 
parfor i=1:framenorm %pro každý HODNOCENÝ  snímek
    [ssimvalM(i)] = ssimM(X3{i}(:,:,:),Y3{i}(:,:,:)); %SSIM index (viz ssimM.m)
    ssimval3M(i)=ssimvalM(i); %zapsat výsledek do připraveného vektoru
    ssimvalM(i)=NaN; %připravení pro nový výpočet
end

%% MSSIM 3 ORIGO pro ROI3
elseif vyber == 1  % VÝBĚR POČÍTANÉ METRIKY - SSIM ORIGO

ssimval3O=NaN(framenorm,1); %připravení vektoru pro zápis hodnot 
parfor i=1:framenorm %pro každý HODNOCENÝ  snímek
    XC{i}= 0.2126*X3{i}(:,:,1)+0.7152*X3{i}(:,:,2)+0.0722*X3{i}(:,:,3) %jasová rovnice - BARVA = JEDNA
    YC{i}= 0.2126*Y3{i}(:,:,1)+0.7152*Y3{i}(:,:,2)+0.0722*Y3{i}(:,:,3) %jasová rovnice - BARVA = JEDNA
    [ssimvalO(i)] = ssimO(XC{i}(:,:,:),YC{i}(:,:,:)); %SSIM index (viz ssimO.m)
    ssimval3O(i)=ssimvalO(i); %zapsat výsledek do připraveného vektoru
    ssimvalO(i)=NaN; %připravení pro nový výpočet
end

end

%% NORMOVANI MSSIM hodnot

% 1. PROCENTA ZASTOUPENÍ (zaroven je provedeno otoceni osy v kazdem kroku)

size1 = cell2mat( cellfun(@(A) [size(A,1),size(A,2)], X1(:), 'Uniform', 0) ); %velikost bunek pro výpočet normované MSSIM1
size2 = cell2mat( cellfun(@(B) [size(B,1),size(B,2)], X2(:), 'Uniform', 0) ); %velikost bunek pro výpočet normované MSSIM2

for i=1:framenorm %pro každý HODNOCENÝ  snímek
percent1(i) = 1/(m*n)*((size1(i,1)))*(size1(i,2)); %procenta zastoupení MSSIM1 podle ROI1
percent2(i) = 1/(m*n)*((size2(i,1)))*(size2(i,2)); %procenta zastoupení MSSIM2 podle ROI2

if vyber == 0 % VÝBĚR POČÍTANÉ METRIKY - SSIM MATLAB
    MSSIM1sM(i) = (1-ssimval1M(i))*percent1(i); %Výpočet procentuálního zastoupení MATLAB ROI1
    MSSIM2sM(i) = (1-ssimval2M(i))*percent2(i); %Výpočet procentuálního zastoupení MATLAB ROI2
    MSSIM3sM(i) = (1-ssimval3M(i));             %Výpočet procentuálního zastoupení MATLAB ROI3
elseif vyber == 1 % VÝBĚR POČÍTANÉ METRIKY - SSIM ORIGO
    MSSIM1sO(i) = (1-ssimval1O(i))*percent1(i); %Výpočet procentuálního zastoupení ORIGO ROI1
    MSSIM2sO(i) = (1-ssimval2O(i))*percent2(i); %Výpočet procentuálního zastoupení ORIGO ROI2
    MSSIM3sO(i) = (1-ssimval3O(i));             %Výpočet procentuálního zastoupení ORIGO ROI3
end

end

% 2. JEDNOTNE MSSIM pro vsechny snimky (1 hodnota MSSIM pro jednu oblast ROI v celé videosekvenci)
if vyber == 0 % VÝBĚR POČÍTANÉ METRIKY - SSIM MATLAB
    MSSIM1M = nansum(MSSIM1sM/framenorm); %ROI1 MATLAB
    MSSIM2M = nansum(MSSIM2sM/framenorm); %ROI2 MATLAB
    MSSIM3M = nansum(MSSIM3sM/framenorm); %ROI3 MATLAB
elseif vyber == 1 % VÝBĚR POČÍTANÉ METRIKY - SSIM ORIGO
    MSSIM1O = nansum(MSSIM1sO/framenorm); %ROI1 ORIGO
    MSSIM2O = nansum(MSSIM2sO/framenorm); %ROI2 ORIGO
    MSSIM3O = nansum(MSSIM3sO/framenorm); %ROI3 ORIGO
end
%% VYPOCTENE PARAMETRY

if vyber == 0 % VÝBĚR POČÍTANÉ METRIKY - SSIM MATLAB
    AM=[71.0017490627563]; BM=-0.594768074633546; CM=1; kM=2396.77384715569; %parametry MATLAB
elseif vyber == 1 % VÝBĚR POČÍTANÉ METRIKY - SSIM ORIGO
    AO=53.8106502568338; BO=1; CO=3.66380724799290; kO=477.011953586679; %parametry ORIGO
end
%% VYSLEDEK FQR METODY

if vyber == 0 % VÝBĚR POČÍTANÉ METRIKY - SSIM MATLAB
    FQRM = kM*((AM*MSSIM1M)^2+BM*MSSIM2M+CM*MSSIM3M); % VYSLEDEK MATLAB
elseif vyber == 1 % VÝBĚR POČÍTANÉ METRIKY - SSIM ORIGO
    FQRO = kO*((AO*MSSIM1O)^2+BO*MSSIM2O+CO*MSSIM3O); % VYSLEDEK ORIGO
end

%AUTOR - DARIA BASHKATOVA, SSIM ALGORITMY PREVZATE Z:
%ORIGO - https://ece.uwaterloo.ca/~z70wang/research/ssim/ssim_index.m
%MATLAB - http://www.mathworks.com/help/images/ref/ssim.html?refresh=true