classdef Extra_detect < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        UIFigure                matlab.ui.Figure
        Panel                   matlab.ui.container.Panel
        MinLengthSpinner        matlab.ui.control.Spinner
        MinLengthSpinnerLabel   matlab.ui.control.Label
        FillGapSpinner          matlab.ui.control.Spinner
        FillGapSpinnerLabel     matlab.ui.control.Label
        RadiusrangeSlider       matlab.ui.control.RangeSlider
        RadiusrangeSliderLabel  matlab.ui.control.Label
        InverseButton           matlab.ui.control.StateButton
        ObjecttypeButtonGroup   matlab.ui.container.ButtonGroup
        CirclesButton           matlab.ui.control.ToggleButton
        LinesButton             matlab.ui.control.ToggleButton
        LoadButton              matlab.ui.control.Button
        ImageAxes               matlab.ui.control.UIAxes
    end


    properties (Access = private)
        RGBImage;
        BWImage;
        Lines;
        Center;
        Radius;

    end

    methods (Access = private)

        function results = DrawImage(app)
            imshow(app.RGBImage, Parent=app.ImageAxes);
            hold(app.ImageAxes, "on");

            if app.ObjecttypeButtonGroup.SelectedObject == app.LinesButton
            for k = 1:length(app.Lines)
                xy = [app.Lines(k).point1; app.Lines(k).point2];
                plot(app.ImageAxes,xy(:,1),xy(:,2),'LineWidth',2,'Color','green');

                plot(app.ImageAxes,xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
                plot(app.ImageAxes,xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');
            end
            else
                viscircles(app.ImageAxes, app.Center, app.Radius,'EdgeColor','b');
            end


            hold(app.ImageAxes,"off");
        end

        
        function results = FindObjects(app)
            if app.ObjecttypeButtonGroup.SelectedObject == app.LinesButton
                [H,T,R] = hough(app.BWImage);
                P  = houghpeaks(H,5,'threshold',ceil(0.3*max(H(:))));
                app.Lines = houghlines(app.BWImage,T,R,P,'FillGap',app.FillGapSpinner.Value,'MinLength',app.MinLengthSpinner.Value);
            else
                [app.Center,app.Radius] = imfindcircles(app.RGBImage, round(app.RadiusrangeSlider.Value));
            end

            
        end
    end


    % Callbacks that handle component events
    methods (Access = private)

        % Button pushed function: LoadButton
        function LoadButtonPushed(app, event)
        try
        [file, path] = uigetimagefile;
        if ~isempty(file)
            app.RGBImage = double(imread(file))/255;
            app.BWImage = edge(rgb2gray(app.RGBImage),'canny');

            app.FindObjects;
            app.DrawImage;

            app.ImageAxes.Visible = "on";

            app.Panel.Visible = "on";
        end
        catch e
            uialert(app.UIFigure, e.message, "Error while loading image",Interpreter="html");
        end
        end

        % Value changed function: FillGapSpinner, MinLengthSpinner, 
        % ...and 1 other component
        function MinLengthSpinnerValueChanged(app, event)
            app.FindObjects;
            app.DrawImage;
        end

        % Value changed function: InverseButton
        function InverseButtonValueChanged(app, event)
            app.BWImage = ~app.BWImage;
            app.FindObjects;
            app.DrawImage;
        end

        % Selection changed function: ObjecttypeButtonGroup
        function ObjecttypeButtonGroupSelectionChanged(app, event)
            selectedButton = app.ObjecttypeButtonGroup.SelectedObject;
            if selectedButton==app.CirclesButton
                app.MinLengthSpinner.Visible= "off";
                app.FillGapSpinner.Visible = "off";
                app.RadiusrangeSlider.Visible = "on";

                app.MinLengthSpinnerLabel.Visible= "off";
                app.FillGapSpinnerLabel.Visible = "off";
                app.RadiusrangeSliderLabel.Visible = "on";
            else
                app.MinLengthSpinner.Visible= "on";
                app.FillGapSpinner.Visible = "on";
                app.RadiusrangeSlider.Visible = "off";

                app.MinLengthSpinnerLabel.Visible= "on";
                app.FillGapSpinnerLabel.Visible = "on";
                app.RadiusrangeSliderLabel.Visible = "off";
            end
            app.FindObjects;
            app.DrawImage;
        end
    end

    % Component initialization
    methods (Access = private)

        % Create UIFigure and components
        function createComponents(app)

            % Create UIFigure and hide until all components are created
            app.UIFigure = uifigure('Visible', 'off');
            app.UIFigure.Position = [100 100 1172 493];
            app.UIFigure.Name = 'MATLAB App';

            % Create ImageAxes
            app.ImageAxes = uiaxes(app.UIFigure);
            app.ImageAxes.XTick = [];
            app.ImageAxes.YTick = [];
            app.ImageAxes.ZTick = [];
            app.ImageAxes.Position = [2 14 640 480];

            % Create LoadButton
            app.LoadButton = uibutton(app.UIFigure, 'push');
            app.LoadButton.ButtonPushedFcn = createCallbackFcn(app, @LoadButtonPushed, true);
            app.LoadButton.Position = [672 446 100 23];
            app.LoadButton.Text = 'Load';

            % Create Panel
            app.Panel = uipanel(app.UIFigure);
            app.Panel.Visible = 'off';
            app.Panel.Position = [673 1 488 433];

            % Create ObjecttypeButtonGroup
            app.ObjecttypeButtonGroup = uibuttongroup(app.Panel);
            app.ObjecttypeButtonGroup.SelectionChangedFcn = createCallbackFcn(app, @ObjecttypeButtonGroupSelectionChanged, true);
            app.ObjecttypeButtonGroup.Title = 'Object type';
            app.ObjecttypeButtonGroup.Position = [1 327 123 106];

            % Create LinesButton
            app.LinesButton = uitogglebutton(app.ObjecttypeButtonGroup);
            app.LinesButton.Text = 'Lines';
            app.LinesButton.Position = [11 52 100 23];
            app.LinesButton.Value = true;

            % Create CirclesButton
            app.CirclesButton = uitogglebutton(app.ObjecttypeButtonGroup);
            app.CirclesButton.Text = 'Circles';
            app.CirclesButton.Position = [11 31 100 23];

            % Create InverseButton
            app.InverseButton = uibutton(app.Panel, 'state');
            app.InverseButton.ValueChangedFcn = createCallbackFcn(app, @InverseButtonValueChanged, true);
            app.InverseButton.Text = 'Inverse';
            app.InverseButton.Position = [124 409 100 23];

            % Create RadiusrangeSliderLabel
            app.RadiusrangeSliderLabel = uilabel(app.Panel);
            app.RadiusrangeSliderLabel.HorizontalAlignment = 'right';
            app.RadiusrangeSliderLabel.Visible = 'off';
            app.RadiusrangeSliderLabel.Position = [13 284 42 30];
            app.RadiusrangeSliderLabel.Text = {'Radius'; 'range'};

            % Create RadiusrangeSlider
            app.RadiusrangeSlider = uislider(app.Panel, 'range');
            app.RadiusrangeSlider.Limits = [0 300];
            app.RadiusrangeSlider.ValueChangedFcn = createCallbackFcn(app, @MinLengthSpinnerValueChanged, true);
            app.RadiusrangeSlider.Visible = 'off';
            app.RadiusrangeSlider.Position = [77 301 300 3];
            app.RadiusrangeSlider.Value = [50 200];

            % Create FillGapSpinnerLabel
            app.FillGapSpinnerLabel = uilabel(app.Panel);
            app.FillGapSpinnerLabel.HorizontalAlignment = 'right';
            app.FillGapSpinnerLabel.Position = [33 292 46 22];
            app.FillGapSpinnerLabel.Text = 'Fill Gap';

            % Create FillGapSpinner
            app.FillGapSpinner = uispinner(app.Panel);
            app.FillGapSpinner.Limits = [1 100];
            app.FillGapSpinner.ValueChangedFcn = createCallbackFcn(app, @MinLengthSpinnerValueChanged, true);
            app.FillGapSpinner.Position = [94 292 100 22];
            app.FillGapSpinner.Value = 1;

            % Create MinLengthSpinnerLabel
            app.MinLengthSpinnerLabel = uilabel(app.Panel);
            app.MinLengthSpinnerLabel.HorizontalAlignment = 'right';
            app.MinLengthSpinnerLabel.Position = [15 263 64 22];
            app.MinLengthSpinnerLabel.Text = 'Min Length';

            % Create MinLengthSpinner
            app.MinLengthSpinner = uispinner(app.Panel);
            app.MinLengthSpinner.Limits = [1 500];
            app.MinLengthSpinner.ValueChangedFcn = createCallbackFcn(app, @MinLengthSpinnerValueChanged, true);
            app.MinLengthSpinner.Position = [94 263 100 22];
            app.MinLengthSpinner.Value = 1;

            % Show the figure after all components are created
            app.UIFigure.Visible = 'on';
        end
    end

    % App creation and deletion
    methods (Access = public)

        % Construct app
        function app = Extra_detect

            % Create UIFigure and components
            createComponents(app)

            % Register the app with App Designer
            registerApp(app, app.UIFigure)

            if nargout == 0
                clear app
            end
        end

        % Code that executes before app deletion
        function delete(app)

            % Delete UIFigure when app is deleted
            delete(app.UIFigure)
        end
    end
end