classdef app1 < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        UIFigure                   matlab.ui.Figure
        ResultsPanel               matlab.ui.container.Panel
        ObjectIdentificationPanel  matlab.ui.container.Panel
        ValueSlider                matlab.ui.control.Slider
        ValueSliderLabel           matlab.ui.control.Label
        SaturationSlider           matlab.ui.control.Slider
        SaturationSliderLabel      matlab.ui.control.Label
        HueSlider                  matlab.ui.control.Slider
        HueSliderLabel             matlab.ui.control.Label
        GetDepthFrameButton        matlab.ui.control.Button
        UIAxes2                    matlab.ui.control.UIAxes
        VideoPreviewPanel          matlab.ui.container.Panel
        GetVideoStreamsButton      matlab.ui.control.Button
        UIAxes_2                   matlab.ui.control.UIAxes
        UIAxes                     matlab.ui.control.UIAxes
    end

    
    methods (Access = public)
        
        function Kinect_DepthNormalization (depthImage)

    [row,col] = size(depthImage);
    widthBound = row-1;
    heightBound = col-1;

    % initializing working image; leave original matrix aside
    filledDepth = depthImage;

    %initializing the filter matrix
    filterBlock5x5 = zeros(5,5);
    
    % to keep count of zero pixels found
    zeroPixels = 0;
    
    %The main loop
    for x=1 : row
        for y=1 : col        
            %Only for pixels with 0 depth value; else skip
            if filledDepth(x,y) == 0;
                zeroPixels = zeroPixels+1;
                % values set to identify a positive filter result.
                 p = 1;
                % Taking a cube of 5x5 around the 0 depth pixel
                % q = index
                % select two pixels behind and two ahead in a row
                % select two pixels behind and two ahead in a column
                % leave the center pixel (as its the one to be filled)
                for xi = -2 : 1 : 2;
                    q = 1;
                    for yi = -2 : 1 : 2;
                        % updating index for next pass
                        xSearch = x + xi; 
                        ySearch = y + yi;
                        % xSearch and ySearch to avoid edges
                        if (xSearch > 0 && xSearch < widthBound && ySearch > 0 && ySearch < heightBound)
                            % save values from depth image into filter
                            filterBlock5x5(p,q) = filledDepth(xSearch,ySearch);
                        end
                        q = q+1;
                    end
                    p = p+1;
                end
                % Now that we have the 5x5 filter, with values surrounding
                % the zero valued fixel, in 'filterBlock5x5' ; we can now
                % Calculate statistical mode of the 5x5 matrix
                X = sort(filterBlock5x5(:));
                % find all non-zero entries in the sorted filter block 
                [~,~,v] = find(X);
                % indices where repeated values change
                if (isempty(v));
                    filledDepth(x,y) = 0;
                else
                    indices   =  find(diff([v; realmax]) > 0);
                    % finding longest persistent length of repeated values
                    [~,i] =  max (diff([0; indices]));     
                    % The value that is repeated is the mode
                    mode      =  v(indices(i));

                    % fill in the x,y value with the statistical mode of the values
                    filledDepth(x,y) = mode;
                end
            end
        end
    % end for
    end
return;
end
    end
   

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

        % Button pushed function: GetVideoStreamsButton
        function GetVideoStreamsButtonPushed(app, event)
            global vidDEPTH
            vidRGB = videoinput("kinect",1,"RGB_640x480");
            vidDEPTH = videoinput("kinect",2,"Depth_640x480");
            
            %% RGB Video Stream
            frameRGB = getsnapshot(vidRGB);
            imRGB = image(app.UIAxes,zeros(size(frameRGB),'uint8'));
            axis(app.UIAxes,'image');            
            preview(vidRGB,imRGB);

            % Define proper aspect ratio
            app.UIAxes.XLim = [0,640];
            app.UIAxes.YLim = [0,480];
            app.UIAxes.XTick = [];
            app.UIAxes.YTick = [];
            pbaspect(app.UIAxes,[640,480,1])

            %% Depth Video Stream             
            frameDEPTH = getsnapshot(vidDEPTH);
            imDEPTH = image(app.UIAxes_2,ones(size(frameDEPTH),'uint8'));
            axis(app.UIAxes_2,'image');            
            preview(vidDEPTH,imDEPTH);

            % Define proper aspect ratio
            app.UIAxes_2.XLim = [0,640];
            app.UIAxes_2.YLim = [0,480];
            app.UIAxes_2.XTick = [];
            app.UIAxes_2.YTick = [];
            pbaspect(app.UIAxes_2,[640,480,2])
        end

        % Button down function: UIAxes2
        function UIAxes2ButtonDown(app, event)

        end

        % Button pushed function: GetDepthFrameButton
        function GetDepthFrameButtonPushed(app, event)
            global vidDEPTH

            img_depth = getsnapshot(vidDEPTH);           
            Kinect_DepthNormalization(img_depth);
            imagesc(app.UIAxes2,filledImage);

            app.UIAxes2.XLim = [0,640];
            app.UIAxes2.YLim = [0,480];
            app.UIAxes2.XTick = [];
            app.UIAxes2.YTick = [];
