classdef app1_FINAL_ChaoRemov_Target_ROI_2 < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        UIFigure                    matlab.ui.Figure
        OBJECTDETECTIONPanel        matlab.ui.container.Panel
        CONTOURSPanel               matlab.ui.container.Panel
        ShowContoursButton          matlab.ui.control.Button
        UIAxesObjectContours        matlab.ui.control.UIAxes
        REGIONOFINTERESTPanel       matlab.ui.container.Panel
        SelectRegionofInterestforContoursPanel  matlab.ui.container.Panel
        SelectedROICheckBox         matlab.ui.control.CheckBox
        FullObjectCheckBox          matlab.ui.control.CheckBox
        TabGroup                    matlab.ui.container.TabGroup
        FullObjectPointCloudTab     matlab.ui.container.Tab
        ShowObjectPointCloudButton  matlab.ui.control.Button
        ROITab                      matlab.ui.container.Tab
        ShowROIPointCloudButton     matlab.ui.control.Button
        DeleteROIButton             matlab.ui.control.Button
        SelectROIButton             matlab.ui.control.Button
        TargetAreaPanel             matlab.ui.container.Panel
        Image                       matlab.ui.control.Image
        GetTargetAreaButton         matlab.ui.control.Button
        ZLabel                      matlab.ui.control.Label
        YLabel                      matlab.ui.control.Label
        XLabel                      matlab.ui.control.Label
        EditField_Zmax              matlab.ui.control.NumericEditField
        EditField_Zmin              matlab.ui.control.NumericEditField
        EditField_Xmax              matlab.ui.control.NumericEditField
        EditField_Ymax              matlab.ui.control.NumericEditField
        EditField_Ymin              matlab.ui.control.NumericEditField
        EditField_Xmin              matlab.ui.control.NumericEditField
        ViewFullPointCloudButton    matlab.ui.control.Button
        GetFullPointCloudButton     matlab.ui.control.Button
        ExitButton                  matlab.ui.control.Button
        VIDEOSTREAMSPanel           matlab.ui.container.Panel
        DepthVideoStreamLabel       matlab.ui.control.Label
        RGBVideoStreamLabel         matlab.ui.control.Label
        StartStreamsButton          matlab.ui.control.Button
        UIAxesDEPTHStream           matlab.ui.control.UIAxes
        UIAxesRGBStream             matlab.ui.control.UIAxes
    end

    
    methods (Access = private)
        

        
        function [pcloud, distance] = depthToCloud(depth,topleft,profmax)

            if nargin < 2
                topleft = [1 1];
            end

            depth= double(depth);
            depth(depth>profmax) = nan;
            depth(depth==0) = nan;

            % RGB-D camera constants
            center = [320 240];
            [imh, imw] = size(depth);
            constant = 570.3;
            MM_PER_M = 1000;

            % convert depth image to 3d point clouds
            pcloud = zeros(imh,imw,3);
            xgrid = ones(imh,1)*(1:imw) + (topleft(1)-1) - center(1);
            ygrid = (1:imh)'*ones(1,imw) + (topleft(2)-1) - center(2);
            pcloud(:,:,1) = xgrid.*depth/constant/MM_PER_M;
            pcloud(:,:,2) = ygrid.*depth/constant/MM_PER_M;
            pcloud(:,:,3) = depth/MM_PER_M;
            distance = sqrt(sum(pcloud.^2,3));            
        end
    end
    

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

        % Code that executes after component creation
        function startupFcn(app)
            % DESATIVAR TODOS OS BOTÕES AO INICIAR A APP
            set(app.GetFullPointCloudButton,'Enable','off')
            set(app.ViewFullPointCloudButton,'Enable','off')
            set(app.EditField_Xmax,'Enable','off')
            set(app.EditField_Xmin,'Enable','off')
            set(app.EditField_Ymax,'Enable','off')
            set(app.EditField_Ymin,'Enable','off')
            set(app.EditField_Zmax,'Enable','off')
            set(app.EditField_Zmin,'Enable','off')
            set(app.GetTargetAreaButton,'Enable','off')
            set(app.ViewFullPointCloudButton,'Enable','off')
            set(app.ShowObjectPointCloudButton,'Enable','off')
            set(app.ShowContoursButton,'Enable','off')
        end

        % Button pushed function: StartStreamsButton
        function StartStreamsButtonPushed(app, event)
            %% GLOBALS
            global DEPTHDisp
            global RGBDisp
            global imgRGB
            global RGBFrameFlipped
            global DEPTHFrameFlipped

            %% FECHAR JANELA ABERTA
            close(figure(1))

           % ATIVAR O BOTAO PARA OBTER NUVEM COMPLETA, DEPOIS DO BOTÃO PARA OBTER AS STREAMS SER CLICKADO
            if app.StartStreamsButton.Enable
                set(app.GetFullPointCloudButton,'Enable','on')
            end

            % AVISAR O USER QUE É NECESSÁRIO ESPERAR PELA DEPTH CAM ESTABILIZAR PARA SE OBTER A NUVEM DE PONTOS
            if app.StartStreamsButton.Enable
                uialert(app.UIFigure,'Depth camera must be stabilised before proceeding to the next stage.','Depth camera stabilization','Icon','warning')
            end

            %% RGB
            % LIGAR CAMARA RGB
            RGBDisp = videoinput('kinect',1,'RGB_640x480');

            RGBFrameFlipped = flip(getsnapshot(RGBDisp),2);
            imgRGB = image(app.UIAxesRGBStream,zeros(size(RGBFrameFlipped),'uint16'));

            % MOSTRAR RGB STREAM
            axis(app.UIAxesRGBStream,'image');
            preview(RGBDisp,imgRGB);

            % RGB VIDEO STREAM ASPECT RATIO
            app.UIAxesRGBStream.XLim = [0,640];
            app.UIAxesRGBStream.YLim = [0,480];
            pbaspect(app.UIAxesRGBStream,[640,480,1]);

            %% DEPTH
            % LIGAR CAMARA DEPTH
            DEPTHDisp = videoinput('kinect',2,'Depth_640x480');

            DEPTHFrameFlipped = flip(getsnapshot(DEPTHDisp),2);
            imgDEPTH = image(app.UIAxesDEPTHStream,zeros(size(DEPTHFrameFlipped),'uint16'));

            % MOSTRAR DEPTH STREAM
            axis(app.UIAxesDEPTHStream)
            preview(DEPTHDisp,imgDEPTH)

            % DEPTH VIDEO STREAM ASPECT RATIO
            app.UIAxesDEPTHStream.XLim = [0,640];
            app.UIAxesDEPTHStream.YLim = [0,480];
            pbaspect(app.UIAxesDEPTHStream,[640,480,2]);
            colormap(app.UIAxesDEPTHStream,'jet')

        end

        % Button pushed function: ExitButton
        function ExitButtonPushed(app, event)
            app.delete
            close all
        end

        % Button pushed function: GetFullPointCloudButton
        function GetFullPointCloudButtonPushed(app, event)
            %% GLOBALS
            global DEPTHDisp
            global RGBDisp
            global ptCloudRot

            % ATIVAR O BOTAO PARA OBTER NUVEM COMPLETA, DEPOIS DO BOTÃO PARA OBTER AS STREAMS SER CLICKADO
            if app.GetFullPointCloudButton.Enable
                set(app.GetTargetAreaButton,'Enable','on')
                set(app.EditField_Xmax,'Enable','on')
                set(app.EditField_Xmin,'Enable','on')
                set(app.EditField_Ymax,'Enable','on')
                set(app.EditField_Ymin,'Enable','on')
                set(app.EditField_Zmax,'Enable','on')
                set(app.EditField_Zmin,'Enable','on')
                set(app.ViewFullPointCloudButton,'Enable','on')
            end

            % MUDAR O NOME DO BOTAO DEPOIS DESTE SER CLICKADO
            if app.GetFullPointCloudButton.Enable
                app.GetFullPointCloudButton.Text = "Update Full Point Cloud";
            end

            %% FECHAR JANELA ABERTA
            close(figure(1))

            %% NUVEM DE PONTOS COMPLETA
            % EXTRAIR A NUVEM DE PONTOS
            RGBFrame1 = getsnapshot(RGBDisp);
            DEPTHFrame1 = getsnapshot(DEPTHDisp);

            ptCloudOriginal = pcfromkinect(DEPTHDisp, DEPTHFrame1, RGBFrame1);

            %% RODAR A NUVEM DE PONTOS PARA FICAR PARALELA COM EIXO DOS XX
            %ANGULO DE ROTAÇAO
            theta = -0.04;

            % MATRIZ DE ROTAÇAO EM X
            Rx = [1 0 0; 0 cos(theta) -sin(theta); 0 sin(theta) cos(theta)];
            trans = [0, 0, 0];
            tform = rigid3d(Rx,trans);

            % NOVA NUVEM DE PONTOS RODADA
            ptCloudRot = pctransform(ptCloudOriginal,tform);

            % MOSTART NUVEM DE PONTOS
            figure
            pcshow(ptCloudRot,"VerticalAxis","Y",VerticalAxisDir="Down");
            title('Full Point Cloud')
            xlabel('X(m)')
            ylabel('Y(m)')
            zlabel('Z(m)')

        end

        % Button pushed function: GetTargetAreaButton
        function GetTargetAreaButtonPushed(app, event)
            %% GLOBALS
            global ptCloudRot
            global ptcloudB
            
            % ATIVAR O BOTAO PARA OBTER NUVEM COMPLETA, DEPOIS DO BOTÃO PARA OBTER AS STREAMS SER CLICKADO
            if app.GetTargetAreaButton.Enable
                set(app.ShowObjectPointCloudButton,'Enable','on')
            end

            % MUDAR O NOME DO BOTAO DEPOIS DESTE SER CLICKADO
             if app.GetTargetAreaButton.Enable
                app.GetTargetAreaButton.Text = "Update Target Area";
            end

            %% FECHAR JANELA ABERTA
            close(figure(1))
            %%
           
            stepSize = 100;

            indices = 1:stepSize:ptCloudRot.Count;
            tempPtCloud = select(ptCloudRot,indices);

            [tempPtCloud,validIndices] = removeInvalidPoints(tempPtCloud);

            worldPoints = tempPtCloud.Location;

            [Y,X] = ind2sub([size(ptCloudRot.Location,1),size(ptCloudRot.Location,2)],indices);
            imagePoints = [X(validIndices)' Y(validIndices)'];

            camMatrix = estimateCameraMatrix(imagePoints,worldPoints);

            roi = [app.EditField_Xmin.Value app.EditField_Xmax.Value app.EditField_Ymin.Value app.EditField_Ymax.Value app.EditField_Zmin.Value app.EditField_Zmax.Value];
            
            indices = findPointsInROI(ptCloudRot,roi,camMatrix);
            ptcloudB = select(ptCloudRot,indices);

            figure
            pcshow(ptCloudRot,"VerticalAxis","Y",VerticalAxisDir="Down")
            hold on
            pcshow(ptcloudB.Location,'r',"VerticalAxis","Y",VerticalAxisDir="Down")
            title('Full Point Cloud with Target Area')
            xlabel('X(m)')
            ylabel('Y(m)')
            zlabel('Z(m)')

            p1 = [app.EditField_Xmin.Value app.EditField_Ymax.Value app.EditField_Zmax.Value]';
            p2 = [app.EditField_Xmin.Value app.EditField_Ymax.Value app.EditField_Zmin.Value]';
            p3 = [app.EditField_Xmax.Value app.EditField_Ymax.Value app.EditField_Zmin.Value]';
            p4 = [app.EditField_Xmax.Value app.EditField_Ymax.Value app.EditField_Zmax.Value]';
            p5 = [app.EditField_Xmin.Value app.EditField_Ymin.Value app.EditField_Zmax.Value]';
            p6 = [app.EditField_Xmin.Value app.EditField_Ymin.Value app.EditField_Zmin.Value]';
            p7 = [app.EditField_Xmax.Value app.EditField_Ymin.Value app.EditField_Zmin.Value]';
            p8 = [app.EditField_Xmax.Value app.EditField_Ymin.Value app.EditField_Zmax.Value]';

            A1=[p1 p2 p3 p4;p4 p3 p7 p8;p7 p8 p5 p6;p7 p6 p2 p3;p6 p5 p1 p2;p8 p5 p1 p4];

            p=fill3(A1(1,:),A1(2,:),A1(3,:),'--w');
            p.FaceAlpha = 0.3;
            p=fill3(A1(4,:),A1(5,:),A1(6,:),'--w');
            p.FaceAlpha = 0.3;
            p=fill3(A1(7,:),A1(8,:),A1(9,:),'--w');
            p.FaceAlpha = 0.3;
            p=fill3(A1(10,:),A1(11,:),A1(12,:),'--w');
            p.FaceAlpha = 0.3;
            p=fill3(A1(13,:),A1(14,:),A1(15,:),'--w');
            p.FaceAlpha = 0.3;
            p=fill3(A1(16,:),A1(17,:),A1(18,:),'--w');
            p.FaceAlpha = 0.3;

            hold off
        end

        % Button pushed function: ShowObjectPointCloudButton
        function ShowObjectPointCloudButtonPushed(app, event)
            %% GLOBALS
            global ptcloudB
            global pclimpa

             % ATIVAR O BOTAO PARA OBTER NUVEM COMPLETA, DEPOIS DO BOTÃO PARA OBTER AS STREAMS SER CLICKADO
            if app.ShowObjectPointCloudButton.Enable
                set(app.ShowContoursButton,'Enable','on')
            end

            % MUDAR O NOME DO BOTAO DEPOIS DESTE SER CLICKADO
            if app.ShowObjectPointCloudButton.Enable
                app.ShowObjectPointCloudButton.Text = "Update Object Point Cloud";
            end

            %% FECHAR JANELA ABERTA
            close(figure(1))

            %% REMOVER O PLANO DO CHAO
            % SET THE MAX POINT TO PLABE DISTANCE FOR PLANE FITTING
            maxDistance = 0.005;     % (m)

            % SET THE NORMAL VECTOR OF THE PLANE
            referenceVector = [0,1,0];

            % DETECT THE FIRST PLANE AND EXTRACT IT FROM THE POINT CLOUD
            [~,~,outlierIndices] = pcfitplane(ptcloudB,maxDistance,referenceVector);
            remainPtCloud = select(ptcloudB,outlierIndices);

            % REMOVER O BARULHO DA NUVEM DE PONTOS (ELIMINAR "IMPUREZAS")
            pclimpa = pcdenoise(remainPtCloud,"NumNeighbors",100);

            % MOSTRAR A NUVEM DE PONTOS LIMPA
            figure
            pcshow(pclimpa,"VerticalAxis","Y",VerticalAxisDir="Down")
            title('Object Cloud Point')
            xlabel('X(m)')
            ylabel('Y(m)')
            zlabel('Z(m)')
        end

        % Button pushed function: ShowContoursButton
        function ShowContoursButtonPushed(app, event)
            %% GLOBALS
            global pclimpa
            global RGBFrameFlipped
            global ptCloudRot
            
            %% FECHAR JANELA ABERTA
            close(figure(1))

            %% CONTORNOS DO OBJETO
            indices1=0;
            for i=1:size(pclimpa.Location(:,1))
                indices1= [indices1 find(ptCloudRot.Location(:,:,1)==pclimpa.Location(i,1) & ptCloudRot.Location(:,:,2)==pclimpa.Location(i,2) & ptCloudRot.Location(:,:,3)==pclimpa.Location(i,3))];
            end

            % LINHAS E COLUNAS DA MATRIZ DO OBJETO SELECIONADO
            [row,col] = ind2sub([480 640],indices1(2:end));

            % CONVERTER IMAGEM RGB EM IMAGEM DO MESMO SIZE DE PRETOS
            BlackRGB=zeros(size(RGBFrameFlipped));

            % OS PONTOS DO OBJETO COINCIDENTES COM A IMAGEM RGB SÃO CONVERTIDOS A BRANCO
            for i=1:size(col,2)
                BlackRGB(row(i),col(i),:)=1;
            end

            % BINARIZAR A IMAGEM PRETOS
            bi = imbinarize(im2gray(BlackRGB));

            % RETIRAR O PERIMETRO DOS PONTOS A BRANCO DA IMAGEM
            p=bwperim(bi);

            % ENCONTRAR OS LIMITES DO OBJETO
            rowmax = max(max(row))+10;
            rowmin = min(min(row))-10;
            colmax = max(max(col))+10;
            colmin = min(min(col))-10;

            % FRAME RGB RECORTADO PARA ELIMINAR PERTURBAÇÕES NO FUNDO
            RGBCropped = p(rowmin:rowmax,colmin:colmax,:);

            % MOSTRAR IMAGEM DO OBJETO RECORTADO
            imshow(RGBCropped,'Parent',app.UIAxesObjectContours)
            pbaspect(app.UIAxesObjectContours,[640,480,2]);
        end

        % Button pushed function: ViewFullPointCloudButton
        function ViewFullPointCloudButtonPushed(app, event)
            %% GLOBALS
            global ptCloudRot

            % MOSTRAR APENAS A NUVEM DE PONTOS SEM A ALTERAR
            figure
            pcshow(ptCloudRot,"VerticalAxis","Y",VerticalAxisDir="Down");
            title('Full Point Cloud')
            xlabel('X(m)')
            ylabel('Y(m)')
            zlabel('Z(m)')
        end

        % Button pushed function: SelectROIButton
        function SelectROIButtonPushed(app, event)
            %% GLOBALS
            global ptCloudRot
            global RGBFrameFlipped
            global DEPTHFrameFlipped
            global ptcloudB
           
             %% REMOVER O PLANO DO CHAO
            % SET THE MAX POINT TO PLABE DISTANCE FOR PLANE FITTING
            maxDistance_ROI = 0.005;     % (m)

            % SET THE NORMAL VECTOR OF THE PLANE
            referenceVector_ROI = [0,1,0];

            % DETECT THE FIRST PLANE AND EXTRACT IT FROM THE POINT CLOUD
            [~,~,outlierIndices_ROI] = pcfitplane(ptcloudB,maxDistance_ROI,referenceVector_ROI);
            remainPtCloud_ROI = select(ptcloudB,outlierIndices_ROI);

            % REMOVER O BARULHO DA NUVEM DE PONTOS (ELIMINAR "IMPUREZAS")
            pclimpa_ROI = pcdenoise(remainPtCloud_ROI,"NumNeighbors",100);

          
            indicescor_ROI=0;
            for i=1:size(pclimpa_ROI.Location(:,1))
                indicescor_ROI= [indicescor_ROI find(ptCloudRot.Location(:,:,1)==pclimpa_ROI.Location(i,1) & ptCloudRot.Location(:,:,2)==pclimpa_ROI.Location(i,2) & ptCloudRot.Location(:,:,3)==pclimpa_ROI.Location(i,3))];
            end

            % LINHAS E COLUNAS DA MATRIZ DO OBJETO SELECIONADO
            [row_ROI,col_ROI] = ind2sub([480 640],indicescor_ROI(2:end));

            % criarIMAGEM preta
            Black_ROI=zeros(size(RGBFrameFlipped));

            for i=1:size(col_ROI,2)
                Black_ROI(row_ROI(i),col_ROI(i),:)=1;
            end

            % mascara usada para ir buscar as partes coincidentes
            RGBFrameFlipped(Black_ROI==0)=0;
            % guardar com um novo nome as variaveis
            f_p_b_c_ROI=RGBFrameFlipped;

            figure
            imshow(f_p_b_c_ROI)


            h1_ROI = imrect;
            position1_ROI = wait(h1_ROI);

            croppedRGB = imcrop(f_p_b_c_ROI, position1_ROI);

