function varargout = BlobDetection(varargin)
% BLOBDETECTION MATLAB code for BlobDetection.fig
%      BLOBDETECTION, by itself, creates a new BLOBDETECTION or raises the existing
%      singleton*.
%
%      H = BLOBDETECTION returns the handle to a new BLOBDETECTION or the handle to
%      the existing singleton*.
%
%      BLOBDETECTION('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in BLOBDETECTION.M with the given input arguments.
%
%      BLOBDETECTION('Property','Value',...) creates a new BLOBDETECTION or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before BlobDetection_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to BlobDetection_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 BlobDetection

% Last Modified by GUIDE v2.5 21-Jul-2011 12:50:18

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @BlobDetection_OpeningFcn, ...
                   'gui_OutputFcn',  @BlobDetection_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 BlobDetection is made visible.
function BlobDetection_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 BlobDetection (see VARARGIN)

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

handles.S = 0;
set(handles.SymbolText,'String','X');

% handles.files = dir('img*.jpg');

figure(2)
figure(4)
figure(6)
figure(8)

% Update handles structure
guidata(hObject, handles);

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

% --- Outputs from this function are returned to the command line.
function varargout = BlobDetection_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 PB_Start.
function PB_Start_Callback(hObject, eventdata, handles)
% hObject    handle to PB_Start (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

%initialize the flag variable
set(handles.PB_Start,'UserData',1); 

ni = 1; % reset the counter for numbering of saved images

nametxt = 'PatternTest.txt'; % text file for statistic
file = fopen(nametxt, 'wt');
fprintf(file,'Name,\tRed,\tGreen,\tYellow,\tbRed,\tbGreen,\tbYellow,\tdMred,\tdMgreen,\tdMyellow,\tSymbol,\tMahalDist\n');
fclose(file);
    

%while the flag variable is one, the loop continues
while (get(handles.PB_Start,'UserData') == 1)
    
    % Loading image data
    files = dir('img*.jpg');
    namejpg = files(ni).name;

    image_rgb = imread(namejpg);

    figure(2), imshow(image_rgb);
    title('Original Image');

    % Converting to HSV colour space and extraction of HSV component
    hsv_image=rgb2hsv(image_rgb);
    [~,N,~]=size(hsv_image);

    image_H=hsv_image(:, :, 1);
    image_S=hsv_image(:, :, 2);
    image_V=hsv_image(:, :, 3);


    %% ### QUANTITY OF GREEN COLOUR ###
    value = (image_H>0.2 & image_H<0.54) & image_S>0.4 & image_V>0.4;
    qG = sum(sum(value)); % quantity of green color using color segmentation

%     figure(3), imshow(value);
%     title('Value, Green');

    % Blob analysis
    Label = bwlabel(value,4);
    BlobStats = regionprops(Label, 'Area', 'Solidity', 'Eccentricity', 'Extent', 'Perimeter', 'MajorAxisLength', 'MinorAxisLength', 'BoundingBox');
    idx = find([BlobStats.Area] > 35 & [BlobStats.Eccentricity] < 0.97);
    keepBlobImage = ismember(Label, idx);     % logical

    dMg = Inf; % Mahalanobis distance of green blob
    RdMg = dMg;
    qGb = sum(sum(keepBlobImage)); % quantity of green color using color segmentation and blobs
    RGg = qGb; % green for R&G symbol

    if numel(idx) ~= 0

        % Pattern recognition
        dM = zeros(1,numel(idx));
        X = [0.744400000000000,0.796000000000000,0.452700000000000,0.516300000000000,1.65200000000000;0.751300000000000,0.803600000000000,0.472400000000000,0.527400000000000,1.68030000000000;0.748100000000000,0.804400000000000,0.458900000000000,0.502600000000000,1.68310000000000;0.728900000000000,0.819700000000000,0.446500000000000,0.487000000000000,1.74580000000000;0.741200000000000,0.793400000000000,0.463600000000000,0.511800000000000,1.64590000000000;0.707000000000000,0.807400000000000,0.413800000000000,0.456800000000000,1.69500000000000;0.716700000000000,0.819400000000000,0.426800000000000,0.465000000000000,1.74450000000000;0.717000000000000,0.808000000000000,0.427800000000000,0.456000000000000,1.69740000000000;0.709900000000000,0.811800000000000,0.433400000000000,0.462300000000000,1.71240000000000;0.708300000000000,0.811700000000000,0.426500000000000,0.464400000000000,1.7120;0.716300000000000,0.876700000000000,0.430000000000000,0.457000000000000,2.07910000000000;0.719500000000000,0.866900000000000,0.449200000000000,0.440200000000000,2.00620000000000];

        FormFactor = imdivide((4*pi*[BlobStats.Area]),immultiply([BlobStats.Perimeter],[BlobStats.Perimeter]));
        AxisProp = imdivide([BlobStats.MajorAxisLength],[BlobStats.MinorAxisLength]);

        for i = 1:numel(idx)
            t = idx(i);
            T = [BlobStats(t).Solidity, BlobStats(t).Eccentricity, BlobStats(t).Extent, FormFactor(t), AxisProp(t)];
            dM(i) = mahal(T,X);
        end;

        MindM = find(dM == min(dM));
        dMg = dM(MindM);

        if dM(MindM) < 100
            RightBlob = idx(MindM);
            keepBlobImage = ismember(Label, RightBlob);
            figure(2)
            rectangle('Position', [BlobStats(RightBlob).BoundingBox], 'LineWidth', 1, 'EdgeColor','g')
            RdMg = dM(MindM);
        else if numel(idx) < 6
                keepBlobImage = zeros(size(Label));
                RGg = 0;
            end;
        end;

    end;

    figure(4), imshow(keepBlobImage);
    title('KeepBlob, Green');


    %% ### QUANTITY OF YELLOW COLOUR ###
    value =(image_H>0.11 & image_H<0.2) & image_S>0.5 & image_V>0.4;
    qY = sum(sum(value)); % quantity of yellow color using color segmentation

%     figure(5), imshow(value);
%     title('value, yellow');

    % Blob analysis
    Label = bwlabel(value,4);
    BlobStats = regionprops(Label, 'Area', 'Solidity', 'Eccentricity', 'Extent', 'Extent', 'Perimeter', 'MajorAxisLength', 'MinorAxisLength', 'Orientation', 'EulerNumber', 'BoundingBox', 'Centroid');
    idx = find([BlobStats.Area] > 180 & [BlobStats.Eccentricity] < 0.9 & [BlobStats.Solidity] > 0.55 & [BlobStats.Solidity] < 0.83 & [BlobStats.Extent] > 0.35 & [BlobStats.Orientation] > -25 & [BlobStats.Orientation] < 25 & [BlobStats.EulerNumber] > -8);
    keepBlobImage = ismember(Label, idx);     % logical

    dMy = Inf;
    RdMy = dMy;
    qYb = sum(sum(keepBlobImage)); % quantity of yellow color using blob

    if numel(idx) ~= 0

        % Pattern recognition
        dM = zeros(1,numel(idx));
        X = [0.7170,0.7712,0.4200,0.4619,1.5707;0.7262,0.7755,0.4575,0.497100000000000,1.58390000000000;0.708500000000000,0.851400000000000,0.433900000000000,0.502700000000000,1.90660000000000;0.666300000000000,0.764700000000000,0.403500000000000,0.368600000000000,1.55200000000000;0.741500000000000,0.833600000000000,0.463500000000000,0.495400000000000,1.81050000000000;0.692200000000000,0.743800000000000,0.395300000000000,0.438200000000000,1.49600000000000;0.715900000000000,0.785800000000000,0.426800000000000,0.467700000000000,1.61670000000000;0.662000000000000,0.816300000000000,0.399200000000000,0.424300000000000,1.73140000000000;0.722900000000000,0.798400000000000,0.421900000000000,0.470200000000000,1.66060000000000;0.679400000000000,0.777400000000000,0.409500000000000,0.385000000000000,1.58990000000000];

        FormFactor = imdivide((4*pi*[BlobStats.Area]),immultiply([BlobStats.Perimeter],[BlobStats.Perimeter]));
        AxisProp = imdivide([BlobStats.MajorAxisLength],[BlobStats.MinorAxisLength]);

        for i = 1:numel(idx)
            t = idx(i);
            T = [BlobStats(t).Solidity, BlobStats(t).Eccentricity, BlobStats(t).Extent, FormFactor(t), AxisProp(t)];
            dM(i) = mahal(T,X);
        end;

        MindM = find(dM == min(dM)); % blob with minumum Mahalanobis distance
        dMy = dM(MindM);

        if dM(MindM) < 100
            RightBlob = idx(MindM);
            RdMy = dM(MindM);

            Centroid = [BlobStats(RightBlob).Centroid];
            figure(2)
            hold on
            plot(Centroid(:,1), Centroid(:,2), 'r+')
            hold off

            rectangle('Position', [BlobStats(RightBlob).BoundingBox], 'LineWidth', 1, 'EdgeColor','g')

            Cx = int16(Centroid(:,1)); % X coordinate of centroid
            L = keepBlobImage(:,1:Cx); % left part of symbol
            R = keepBlobImage(:,Cx+1:N); % right part of symbol

            % calculation of area for left and right part
            AreaL =  sum(sum(L));
            AreaR =  sum(sum(R));

            % compare which part is bigger and establish direction
            D = 9; % reset direction
            if AreaL > AreaR
                D = 2; % to the left
            else if AreaL < AreaR
                    D = 4; % to the right
                end;
            end;
        else
            RightBlob = [];
        end;
        keepBlobImage = ismember(Label, RightBlob);
    end;

    figure(6), imshow(keepBlobImage);
    title('KeepBlob, yellow');


    %% ### QUANTITY OF RED COLOUR ###
    value = ((image_H >=0 & image_H<0.07) | (image_H >=0.96 & image_H<=1)) & image_S>0.5 & image_V>0.5;
    qR = sum(sum(value));   % quantity of red color using color segmentation

%     figure(7), imshow(value);
%     title('value, red');

    % Blob analysis
    Label = bwlabel(value,4);
    BlobStats = regionprops(Label, 'Area', 'Solidity', 'Eccentricity', 'Extent', 'Perimeter', 'MajorAxisLength', 'MinorAxisLength', 'BoundingBox');
    idx = find([BlobStats.Area] > 35 & [BlobStats.Eccentricity] < 0.97);  % index of areas biggest than 10
    keepBlobImage = ismember(Label, idx);     % logical

    dMr = Inf;
    RdMr = dMr;
    qRb = sum(sum(keepBlobImage)); % quantity of red color using blob
    RGr = qRb;

    if numel(idx) ~= 0

        % Pattern recognition
        dM = zeros(1,numel(idx));
        X = [0.5682,0.3061,0.5398,0.2744,1.0504;0.5738,0.3168,0.5373,0.2905,1.0543;0.5712,0.3442,0.5530,0.2895,1.0688;0.5793,0.3265,0.5621,0.2861,1.0580;0.5744,0.3790,0.5536,0.2883,1.0806;0.5648,0.3288,0.5482,0.2829,1.0589;0.5720,0.3195,0.5547,0.3003,1.0553;0.5775,0.3634,0.5549,0.2987,1.0734;0.5771,0.3319,0.5424,0.2866,1.0601;0.5820,0.3739,0.5664,0.2969,1.07820;0.543300000000000,0.502500000000000,0.475800000000000,0.272900000000000,1.15670000000000;0.515400000000000,0.625400000000000,0.459200000000000,0.258300000000000,1.28150000000000];

        FormFactor = imdivide((4*pi*[BlobStats.Area]),immultiply([BlobStats.Perimeter],[BlobStats.Perimeter]));
        AxisProp = imdivide([BlobStats.MajorAxisLength],[BlobStats.MinorAxisLength]);

        for i = 1:numel(idx)
            t = idx(i);
            T = [BlobStats(t).Solidity, BlobStats(t).Eccentricity, BlobStats(t).Extent, FormFactor(t), AxisProp(t)];
            dM(i) = mahal(T,X);
        end;

        MindM = find(dM == min(dM));
        dMr = dM(MindM);
        
        if numel(MindM) == 2
            AreaMindM = [BlobStats(MindM).Area];
            MaxAreaMindM = find(AreaMindM == max(AreaMindM));
            dMr = MindM(MaxAreaMindM);
        end;

        if dM(MindM) < 300
            RightBlob = idx(MindM);
            keepBlobImage = ismember(Label, RightBlob);
            figure(2)
            rectangle('Position', [BlobStats(RightBlob).BoundingBox], 'LineWidth', 1, 'EdgeColor','r')
            RdMr = dM(MindM);
        else if numel(idx) < 6
                keepBlobImage = zeros(size(Label));
                RGr = 0;
            end;
        end;
    end;

%     qRb = sum(sum(keepBlobImage)); % quantity of red color using blob detection

    figure(8), imshow(keepBlobImage);
    title('keepBlobImage, red');

%     % Proportion of colours, value in percent (colour segmentation)
%     red   =qR/numel(image_H)*100;
%     green =qG/numel(image_H)*100;
%     yellow=qY/numel(image_H)*100;
% 

%     % Dominant colour by colour segmentation / just for testing
%     dC = -8;
%     col={ 'red', 'green', 'yellow'};
%     if numel(idx) == 1
%         dC = idx;
%     else if numel(idx) == 2
%             dC = 22;
%         else if numel(idx) == 3
%                 dC = 33;
%             else
%                     dC = 88;
%             end;
%         end;
%     end;
% 
%     % Proportion of colours, values in percent (colour segmentation + blob analysis)
%     red_b   =qRb/numel(image_H)*100;
%     green_b =qGb/numel(image_H)*100;
%     yellow_b=qYb/numel(image_H)*100;


    %% Decision which symbol is in the image.
    col_comp = [RdMr RdMy RdMg];
    symbol = find(col_comp == min(col_comp));
    MahalDist = Inf;

    if numel(symbol) == 1
        symbol = symbol; % symbol with minimal Mahalanobis distance
        MahalDist = col_comp(symbol); % Mahalanobis distance of the symbol
    else if numel(symbol) == 2
            if RGR ~= 0 && RGg ~= 0
                symbol = 5; % symbol is R&G
            else
                symbol = 22; % there are two symbols recognized in the image
            end;
        else if numel(symbol) == 3
                if RGr ~= 0 && RGg ~= 0
                    symbol = 5; % symbol is R&G
                else
                    symbol = 0; % there are no symbol
                end;
            else if numel(symbol == 0)
                    if RGr ~= 0 && RGg ~= 0
                        symbol = 5; % symbol is R&G
                    else
                        symbol = 0; % there are no symbol
                    end;
                end;
            end;
        end;
    end;

    % if detected symbol is yellow arrow, specify the direction
    if symbol == 2
        symbol = D;
    end;

    ni = ni + 1;  % counter for numbering of saved images

    %% Save results into the text file
    file = fopen(nametxt, 'at');
    fprintf(file,'%s,\t%.0f,\t%.0f,\t%.0f,\t%.0f,\t%.0f,\t%.0f,\t%.4f,\t%.4f,\t%.4f,\t%.0f,\t%.4f\n', namejpg, qR, qG, qY, qRb, qGb, qYb, dMr, dMg, dMy, symbol, MahalDist);
    fclose(file);

    if symbol == 0
        S = '0';
        else if symbol == 1
            S = 'Red Cross';
            else  if symbol == 2
                    S = 'Left Arrow';
                else if symbol == 3
                        S = 'Green Arrow';
                    else if symbol == 4
                            S = 'Right Arrow';
                        else if symbol == 5
                                S = 'End';
                             end;
                         end;
                      end;
                   end;
            end;
    end;
    
    
    handles.S = S;
    set(handles.SymbolText, 'String',S);
    
   
end;

guidata(hObject, handles);

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

%toggle the flag variable so that the other process will stop
set(handles.PB_Start,'UserData',0);
guidata(hObject, handles);