%             pbaspect(app.UIAxes2,[640,480,2])
        end

        % Value changed function: HueSlider
        function HueSliderValueChanged(app, event)
                   
        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 1317 827];
            app.UIFigure.Name = 'MATLAB App';

            % Create VideoPreviewPanel
            app.VideoPreviewPanel = uipanel(app.UIFigure);
            app.VideoPreviewPanel.Title = 'Video Preview';
            app.VideoPreviewPanel.Position = [18 86 391 727];

            % Create UIAxes
            app.UIAxes = uiaxes(app.VideoPreviewPanel);
            title(app.UIAxes, 'RGB Stream')
            zlabel(app.UIAxes, 'Z')
            app.UIAxes.Position = [11 395 369 294];

            % Create UIAxes_2
            app.UIAxes_2 = uiaxes(app.VideoPreviewPanel);
            title(app.UIAxes_2, 'Depth Stream')
            zlabel(app.UIAxes_2, 'Z')
            app.UIAxes_2.Position = [11 72 369 294];

            % Create GetVideoStreamsButton
            app.GetVideoStreamsButton = uibutton(app.VideoPreviewPanel, 'push');
            app.GetVideoStreamsButton.ButtonPushedFcn = createCallbackFcn(app, @GetVideoStreamsButtonPushed, true);
            app.GetVideoStreamsButton.IconAlignment = 'center';
            app.GetVideoStreamsButton.Position = [113 19 166 33];
            app.GetVideoStreamsButton.Text = 'Get Video Streams';

            % Create ObjectIdentificationPanel
            app.ObjectIdentificationPanel = uipanel(app.UIFigure);
            app.ObjectIdentificationPanel.Title = 'Object Identification';
            app.ObjectIdentificationPanel.Position = [482 482 819 330];

            % Create UIAxes2
            app.UIAxes2 = uiaxes(app.ObjectIdentificationPanel);
            title(app.UIAxes2, 'Depth Frame')
            app.UIAxes2.ButtonDownFcn = createCallbackFcn(app, @UIAxes2ButtonDown, true);
            app.UIAxes2.Position = [21 41 354 253];

            % Create GetDepthFrameButton
            app.GetDepthFrameButton = uibutton(app.ObjectIdentificationPanel, 'push');
            app.GetDepthFrameButton.ButtonPushedFcn = createCallbackFcn(app, @GetDepthFrameButtonPushed, true);
            app.GetDepthFrameButton.IconAlignment = 'center';
            app.GetDepthFrameButton.Position = [145 14 108 22];
            app.GetDepthFrameButton.Text = 'Get Depth Frame';

            % Create HueSliderLabel
            app.HueSliderLabel = uilabel(app.ObjectIdentificationPanel);
            app.HueSliderLabel.HorizontalAlignment = 'right';
            app.HueSliderLabel.Position = [461 271 28 22];
            app.HueSliderLabel.Text = 'Hue';

            % Create HueSlider
            app.HueSlider = uislider(app.ObjectIdentificationPanel);
            app.HueSlider.ValueChangedFcn = createCallbackFcn(app, @HueSliderValueChanged, true);
            app.HueSlider.Position = [510 280 150 3];

            % Create SaturationSliderLabel
            app.SaturationSliderLabel = uilabel(app.ObjectIdentificationPanel);
            app.SaturationSliderLabel.HorizontalAlignment = 'right';
            app.SaturationSliderLabel.Position = [429 193 60 22];
            app.SaturationSliderLabel.Text = 'Saturation';

            % Create SaturationSlider
            app.SaturationSlider = uislider(app.ObjectIdentificationPanel);
            app.SaturationSlider.Position = [510 202 150 3];

            % Create ValueSliderLabel
            app.ValueSliderLabel = uilabel(app.ObjectIdentificationPanel);
            app.ValueSliderLabel.HorizontalAlignment = 'right';
            app.ValueSliderLabel.Position = [457 116 35 22];
            app.ValueSliderLabel.Text = 'Value';

            % Create ValueSlider
            app.ValueSlider = uislider(app.ObjectIdentificationPanel);
            app.ValueSlider.Position = [513 125 150 3];

            % Create ResultsPanel
            app.ResultsPanel = uipanel(app.UIFigure);
            app.ResultsPanel.Title = 'Results';
            app.ResultsPanel.Position = [483 137 815 315];

            % 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 = app1

            % 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