%             figure;
%             hold on
%             subplot(1,2,1)
%             imshow(croppedRGB)
%             title('RGB Image cropped using ROI')

            position2 = position1_ROI;            
            croppedDEPTH =  imcrop(DEPTHFrameFlipped, position2);

%             subplot(1,2,2)
%             imshow(croppedDEPTH,[])
%             title('DEPTH Image cropped using ROI')
%             hold off

            profmax=1700;
            [pcloud, ~] = depthToCloud(croppedDEPTH,position1_ROI,profmax);


            figure
            pcshow(pcloud,"VerticalAxis","Y",VerticalAxisDir="Down")
            title('Object Cloud Point')
            xlabel('X(m)')
            ylabel('Y(m)')
            zlabel('Z(m)')
            
        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 1162 671];
            app.UIFigure.Name = 'MATLAB App';

            % Create VIDEOSTREAMSPanel
            app.VIDEOSTREAMSPanel = uipanel(app.UIFigure);
            app.VIDEOSTREAMSPanel.Title = 'VIDEO STREAMS';
            app.VIDEOSTREAMSPanel.Position = [21 53 354 605];

            % Create UIAxesRGBStream
            app.UIAxesRGBStream = uiaxes(app.VIDEOSTREAMSPanel);
            app.UIAxesRGBStream.Box = 'on';
            app.UIAxesRGBStream.Position = [21 378 312 185];

            % Create UIAxesDEPTHStream
            app.UIAxesDEPTHStream = uiaxes(app.VIDEOSTREAMSPanel);
            app.UIAxesDEPTHStream.Box = 'on';
            app.UIAxesDEPTHStream.Position = [21 138 313 185];

            % Create StartStreamsButton
            app.StartStreamsButton = uibutton(app.VIDEOSTREAMSPanel, 'push');
            app.StartStreamsButton.ButtonPushedFcn = createCallbackFcn(app, @StartStreamsButtonPushed, true);
            app.StartStreamsButton.Position = [128 68 100 22];
            app.StartStreamsButton.Text = 'Start Streams';

            % Create RGBVideoStreamLabel
            app.RGBVideoStreamLabel = uilabel(app.VIDEOSTREAMSPanel);
            app.RGBVideoStreamLabel.Position = [124 554 107 22];
            app.RGBVideoStreamLabel.Text = 'RGB Video Stream';

            % Create DepthVideoStreamLabel
            app.DepthVideoStreamLabel = uilabel(app.VIDEOSTREAMSPanel);
            app.DepthVideoStreamLabel.Position = [121 314 113 22];
            app.DepthVideoStreamLabel.Text = 'Depth Video Stream';

            % Create ExitButton
            app.ExitButton = uibutton(app.UIFigure, 'push');
            app.ExitButton.ButtonPushedFcn = createCallbackFcn(app, @ExitButtonPushed, true);
            app.ExitButton.Position = [1038 10 100 22];
            app.ExitButton.Text = 'Exit';

            % Create OBJECTDETECTIONPanel
            app.OBJECTDETECTIONPanel = uipanel(app.UIFigure);
            app.OBJECTDETECTIONPanel.Title = 'OBJECT DETECTION';
            app.OBJECTDETECTIONPanel.Position = [398 53 740 604];

            % Create GetFullPointCloudButton
            app.GetFullPointCloudButton = uibutton(app.OBJECTDETECTIONPanel, 'push');
            app.GetFullPointCloudButton.ButtonPushedFcn = createCallbackFcn(app, @GetFullPointCloudButtonPushed, true);
            app.GetFullPointCloudButton.Position = [18 544 300 32];
            app.GetFullPointCloudButton.Text = 'Get Full Point Cloud';

            % Create ViewFullPointCloudButton
            app.ViewFullPointCloudButton = uibutton(app.OBJECTDETECTIONPanel, 'push');
            app.ViewFullPointCloudButton.ButtonPushedFcn = createCallbackFcn(app, @ViewFullPointCloudButtonPushed, true);
            app.ViewFullPointCloudButton.Position = [415 544 300 32];
            app.ViewFullPointCloudButton.Text = 'View Full Point Cloud';

            % Create TargetAreaPanel
            app.TargetAreaPanel = uipanel(app.OBJECTDETECTIONPanel);
            app.TargetAreaPanel.TitlePosition = 'centertop';
            app.TargetAreaPanel.Title = 'Target Area';
            app.TargetAreaPanel.Position = [18 289 697 244];

            % Create EditField_Xmin
            app.EditField_Xmin = uieditfield(app.TargetAreaPanel, 'numeric');
            app.EditField_Xmin.HorizontalAlignment = 'left';
            app.EditField_Xmin.Position = [41 158 52 22];
            app.EditField_Xmin.Value = -0.5;

            % Create EditField_Ymin
            app.EditField_Ymin = uieditfield(app.TargetAreaPanel, 'numeric');
            app.EditField_Ymin.HorizontalAlignment = 'left';
            app.EditField_Ymin.Position = [42 126 52 22];

            % Create EditField_Ymax
            app.EditField_Ymax = uieditfield(app.TargetAreaPanel, 'numeric');
            app.EditField_Ymax.Position = [132 126 52 22];
            app.EditField_Ymax.Value = 0.4;

            % Create EditField_Xmax
            app.EditField_Xmax = uieditfield(app.TargetAreaPanel, 'numeric');
            app.EditField_Xmax.Position = [132 158 52 22];
            app.EditField_Xmax.Value = 0.5;

            % Create EditField_Zmin
            app.EditField_Zmin = uieditfield(app.TargetAreaPanel, 'numeric');
            app.EditField_Zmin.HorizontalAlignment = 'left';
            app.EditField_Zmin.Position = [42 93 52 22];
            app.EditField_Zmin.Value = 1.2;

            % Create EditField_Zmax
            app.EditField_Zmax = uieditfield(app.TargetAreaPanel, 'numeric');
            app.EditField_Zmax.Position = [132 92 52 22];
            app.EditField_Zmax.Value = 1.7;

            % Create XLabel
            app.XLabel = uilabel(app.TargetAreaPanel);
            app.XLabel.HorizontalAlignment = 'center';
            app.XLabel.Position = [98 158 28 22];
            app.XLabel.Text = '<X<';

            % Create YLabel
            app.YLabel = uilabel(app.TargetAreaPanel);
            app.YLabel.HorizontalAlignment = 'center';
            app.YLabel.Position = [98 126 28 22];
            app.YLabel.Text = '<Y<';

            % Create ZLabel
            app.ZLabel = uilabel(app.TargetAreaPanel);
            app.ZLabel.HorizontalAlignment = 'center';
            app.ZLabel.Position = [98 93 27 22];
            app.ZLabel.Text = '<Z<';

            % Create GetTargetAreaButton
            app.GetTargetAreaButton = uibutton(app.TargetAreaPanel, 'push');
            app.GetTargetAreaButton.ButtonPushedFcn = createCallbackFcn(app, @GetTargetAreaButtonPushed, true);
            app.GetTargetAreaButton.Position = [52 46 119 22];
            app.GetTargetAreaButton.Text = 'Get Target Area';

            % Create Image
            app.Image = uiimage(app.TargetAreaPanel);
            app.Image.Position = [236 1 442 235];
            app.Image.ImageSource = 'App Designer Kinect Diagram.png';

            % Create REGIONOFINTERESTPanel
            app.REGIONOFINTERESTPanel = uipanel(app.OBJECTDETECTIONPanel);
            app.REGIONOFINTERESTPanel.Title = 'REGION OF INTEREST';
            app.REGIONOFINTERESTPanel.Position = [18 15 338 257];

            % Create TabGroup
            app.TabGroup = uitabgroup(app.REGIONOFINTERESTPanel);
            app.TabGroup.Position = [0 123 338 117];

            % Create FullObjectPointCloudTab
            app.FullObjectPointCloudTab = uitab(app.TabGroup);
            app.FullObjectPointCloudTab.Title = 'Full Object Point Cloud';

            % Create ShowObjectPointCloudButton
            app.ShowObjectPointCloudButton = uibutton(app.FullObjectPointCloudTab, 'push');
            app.ShowObjectPointCloudButton.ButtonPushedFcn = createCallbackFcn(app, @ShowObjectPointCloudButtonPushed, true);
            app.ShowObjectPointCloudButton.Position = [86 36 160 22];
            app.ShowObjectPointCloudButton.Text = 'Show Object Point Cloud';

            % Create ROITab
            app.ROITab = uitab(app.TabGroup);
            app.ROITab.Title = 'ROI';

            % Create SelectROIButton
            app.SelectROIButton = uibutton(app.ROITab, 'push');
            app.SelectROIButton.ButtonPushedFcn = createCallbackFcn(app, @SelectROIButtonPushed, true);
            app.SelectROIButton.Position = [42 57 100 22];
            app.SelectROIButton.Text = 'Select ROI';

            % Create DeleteROIButton
            app.DeleteROIButton = uibutton(app.ROITab, 'push');
            app.DeleteROIButton.Position = [200 57 100 22];
            app.DeleteROIButton.Text = 'Delete ROI';

            % Create ShowROIPointCloudButton
            app.ShowROIPointCloudButton = uibutton(app.ROITab, 'push');
            app.ShowROIPointCloudButton.Position = [101 20 136 22];
            app.ShowROIPointCloudButton.Text = 'Show ROI Point Cloud';

            % Create SelectRegionofInterestforContoursPanel
            app.SelectRegionofInterestforContoursPanel = uipanel(app.REGIONOFINTERESTPanel);
            app.SelectRegionofInterestforContoursPanel.TitlePosition = 'centertop';
            app.SelectRegionofInterestforContoursPanel.Title = 'Select Region of Interest for Contours';
            app.SelectRegionofInterestforContoursPanel.Position = [0 0 338 125];

            % Create FullObjectCheckBox
            app.FullObjectCheckBox = uicheckbox(app.SelectRegionofInterestforContoursPanel);
            app.FullObjectCheckBox.Text = 'Full Object';
            app.FullObjectCheckBox.Position = [51 52 79 22];

            % Create SelectedROICheckBox
            app.SelectedROICheckBox = uicheckbox(app.SelectRegionofInterestforContoursPanel);
            app.SelectedROICheckBox.Text = 'Selected ROI';
            app.SelectedROICheckBox.Position = [199 52 93 22];

            % Create CONTOURSPanel
            app.CONTOURSPanel = uipanel(app.OBJECTDETECTIONPanel);
            app.CONTOURSPanel.Title = 'CONTOURS';
            app.CONTOURSPanel.Position = [378 15 337 257];

            % Create UIAxesObjectContours
            app.UIAxesObjectContours = uiaxes(app.CONTOURSPanel);
            app.UIAxesObjectContours.Box = 'on';
            app.UIAxesObjectContours.Position = [18 47 274 160];

            % Create ShowContoursButton
            app.ShowContoursButton = uibutton(app.CONTOURSPanel, 'push');
            app.ShowContoursButton.ButtonPushedFcn = createCallbackFcn(app, @ShowContoursButtonPushed, true);
            app.ShowContoursButton.Position = [110 23 100 22];
            app.ShowContoursButton.Text = 'Show Contours';

            % 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_FINAL_ChaoRemov_Target_ROI_2

            % Create UIFigure and components
            createComponents(app)

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

            % Execute the startup function
            runStartupFcn(app, @startupFcn)

            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