function varargout = KSVDRecaptureDetection(varargin)
% KSVDRECAPTUREDETECTION MATLAB code for KSVDRecaptureDetection.fig
%      KSVDRECAPTUREDETECTION, by itself, creates a new KSVDRECAPTUREDETECTION or raises the existing
%      singleton*.
%
%      H = KSVDRECAPTUREDETECTION returns the handle to a new KSVDRECAPTUREDETECTION or the handle to
%      the existing singleton*.
%
%      KSVDRECAPTUREDETECTION('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in KSVDRECAPTUREDETECTION.M with the given input arguments.
%
%      KSVDRECAPTUREDETECTION('Property','Value',...) creates a new KSVDRECAPTUREDETECTION or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before KSVDRecaptureDetection_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to KSVDRecaptureDetection_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help KSVDRecaptureDetection

% Last Modified by GUIDE v2.5 10-Jun-2014 18:58:07

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @KSVDRecaptureDetection_OpeningFcn, ...
                   'gui_OutputFcn',  @KSVDRecaptureDetection_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before KSVDRecaptureDetection is made visible.
function KSVDRecaptureDetection_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to KSVDRecaptureDetection (see VARARGIN)

% Choose default command line output for KSVDRecaptureDetection
handles.output = hObject;



axes(handles.DispImages);
set(gca,'XTick',[],'YTick',[]);
axes(handles.DispImages);
set(gca,'XTick',[],'YTick',[]);

axes(handles.ImperialLogo);
set(gca,'XTick',[],'YTick',[]);
logofile=strcat(pwd,'\GUI_data\ic_logo.png');
 imREWINDlogo= imread(logofile);
imshow(imREWINDlogo);


set( handles.StatusText, 'String', 'Initialization');
set( handles.StatusText, 'ForegroundColor', 'blue');

set( handles.DisplayResult, 'String', '');


% Update handles structure
guidata(hObject, handles);

% UIWAIT makes KSVDRecaptureDetection wait for user response (see UIRESUME)
% uiwait(handles.figure1);


% --- Outputs from this function are returned to the command line.
function varargout = KSVDRecaptureDetection_OutputFcn(hObject, eventdata, handles) 
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;


% --- Executes on button press in LoadSCDicButton.
function LoadSCDicButton_Callback(hObject, eventdata, handles)
% hObject    handle to LoadSCDicButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global SCDictionary;

[Myfile,MyPath] = uigetfile('*.mat','Load Dictionary');
filename=strcat(MyPath,Myfile);

SCDictionary = importdata(filename);



return


% --- Executes on button press in LoadRCDictButton.
function LoadRCDictButton_Callback(hObject, eventdata, handles)
% hObject    handle to LoadRCDictButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global RCDictionary;

[Myfile,MyPath] = uigetfile('*.mat','Load Dictionary');
filename=strcat(MyPath,Myfile);

RCDictionary = importdata(filename);

return


% --- Executes on button press in LoadImSetButton.
function LoadImSetButton_Callback(hObject, eventdata, handles)
% hObject    handle to LoadImSetButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global imFileName;
global imPathName;

 [imFileName, imPathName, FilterIndex] = uigetfile({'*.tif','TIF files (*.tif)';'*.jpg', 'Jpeg files (*.jpg)';'*.png', 'PNG files (*.png)'},...
                'Please select single capture image file(s)','Multiselect', 'on', 'C:\');
            
return



function EdgeDetectionFunc(hObject, eventdata, handles)

global QueryImage;
global  EdgeImage;


EdgeImage= edge(QueryImage,'canny',0.2);


% figure
% imshow(EdgeImage);
return


function BlockSelectionFunc(hObject, eventdata, handles)

global QueryImage;
global EdgeImage;
global DetectedArray;

global BlockWidth;
global BlockHeight;
global SharpnArray;

IHeight=size(EdgeImage,1);
ImWidth=size(EdgeImage,2);


DisQueryIm=QueryImage;

NumofDetected=0;
nFactor=4;

%##########################################################

%while NumofDetected < 150 %--- the number of block detected

BlockWidth=64/nFactor;
BlockHeight=64/nFactor;

nRows=ceil(IHeight/BlockHeight);
nCols=ceil(ImWidth/BlockWidth);


DetectedArray=zeros(nRows,nCols);



%##################################################



SharpnArray=zeros(nRows,nCols);
 

%------------------- Flexible for row and column ----------
if nRows>nCols    
    nMaxCol=nCols-1;
else
    nMaxCol=nCols;
end
%------------------------------------------------


 for n=1:nRows-1
   for m=1:nMaxCol


      iBlock(1:BlockHeight,1:BlockWidth)=EdgeImage((BlockHeight*(n-1)+1):(BlockHeight*(n-1)+BlockHeight),(BlockWidth*(m-1)+1):(BlockWidth*(m-1)+BlockWidth));
      imBlock(1:BlockHeight,1:BlockWidth)=QueryImage((BlockHeight*(n-1)+1):(BlockHeight*(n-1)+BlockHeight),(BlockWidth*(m-1)+1):(BlockWidth*(m-1)+BlockWidth));

if IsEDetected(iBlock,0.65)==1
% Detect when the block contains 65% of single lines     
   
    %----------------------------
     SharpnArray(n,m)=BlockAvKLength(imBlock); % measure sharpness of the blocks
        
     %--- measure contrast-----
     Block2Row=reshape(imBlock,1,BlockHeight*BlockWidth);
     stdArray(n,m)=std(im2double(Block2Row));
  
     
else     
    if IsEDetected(rot90(iBlock),0.65)==1
     SharpnArray(n,m)=-1*BlockAvKLength(rot90(iBlock)); % measure sharpness of the blocks
     % ####### Flag negative for horizontal alignment 
     Block2Row=reshape(imBlock,1,BlockHeight*BlockWidth);
     stdArray(n,m)=std(im2double(Block2Row));
     
    end
     
end

    
end
 end
   
 
 NumofDetected=nnz(SharpnArray);
 
 

% end %-- end while

 %####################################################################

 

 %------------------ Sharpness -------------
 
ShpCol = nonzeros(abs(SharpnArray));  
 ThShp = quantile(ShpCol,0.10);  % Select only 30% sharpest blocks  
 %------------------End Sharpness ------------
 
 %------------------Contrast -----------------
 
 stdCol = nonzeros(stdArray);
 ThSTD = quantile(stdCol,0.80);
 
 % --------------- End Contrast --------------
 
 
 
 absSharpnArray=abs(SharpnArray); 
 
sortedValues = unique(absSharpnArray(:));          %# Unique sorted values
minValues = sortedValues(1:15);  %# Get the 10 largest values
%SelectedValues=absSharpnArray(find( and((absSharpnArray<minValues(15)),(absSharpnArray>0))));
SelectedValues=absSharpnArray(find( and((absSharpnArray<ThShp),(absSharpnArray>0))));

DetectedArray = ismember(absSharpnArray,SelectedValues);
 

NumofDetected=nnz(DetectedArray);


for n=1:nRows-1
   for m=1:nMaxCol
     if DetectedArray(n,m)==1
      DisQueryIm((16*(n-1)+1):(16*(n-1)+16),(16*(m-1)+1):(16*(m-1)+16))=  DisQueryIm((16*(n-1)+1):(16*(n-1)+16),(16*(m-1)+1):(16*(m-1)+16))+20; 
     else
      DisQueryIm((16*(n-1)+1):(16*(n-1)+16),(16*(m-1)+1):(16*(m-1)+16))=0;    
     end
   end
end

 axes(handles.DispImages);
imshow(DisQueryIm);

set( handles.DispNumOfBlocks, 'String', num2str(NumofDetected));
set( handles.DispNumOfBlocks, 'ForegroundColor', 'blue');

return

function ClassificationFunc(hObject, eventdata, handles)

global DetectedArray;
global QueryImage; 
global SharpnArray;

IHeight=size(QueryImage,1);
ImWidth=size(QueryImage,2);

global BlockWidth;
global BlockHeight;



nRows=ceil(IHeight/BlockHeight);
nCols=ceil(ImWidth/BlockWidth);


global SCDictionary;
global RCDictionary;
global SVMStruct; 
   
%------------------- Flexible for row and column ----------
if nRows>nCols    
    nMaxCol=nCols-1;
else
    nMaxCol=nCols;
end
%------------------------------------------------

%--- Initialization ------
Totalerr =0;
Y=[];
BlockCount=0;

 for n=1:nRows-1
   for m=1:nMaxCol
       
   %=============================    
      if DetectedArray(n,m)==1
            
      ImBlock(1:BlockHeight,1:BlockWidth)=QueryImage((BlockHeight*(n-1)+1):(BlockHeight*(n-1)+BlockHeight),(BlockWidth*(m-1)+1):(BlockWidth*(m-1)+BlockWidth));      
      WidthAv(n,m)=BlockAvKLength(ImBlock); % Calculate average width of the block 
     %----- For an horizontal edge --- 
     if SharpnArray(n,m)<0
      ImBlock=rot90( ImBlock);
      WidthAv(n,m)=BlockAvKLength(rot90(ImBlock));  
     end
      
      
   BlockCount=BlockCount+1;
   

    SampleSet=ExtractSamples(ImBlock,2);  
    if norm(SampleSet)>0
    Y=[Y SampleSet]; 
    end
   
  
      end %== detected array
    %=============================   
       
   end
 end
 
   %disp(['Number of Samples: ',num2str(size(Y,2))]);  
   
   %--------- The number of samples -------------
   NOfSamples=size(Y,2);
   
   %========= Matching Pursuit for Single Capture ======== 
   SCCoefMatrix=OMP(SCDictionary,Y,3);
   SCTotalerr = sqrt(sum(sum((Y-SCDictionary*SCCoefMatrix).^2))/prod(size(Y)));
   
   %========= Matching Pursuit for Recapture ======== 
   RCCoefMatrix=OMP(RCDictionary,Y,3);
   RCTotalerr = sqrt(sum(sum((Y-RCDictionary*RCCoefMatrix).^2))/prod(size(Y)));
   
   WidthAvCol = nonzeros(WidthAv);  
   WMean=mean(WidthAvCol)/4;

   %========= Recapture Detection ===============
   
   %-- Create Classification Features -----
  
   global QFeature;
   
   QFeature=[WMean SCTotalerr-RCTotalerr];  %Feature1 : Errors Feature2: Width 
   
   
  

   ClassResult = svmclassify(SVMStruct,QFeature);
  
    
   %if SCTotalerr>RCTotalerr
   
   if strcmp(ClassResult,'Recapture')
    DetectionFlag=1;
    set( handles.DisplayResult, 'String', 'Recaptured');
    set( handles.DisplayResult, 'ForegroundColor', 'white');
        set( handles.DisplayResult, 'BackgroundColor', 'red');
    set( handles.ResultPanel, 'BackgroundColor', 'red');
    
   else
    DetectionFlag=0;
       set( handles.DisplayResult, 'String', 'Original');
    set( handles.DisplayResult, 'ForegroundColor', 'white');
      set( handles.DisplayResult, 'BackgroundColor', [0 0.8 0]);
    set( handles.ResultPanel, 'BackgroundColor', [0 0.8 0]);
    
   end
 
%---- Output Fof Multiple Files -----------
global outToFile; 

outToFile={BlockCount,NOfSamples,SCTotalerr,RCTotalerr,WMean,DetectionFlag}; 

return


% --- Executes on button press in BatchComputeButton.
function BatchComputeButton_Callback(hObject, eventdata, handles)
% hObject    handle to BatchComputeButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
clc;

global imFileName;
global imPathName;

global QueryImage;

global outToFile; 
global SVMStruct; 

%-------- Fixed Dictionary ---------
global SCDictionary;
global RCDictionary;


SCDictionary = importdata('Dictionary/LDictionarySC_200its_3atoms_15DEC2013.mat');
RCDictionary = importdata('Dictionary/LDictionaryRC_200its_3atoms_15DEC2013.mat');


%SVMStruct=importdata('TrainedFeatures/SVMTrainSCRC.mat');
SVMStruct=importdata('TrainedFeatures/SVMTrain_QKernel.mat');


    
  % Iteration over selected images
  disp('Batch Processing:');
  
 
    for i=1:max(size(imFileName))
  
  
    QueryImage= imread(fullfile(imPathName, imFileName{i}));
    
    axes(handles.DispImages);
    imshow(QueryImage);
    pause(0.001);
    

   %-------------- Check whether the image is RGB ------------- 
   if size(QueryImage,3)==3 
    QueryImage=rgb2gray(QueryImage);
   end
    
   if size(QueryImage,1)<size(QueryImage,2)
     QueryImage = imresize(QueryImage,[NaN 2048]); 
   else
     QueryImage = imresize(QueryImage,[2048 NaN]);  
   end
    %-----------------------------
 

EdgeDetectionFunc(hObject, eventdata, handles)
BlockSelectionFunc(hObject, eventdata, handles)
ClassificationFunc(hObject, eventdata, handles);


 disp([num2str(i),' ',num2str(imFileName{i}),' ',num2str(outToFile{1}),' ',num2str(outToFile{2}),' ',mat2str(outToFile{3},[4 0]),' ',mat2str(outToFile{4},[4 0]),' ',mat2str(outToFile{5},[4 0]),' ',num2str(outToFile{6})]);    

    end
    disp('--- Complete !----');
    
return


% --- Executes on button press in LoadImageButton.
function LoadImageButton_Callback(hObject, eventdata, handles)
% hObject    handle to LoadImageButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
clc;

[filename, pathname] = uigetfile('*.jpg', 'Select a Query Image File');

if isequal(filename,0)
   disp('User selected Cancel')
else
   disp(['User selected: ', fullfile(pathname, filename)])
    
    global QueryImage;
    QueryImage= imread(fullfile(pathname, filename));

    axes(handles.DispImages);
    imshow(QueryImage);
    
    
    set( handles.StatusText, 'String', 'Image Loaded');
    set( handles.StatusText, 'ForegroundColor', 'blue');

end  


return


% --- Executes on button press in BlockEdgeDetectionButton.
function BlockEdgeDetectionButton_Callback(hObject, eventdata, handles)
% hObject    handle to BlockEdgeDetectionButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global QueryImage;
global  EdgeImage;

% if size(QueryImage,3)==3 
%     QueryImage=rgb2gray(QueryImage);
%    end
%     
%    if size(QueryImage,1)<size(QueryImage,2)
%      QueryImage = imresize(QueryImage,[NaN 2048]); 
%    else
%      QueryImage = imresize(QueryImage,[2048 NaN]);  
%    end
%     %-----------------------------
%  
% 
% EdgeDetectionFunc(hObject, eventdata, handles)
BlockSelectionFunc(hObject, eventdata, handles)

set( handles.StatusText, 'String', 'Blocks Selected');
set( handles.StatusText, 'ForegroundColor', 'blue');

return


% --- Executes on button press in ClassificationButton.
function ClassificationButton_Callback(hObject, eventdata, handles)
% hObject    handle to ClassificationButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global QueryImage;

global outToFile; 
global SVMStruct; 

%-------- Fixed Dictionary ---------
global SCDictionary;
global RCDictionary;


SCDictionary = importdata('Dictionary/LDictionarySC_200its_3atoms.mat');
RCDictionary = importdata('Dictionary/LDictionaryRC_200its_3atoms.mat');


%SVMStruct=importdata('TrainedFeatures/SVMTrainSCRC.mat');
SVMStruct=importdata('TrainedFeatures/SVMStructClassification.mat');

ClassificationFunc(hObject, eventdata, handles);

 disp([num2str(outToFile{1}),' ',num2str(outToFile{2}),' ',mat2str(outToFile{3},[4 0]),' ',mat2str(outToFile{4},[4 0]),' ',mat2str(outToFile{5},[4 0]),' ',num2str(outToFile{6})]);    


return


% --- Executes on button press in EdgeDetectionButton.
function EdgeDetectionButton_Callback(hObject, eventdata, handles)
% hObject    handle to EdgeDetectionButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

global QueryImage;
global  EdgeImage;


if size(QueryImage,3)==3 
    QueryImage=rgb2gray(QueryImage);
   end
    
   if size(QueryImage,1)<size(QueryImage,2)
     QueryImage = imresize(QueryImage,[NaN 2048]); 
   else
     QueryImage = imresize(QueryImage,[2048 NaN]);  
   end
   

EdgeImage= edge(QueryImage,'canny',0.2);
axes(handles.DispImages);
imshow(EdgeImage);

set( handles.StatusText, 'String', 'Edges Detected');
set( handles.StatusText, 'ForegroundColor', 'blue');


return


% --- Executes on button press in ShowCoorButton.
function ShowCoorButton_Callback(hObject, eventdata, handles)
% hObject    handle to ShowCoorButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

global SVMStruct; 
global QFeature;

figure

set(0, 'currentfigure', f);  %# for figures
set(f, 'currentaxes', axs); 

%set(0,'CurrentFigure')
%plot(h,svmclassify(SVMStruct,QFeature,'Showplot',true));

% %axes(handles.DispImages);
ClassResult = svmclassify(SVMStruct,QFeature,'Showplot',true);

return
