classdef App_AQUISICAO_IMAGEM_testesCopia < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        UIFigure                        matlab.ui.Figure
        TabGroup                        matlab.ui.container.TabGroup
        IMAGEACQUISITIONTab             matlab.ui.container.Tab
        DropDownSelectROIForContour     matlab.ui.control.DropDown
        Label                           matlab.ui.control.Label
        StructuringElementRadiusSlider  matlab.ui.control.Slider
        StructuringElementRadiusSliderLabel  matlab.ui.control.Label
        DepthVideoStreamLabel           matlab.ui.control.Label
        RGBVideoStreamLabel             matlab.ui.control.Label
        UIAxesObjectContours            matlab.ui.control.UIAxes
        UIAxesDEPTHStream               matlab.ui.control.UIAxes
        UIAxesRGBStream                 matlab.ui.control.UIAxes
        StartStreamsButton              matlab.ui.control.Button
        GetFullPointCloudButton         matlab.ui.control.Button
        ViewFullPointCloudButton        matlab.ui.control.Button
        Image                           matlab.ui.control.Image
        EditField_Xmin                  matlab.ui.control.NumericEditField
        EditField_Ymin                  matlab.ui.control.NumericEditField
        EditField_Ymax                  matlab.ui.control.NumericEditField
        EditField_Xmax                  matlab.ui.control.NumericEditField
        EditField_Zmin                  matlab.ui.control.NumericEditField
        EditField_Zmax                  matlab.ui.control.NumericEditField
        XLabel                          matlab.ui.control.Label
        YLabel                          matlab.ui.control.Label
        ZLabel                          matlab.ui.control.Label
        ROICoordinatesLabel             matlab.ui.control.Label
        GetTargetAreaButton             matlab.ui.control.Button
        SelectFullObjectButton          matlab.ui.control.Button
        SelectROIButton                 matlab.ui.control.Button
        ShowContoursButton              matlab.ui.control.Button
        ExitButton                      matlab.ui.control.Button
        POINTCLOUDPROCESSINGTab         matlab.ui.container.Tab
        ExitButton_2                    matlab.ui.control.Button
        PointCloudDownsamplingPanel     matlab.ui.container.Panel
        Button3                         matlab.ui.control.Button
        Button2                         matlab.ui.control.Button
        Button                          matlab.ui.control.Button
        DensifyCloudButton              matlab.ui.control.Button
        RemovePointsButton              matlab.ui.control.Button
        CropButton                      matlab.ui.control.Button
        GridBoxFilterSizemmSpinner      matlab.ui.control.Spinner
        GridBoxFilterSizemmSpinnerLabel  matlab.ui.control.Label
        SelectRegionofInterestforPointCloudProcessingPanel  matlab.ui.container.Panel
        DropDownSelectROIForPCProcessing  matlab.ui.control.DropDown
        Label_2                         matlab.ui.control.Label
        UIAxesPCDownSampling            matlab.ui.control.UIAxes
    end

    
    properties (Access = public)
            DEPTHDisp
            RGBDisp
            imgRGB
            RGBFrameFlipped
            DEPTHFrameFlipped
            ptCloudRot
            PointCloudBrowser
            ptcloudB
            pclimpa
            ptcloudB3
            ImgEdge
    end
      

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

        % Code that executes after component creation
        function startupFcn(app)
            % FAZER RESET À CAMARA
            imaqreset

            % DESATIVAR TODOS OS BOTÕES AO INICIAR A APP
            set(app.GetFullPointCloudButton,'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.SelectFullObjectButton,'Enable','off')
            set(app.ShowContoursButton,'Enable','off')
            set(app.SelectROIButton,'Enable','off')
            set(app.DropDownSelectROIForContour,'Enable','off')
            set(app.ViewFullPointCloudButton,'Enable','off')
        end

        % Button pushed function: StartStreamsButton
        function StartStreamsButtonPushed(app, event)
            %% 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 further steps.','Depth camera stabilization.','Icon','warning')
            end

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

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

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

            % RESOLUÇAO DA STREAM VIDEO RGB
            app.UIAxesRGBStream.XLim = [0,640];
            app.UIAxesRGBStream.YLim = [0,480];
            pbaspect(app.UIAxesRGBStream,[640,480,1]);

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

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

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

            % RESOLUÇAO DA STREAM VIDEO DEPTH
            app.UIAxesDEPTHStream.XLim = [0,640];
            app.UIAxesDEPTHStream.YLim = [0,480];
            pbaspect(app.UIAxesDEPTHStream,[640,480,1]);
            colormap(app.UIAxesDEPTHStream,'jet')
%             whitebg(gcf,'white')
%             set(gcf,'Color','w')

        end

        % Button pushed function: GetFullPointCloudButton
        function GetFullPointCloudButtonPushed(app, event)
            % 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(gcf)

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

            ptCloudOriginal = pcfromkinect(app.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
            app.ptCloudRot = pctransform(ptCloudOriginal,tform);

            % MOSTAR NUVEM DE PONTOS
            app.PointCloudBrowser = figure("Name",'Point Cloud Browser','NumberTitle','off');
            pcshow(app.ptCloudRot,"VerticalAxis","Y",VerticalAxisDir="Down");
            title('Full Point Cloud')
            xlabel('X(m)')
            ylabel('Y(m)')
            zlabel('Z(m)')
            whitebg(gcf,'white')
            set(gcf,'Color','w')

        end

        % Button pushed function: ViewFullPointCloudButton
        function ViewFullPointCloudButtonPushed(app, event)
            % MOSTAR NUVEM DE PONTOS
            figure("Name",'Point Cloud Browser','NumberTitle','off')
            pcshow(app.ptCloudRot,"VerticalAxis","Y",VerticalAxisDir="Down");
            title('Full Point Cloud')
            xlabel('X(m)')
            ylabel('Y(m)')
            zlabel('Z(m)')
            whitebg(gcf,'white')
            set(gcf,'Color','w')

        end

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

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

            %% DEFINIR UMA ROI CUBICA PARA ASSUMIR A TARGET AREA
            % ESPECIFICAR O STEP SIZE
            stepSize = 100;

            % AMOSTRA A NUVEM DE PONTOS DE ENTRADA E ARMAZENA AS COORDENADAS DE PONTOS COMO UM OBJETO DE NUVEM DE PONTOS
            indices = 1:stepSize:app.ptCloudRot.Count;
            tempPtCloud = select(app.ptCloudRot,indices);

            % REMOVER OS PONTOS INVALIDOS DENTRO DA AMOSTRA ANTERIOR
            [tempPtCloud,validIndices] = removeInvalidPoints(tempPtCloud);

            % OBTER AS COORDENADAS DE LOCALIZAÇAO 3D DOS PONTOS DA NUVEM DE PONTOS
            worldPoints = tempPtCloud.Location;

            % CONVERTER E ENCONTRAR AS COORDENADAS DOS PONTOS 2D CORRESPONDENTES AOS PONTOS 3D DA NUVEM
            [Y,X] = ind2sub([size(app.ptCloudRot.Location,1),size(app.ptCloudRot.Location,2)],indices);
            imagePoints = [X(validIndices)' Y(validIndices)'];

            % ESTIMATIVA DA MATRIZ DE PROJEÇAO DA CAMARA A PARTIR DA IMAGEM E DAS COORDENADAS DOS PONTOS DE LOCALIZAÇAO 3D
            camMatrix = estimateCameraMatrix(imagePoints,worldPoints);

            % DEFINIR A ROI CUBICA PARA A TARGET AREA
            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];

            % ENCONTRAR OS INDICES DOS PONTOS DA NUVEM QUE ESTAO DENTRO DA ROI CUBICA
            indices = findPointsInROI(app.ptCloudRot,roi,camMatrix);

            % SELECIONAR OS PONTOS DA NUVEM QUE SE ENCONTRAM DENTRO DA ROI
            app.ptcloudB = select(app.ptCloudRot,indices);

            % MOSTRAR A NUVEM DE PONTOS COM A TARGER AREA
            figure(app.PointCloudBrowser);
            pcshow(app.ptCloudRot,"VerticalAxis","Y",VerticalAxisDir="Down")
            hold on
            pcshow(app.ptcloudB.Location,'r',"VerticalAxis","Y",VerticalAxisDir="Down")
            title('Full Point Cloud with Target Area')
            xlabel('X(m)')
            ylabel('Y(m)')
            zlabel('Z(m)')
            whitebg(gcf,'white')
            set(gcf,'Color','w')

            % DEFINIÇÃO DOS PONTOS DOS VERTICES DO CUBO DA ROI
            p1 = [roi(1) roi(4) roi(6)]';
            p2 = [roi(1) roi(4) roi(5)]';
            p3 = [roi(2) roi(4) roi(5)]';
            p4 = [roi(2) roi(4) roi(6)]';
            p5 = [roi(1) roi(3) roi(6)]';
            p6 = [roi(1) roi(3) roi(5)]';
            p7 = [roi(2) roi(3) roi(5)]';
            p8 = [roi(2) roi(3) roi(6)]';

            % DEFINIR AS FACES DO CUBO ATRAVES DOS VERTICES ANTERIORES
            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];

            % CORES DAS FACES
            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: SelectFullObjectButton
        function SelectFullObjectButtonPushed(app, event)
            % ATIVAR O BOTAO PARA OBTER NUVEM COMPLETA, DEPOIS DO BOTÃO PARA OBTER AS STREAMS SER CLICKADO
            if app.SelectFullObjectButton.Enable
                set(app.ShowContoursButton,'Enable','on')
                set(app.SelectROIButton,'Enable','on')
                set(app.DropDownSelectROIForContour,'Enable','on')
            end

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

            %% REMOVER O PLANO DO CHAO
            % DEFINIR A DISTANCIA MAXIMA PONTO-PLANO PARA A MONTAGEM DO PLANO
            maxDistance = 0.0005;     % (m)

            % DEFINIR O VETOR NORMAL AO PLANO A DEFINIR (NESTE CASO VETOR PREPENDICULAR AO PLANO Y)
            referenceVector = [0,1,0];

            % DETETAR O PLANO E EXTRAI-LO DA NUVEM DE PONTOS
            [~,~,outlierIndices] = pcfitplane(app.ptcloudB,maxDistance,referenceVector);
            remainPtCloud = select(app.ptcloudB,outlierIndices);

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

            % MOSTRAR A NUVEM DE PONTOS LIMPA E SEM O PLANO DO CHAO
            figure("Name",'Object Cloud Viewer','NumberTitle','off');
            pcshow(app.pclimpa,"VerticalAxis","Y",VerticalAxisDir="Down")
            title('Object Cloud Point')
            xlabel('X(m)')
            ylabel('Y(m)')
            zlabel('Z(m)')
            whitebg(gcf,'white')
            set(gcf,'Color','w')
        end

        % Button pushed function: SelectROIButton
        function SelectROIButtonPushed(app, event)
            % AVISAR O USER QUE É NECESSÁRIO FAZER DOUBLE CLICK PARA ESCOLHER A ROI
            if app.SelectROIButton.Enable
                uialert(app.UIFigure,'Draw a rectangle to mark the Region of Interest. Double click inside the rectangle to select the ROI.','Info','Icon','info')
            end

            % CONVERTER MATRIX FULL EM MATRIX DE 3xCOLUNAS COM AS COORDENADAS X Y E Z RESPECTIVAMENTE
            NovaMatrizNuvemTotal = [reshape(app.ptCloudRot.Location(:,:,1),[],1) reshape(app.ptCloudRot.Location(:,:,2),[],1) reshape(app.ptCloudRot.Location(:,:,3),[],1)];

            % COMPARAR MATRIZ FULL E MATRIX DA TARGET AREA E RETIRAR OS INDICES DOS PONTOS DO SEU INTERIOR
            [RowNova01,~] = find(NovaMatrizNuvemTotal(:,1)<app.EditField_Xmax.Value & NovaMatrizNuvemTotal(:,1)>app.EditField_Xmin.Value & NovaMatrizNuvemTotal(:,2)<app.EditField_Ymax.Value & NovaMatrizNuvemTotal(:,2)>app.EditField_Ymin.Value & NovaMatrizNuvemTotal(:,3)>app.EditField_Zmin.Value & NovaMatrizNuvemTotal(:,3)<app.EditField_Zmax.Value);

            % CONVERTER OS INDICES EM LINHA COLUNA DENTRO DA RESOLUÇAO DO FRAME
            [ROWNOVA1,COLNOVA1] = ind2sub([480 640],RowNova01);

            % ENCONTRAR OS MAX E MIN DE COLUNA E LINHA PARA FORMATAR IMAGEM
            maxrow3 = max(ROWNOVA1);
            minrow3 = min(ROWNOVA1);
            maxcol3 = max(COLNOVA1);
            mincol3 = min(COLNOVA1);

            % RETIRAR UM FRAME DA CAMARA RGB E DEPTH
            DEPTHFrameFlipped2 = flip(getsnapshot(app.DEPTHDisp),2);
            RGBFrameFlipped2 = flip(getsnapshot(app.RGBDisp),2);

            % "RECORTAR" IMAGEM RGB E DEPTH PELOS MAX/MIN COLUNA/LINHA
            RGB_ROI = RGBFrameFlipped2(minrow3:maxrow3,mincol3:maxcol3,:);
%             DEPTH_ROI = DEPTHFrameFlipped2((minrow3:maxrow3)-10,(mincol3:maxcol3)+15,:);

            % ABRIR PLOT PARA CRIAR A ZONA ROI
            figroi = figure("Name",'Region of Interest Selection','NumberTitle','off');
            imshow(RGB_ROI)

            h1 = drawrectangle;

            % ESPERAR PELO USER DEFINIR A ROI PARA SE OBTER A SUA POSIÇAO
            wait(h1)

            %% RETIRAR DO OBJETO O INTERIOR DA ROI ANTERIORMENTE DEFINIDA
            % ESPECIFICAR O STEP SIZE
            stepSize3 = 100;

            % AMOSTRA A NUVEM DE PONTOS DE ENTRADA E ARMAZENA AS COORDENADAS DE PONTOS COMO UM OBJETO DE NUVEM DE PONTOS
            indices3 = 1:stepSize3:app.ptCloudRot.Count;
            tempPtCloud3 = select(app.ptCloudRot,indices3);

            % REMOVER OS PONTOS INVALIDOS DENTRO DA AMOSTRA ANTERIOR
            [tempPtCloud3,validIndices3] = removeInvalidPoints(tempPtCloud3);

            % OBTER AS COORDENADAS DE LOCALIZAÇAO 3D DOS PONTOS DA NUVEM DE PONTOS
            worldPoints3 = tempPtCloud3.Location;

            % CONVERTER E ENCONTRAR AS COORDENADAS DOS PONTOS 2D CORRESPONDENTES AOS PONTOS 3D DA NUVEM
            [Y,X] = ind2sub([size(app.ptCloudRot.Location,1),size(app.ptCloudRot.Location,2)],indices3);
            imagePoints3 = [X(validIndices3)' Y(validIndices3)'];

            % ESTIMATIVA DA MATRIZ DE PROJEÇAO DA CAMARA A PARTIR DA IMAGEM E DAS COORDENADAS DOS PONTOS DE LOCALIZAÇAO 3D
            camMatrix3 = estimateCameraMatrix(imagePoints3,worldPoints3);

            % DEFINIR A ROI CUBICA PARA A TARGET AREA
            distbetween_x = norm(max(app.pclimpa.Location(:,1))-min(app.pclimpa.Location(:,1)));
            distbetween_y = norm(max(app.pclimpa.Location(:,2))-min(app.pclimpa.Location(:,2)));

            Vertice1xmin = floor(h1.Vertices(1));
            Vertice1xmax = floor(h1.Vertices(4));
            Vertice1ymin = floor(h1.Vertices(5));
            Vertice1ymax = floor(h1.Vertices(7));

            if Vertice1xmin == 0
                Vertice1xmin = 1;
            end

            if Vertice1xmax == 0
                Vertice1xmax = 1;
            end

            if Vertice1ymin == 0
                Vertice1ymin = 1;
            end

            if Vertice1ymax == 0
                Vertice1ymax = 1;
            end

            P_ROI_Xmin = min(min(app.pclimpa.Location(:,1)))+((Vertice1xmin)*distbetween_x)/(size(RGB_ROI,2));
            P_ROI_Xmax = min(min(app.pclimpa.Location(:,1)))+((Vertice1xmax)*distbetween_x)/(size(RGB_ROI,2));
            P_ROI_Ymax = min(min(app.pclimpa.Location(:,2)))+((Vertice1ymax)*distbetween_y)/(size(RGB_ROI,1));
            P_ROI_Ymin = min(min(app.pclimpa.Location(:,2)))+((Vertice1ymin)*distbetween_y)/(size(RGB_ROI,1));

            roi3 = [P_ROI_Xmin P_ROI_Xmax P_ROI_Ymin P_ROI_Ymax app.EditField_Zmin.Value app.EditField_Zmax.Value];

            % ENCONTRAR OS INDICES DOS PONTOS DA NUVEM QUE ESTAO DENTRO DA ROI CUBICA
            indices3 = findPointsInROI(app.ptCloudRot,roi3,camMatrix3);

            % SELECIONAR OS PONTOS DA NUVEM QUE SE ENCONTRAM DENTRO DA ROI
            app.ptcloudB3 = select(app.ptCloudRot,indices3);

            % REMOVER BARULHO DA NUVEM ROI
            app.ptcloudB3 = pcdenoise(app.ptcloudB3,"NumNeighbors",100);

            % FECHAR A JANELA DA ROI DEFINIDA
            close(figure(figroi))
            close()

            % MOSTRAR A NUVEM DE PONTOS DA ROI
            figure("Name",'ROI Point Cloud Viewer','NumberTitle','off')
            pcshow(app.ptcloudB3,"VerticalAxis","Y",VerticalAxisDir="Down")
            title('ROI Point Cloud')
            xlabel('X(m)')
            ylabel('Y(m)')
            zlabel('Z(m)')
            whitebg(gcf,'white')
            set(gcf,'Color','w')

        end

        % Button pushed function: ShowContoursButton
        function ShowContoursButtonPushed(app, event)
            % LIMPAR O AXIS DOS CONTORNOS
            cla(app.UIAxesObjectContours,"reset")

            switch app.DropDownSelectROIForContour.Value
                case 'Full Object'

                    % DEFINIR O VALOR DO INICIAL DO SLIDER PARA 1
                    raio_strel = 1;

                    % EXTRAIR COORDENADAS X E Y DO OBJETO (RETIRAR Z)
                    xnuvem = app.pclimpa.Location(:,1);
                    ynuvem = app.pclimpa.Location(:,2);

                case 'ROI'
                    % DEFINIR O VALOR DO INICIAL DO SLIDER PARA 1
                    raio_strel = 5;

                    % EXTRAIR COORDENADAS X E Y DO OBJETO (RETIRAR Z)
                    xnuvem = app.ptcloudB3.Location(:,1);
                    ynuvem = app.ptcloudB3.Location(:,2);
            end

            % FAZER PLOT DOS PONTOS X E Y DO OBJETO E RODAR O PLOT
            plot(app.UIAxesObjectContours,xnuvem,ynuvem,'.k')
            set(app.UIAxesObjectContours,'ydir','reverse')
            axis(app.UIAxesObjectContours,'off')

            % RETIRAR FRAME DO PLOT ANTERIOR
            FramePlot = frame2im(getframe(app.UIAxesObjectContours));

            % BINARIZAR IMG E INVERTER COR
            ImgBin = imbinarize(im2gray(FramePlot));
            InverseImg = uint8(255) - im2uint8(ImgBin);

            % PREENCHER ESPAÇOS ABERTOS NO OBJETO
            raio_strel = round(app.StructuringElementRadiusSlider.Value);
            se = strel('disk',raio_strel);
            ImgClosed = imclose(InverseImg,se);

            % FAZER CONTORNOS DO OBJETO
            app.ImgEdge = edge(ImgClosed,"canny");

            % ENCONTRAR LINHAS E COLUNAS DOS PONTOS BRANCOS ( AKA CONTORNOS)
            [rowbw1,colbw1] = find(app.ImgEdge==1);

            % LIMITAR IMAGEM SEGUNDO OS CONTORNOS
            rowmax12 = max(rowbw1)+10;
            rowmin12 = min(rowbw1)-10;
            colmax12 = max(colbw1)+10;
            colmin12 = min(colbw1)-10;

            % NAO DEIXAR QUE A IMAGEM RECORTADA NAO ULTRAPASSE A RESOLUÇAO DA IMAGEM
            if rowmin12 < 0
                rowmin12 = 1;
            end

            if rowmax12 > size(app.ImgEdge,1)
                rowmax12 = size(app.ImgEdge,1);
            end

            if colmin12 < 0
                colmin12 = 1;
            end

            if colmax12 > size(app.ImgEdge,2)
                colmax12 = size(app.ImgEdge,2);
            end

            % RECORTAR E MOSTRAR IMAGEM DOS CONTORNOS
%           novaimagembw1 = ImgEdge(rowmin12:rowmax12,colmin12:colmax12,:);
%           imshow(novaimagembw1,'Parent',app.UIAxesObjectContours)
            imshow(app.ImgEdge,'Parent',app.UIAxesObjectContours)
            axis(app.UIAxesObjectContours,"equal")


        end

        % Button pushed function: ExitButton
        function ExitButtonPushed(app, event)
            % FECHAR APLICAÇAO E TODAS AS JANELAS ABERTAS
            app.delete
            close all
        end

        % Value changed function: DropDownSelectROIForPCProcessing
        function DropDownSelectROIForPCProcessingValueChanged(app, event)
            value = app.DropDownSelectROIForPCProcessing.Value;
            gridStep = app.GridBoxFilterSizemmSpinner.Value;

            switch value
                case 'Full Object'
                    ptGridAvgDownS = pcdownsample(app.pclimpa,'gridAverage',gridStep);
                    xnuvem = ptGridAvgDownS.Location(:,1);
                    ynuvem = ptGridAvgDownS.Location(:,2);
                    znuvem = ptGridAvgDownS.Location(:,3);

                    plot3(app.UIAxesPCDownSampling,xnuvem,znuvem,ynuvem,'k.')
                    set(app.UIAxesPCDownSampling,'zdir','reverse')
                    axis(app.UIAxesPCDownSampling,'equal')
                case 'ROI'
                    ptGridAvgDownS = pcdownsample(app.ptcloudB3,'gridAverage',gridStep);
                    xnuvem = ptGridAvgDownS.Location(:,1);
                    ynuvem = ptGridAvgDownS.Location(:,2);
                    znuvem = ptGridAvgDownS.Location(:,3);

                    plot3(app.UIAxesPCDownSampling,xnuvem,znuvem,ynuvem,'k.')
                    set(app.UIAxesPCDownSampling,'zdir','reverse')
                    axis(app.UIAxesPCDownSampling,'equal')
            end
        end

        % Value changing function: GridBoxFilterSizemmSpinner
        function GridBoxFilterSizemmSpinnerValueChanging(app, event)
            changingValue = event.Value;
            
            
        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 1091 713];
            app.UIFigure.Name = 'MATLAB App';
            app.UIFigure.Resize = 'off';

            % Create TabGroup
            app.TabGroup = uitabgroup(app.UIFigure);
            app.TabGroup.Position = [1 22 1072 692];

            % Create IMAGEACQUISITIONTab
            app.IMAGEACQUISITIONTab = uitab(app.TabGroup);
            app.IMAGEACQUISITIONTab.Title = 'IMAGE ACQUISITION';

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

            % Create ShowContoursButton
            app.ShowContoursButton = uibutton(app.IMAGEACQUISITIONTab, 'push');
            app.ShowContoursButton.ButtonPushedFcn = createCallbackFcn(app, @ShowContoursButtonPushed, true);
            app.ShowContoursButton.Position = [821 109 150 39];
            app.ShowContoursButton.Text = 'Show Contours';

            % Create SelectROIButton
            app.SelectROIButton = uibutton(app.IMAGEACQUISITIONTab, 'push');
            app.SelectROIButton.ButtonPushedFcn = createCallbackFcn(app, @SelectROIButtonPushed, true);
            app.SelectROIButton.Position = [562 316 110 39];
            app.SelectROIButton.Text = 'Select ROI';

            % Create SelectFullObjectButton
            app.SelectFullObjectButton = uibutton(app.IMAGEACQUISITIONTab, 'push');
            app.SelectFullObjectButton.ButtonPushedFcn = createCallbackFcn(app, @SelectFullObjectButtonPushed, true);
            app.SelectFullObjectButton.Position = [419 316 110 39];
            app.SelectFullObjectButton.Text = 'Select Full Object';

            % Create GetTargetAreaButton
            app.GetTargetAreaButton = uibutton(app.IMAGEACQUISITIONTab, 'push');
            app.GetTargetAreaButton.ButtonPushedFcn = createCallbackFcn(app, @GetTargetAreaButtonPushed, true);
            app.GetTargetAreaButton.Position = [404 417 119 39];
            app.GetTargetAreaButton.Text = 'Get Target Area';

            % Create ROICoordinatesLabel
            app.ROICoordinatesLabel = uilabel(app.IMAGEACQUISITIONTab);
            app.ROICoordinatesLabel.Position = [416 572 95 22];
            app.ROICoordinatesLabel.Text = 'ROI Coordinates';

            % Create ZLabel
            app.ZLabel = uilabel(app.IMAGEACQUISITIONTab);
            app.ZLabel.HorizontalAlignment = 'center';
            app.ZLabel.Position = [446 475 34 22];
            app.ZLabel.Text = '< Z <';

            % Create YLabel
            app.YLabel = uilabel(app.IMAGEACQUISITIONTab);
            app.YLabel.HorizontalAlignment = 'center';
            app.YLabel.Position = [446 508 34 22];
            app.YLabel.Text = '< Y <';

            % Create XLabel
            app.XLabel = uilabel(app.IMAGEACQUISITIONTab);
            app.XLabel.HorizontalAlignment = 'center';
            app.XLabel.Position = [446 540 34 22];
            app.XLabel.Text = '< X <';

            % Create EditField_Zmax
            app.EditField_Zmax = uieditfield(app.IMAGEACQUISITIONTab, 'numeric');
            app.EditField_Zmax.Position = [483 474 52 22];
            app.EditField_Zmax.Value = 1.7;

            % Create EditField_Zmin
            app.EditField_Zmin = uieditfield(app.IMAGEACQUISITIONTab, 'numeric');
            app.EditField_Zmin.HorizontalAlignment = 'left';
            app.EditField_Zmin.Position = [393 475 52 22];
            app.EditField_Zmin.Value = 1.2;

            % Create EditField_Xmax
            app.EditField_Xmax = uieditfield(app.IMAGEACQUISITIONTab, 'numeric');
            app.EditField_Xmax.Position = [483 540 52 22];
            app.EditField_Xmax.Value = 0.5;

            % Create EditField_Ymax
            app.EditField_Ymax = uieditfield(app.IMAGEACQUISITIONTab, 'numeric');
            app.EditField_Ymax.Position = [483 508 52 22];
            app.EditField_Ymax.Value = 0.4;

            % Create EditField_Ymin
            app.EditField_Ymin = uieditfield(app.IMAGEACQUISITIONTab, 'numeric');
            app.EditField_Ymin.HorizontalAlignment = 'left';
            app.EditField_Ymin.Position = [393 508 52 22];

            % Create EditField_Xmin
            app.EditField_Xmin = uieditfield(app.IMAGEACQUISITIONTab, 'numeric');
            app.EditField_Xmin.HorizontalAlignment = 'left';
            app.EditField_Xmin.Position = [392 540 52 22];
            app.EditField_Xmin.Value = -0.5;

            % Create Image
            app.Image = uiimage(app.IMAGEACQUISITIONTab);
            app.Image.Position = [595 381 442 235];
            app.Image.ImageSource = 'App Designer Kinect Diagram.png';

            % Create ViewFullPointCloudButton
            app.ViewFullPointCloudButton = uibutton(app.IMAGEACQUISITIONTab, 'push');
            app.ViewFullPointCloudButton.ButtonPushedFcn = createCallbackFcn(app, @ViewFullPointCloudButtonPushed, true);
            app.ViewFullPointCloudButton.Position = [551 615 130 32];
            app.ViewFullPointCloudButton.Text = 'View Full Point Cloud';

            % Create GetFullPointCloudButton
            app.GetFullPointCloudButton = uibutton(app.IMAGEACQUISITIONTab, 'push');
            app.GetFullPointCloudButton.ButtonPushedFcn = createCallbackFcn(app, @GetFullPointCloudButtonPushed, true);
            app.GetFullPointCloudButton.Position = [398 615 130 32];
            app.GetFullPointCloudButton.Text = 'Get Full Point Cloud';

            % Create StartStreamsButton
            app.StartStreamsButton = uibutton(app.IMAGEACQUISITIONTab, 'push');
            app.StartStreamsButton.ButtonPushedFcn = createCallbackFcn(app, @StartStreamsButtonPushed, true);
            app.StartStreamsButton.Position = [105 169 150 39];
            app.StartStreamsButton.Text = 'Start Streams';

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

            % Create UIAxesDEPTHStream
            app.UIAxesDEPTHStream = uiaxes(app.IMAGEACQUISITIONTab);
            app.UIAxesDEPTHStream.Box = 'on';
            app.UIAxesDEPTHStream.Position = [22 235 313 185];

            % Create UIAxesObjectContours
            app.UIAxesObjectContours = uiaxes(app.IMAGEACQUISITIONTab);
            app.UIAxesObjectContours.Box = 'on';
            app.UIAxesObjectContours.Position = [399 54 324 218];

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

            % Create DepthVideoStreamLabel
            app.DepthVideoStreamLabel = uilabel(app.IMAGEACQUISITIONTab);
            app.DepthVideoStreamLabel.Position = [122 411 113 22];
            app.DepthVideoStreamLabel.Text = 'Depth Video Stream';

            % Create StructuringElementRadiusSliderLabel
            app.StructuringElementRadiusSliderLabel = uilabel(app.IMAGEACQUISITIONTab);
            app.StructuringElementRadiusSliderLabel.HorizontalAlignment = 'center';
            app.StructuringElementRadiusSliderLabel.WordWrap = 'on';
            app.StructuringElementRadiusSliderLabel.Position = [800 175 190 16];
            app.StructuringElementRadiusSliderLabel.Text = 'Structuring Element Radius';

            % Create StructuringElementRadiusSlider
            app.StructuringElementRadiusSlider = uislider(app.IMAGEACQUISITIONTab);
            app.StructuringElementRadiusSlider.Limits = [0 16];
            app.StructuringElementRadiusSlider.MajorTicks = [0 2 4 6 8 10 12 14 16];
            app.StructuringElementRadiusSlider.MajorTickLabels = {'0', '2', '4', '6', '8', '10', '12', '14', '16'};
            app.StructuringElementRadiusSlider.MinorTicks = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16];
            app.StructuringElementRadiusSlider.Position = [791 227 194 3];
            app.StructuringElementRadiusSlider.Value = 5;

            % Create Label
            app.Label = uilabel(app.IMAGEACQUISITIONTab);
            app.Label.HorizontalAlignment = 'right';
            app.Label.Position = [755 324 25 22];
            app.Label.Text = '';

            % Create DropDownSelectROIForContour
            app.DropDownSelectROIForContour = uidropdown(app.IMAGEACQUISITIONTab);
            app.DropDownSelectROIForContour.Items = {'Full Object', 'ROI'};
            app.DropDownSelectROIForContour.Position = [755 324 203 22];
            app.DropDownSelectROIForContour.Value = 'Full Object';

            % Create POINTCLOUDPROCESSINGTab
            app.POINTCLOUDPROCESSINGTab = uitab(app.TabGroup);
            app.POINTCLOUDPROCESSINGTab.Title = 'POINT CLOUD PROCESSING';

            % Create UIAxesPCDownSampling
            app.UIAxesPCDownSampling = uiaxes(app.POINTCLOUDPROCESSINGTab);
            xlabel(app.UIAxesPCDownSampling, 'X')
            ylabel(app.UIAxesPCDownSampling, 'Y')
            zlabel(app.UIAxesPCDownSampling, 'Z')
            app.UIAxesPCDownSampling.Position = [382 64 741 573];

            % Create SelectRegionofInterestforPointCloudProcessingPanel
            app.SelectRegionofInterestforPointCloudProcessingPanel = uipanel(app.POINTCLOUDPROCESSINGTab);
            app.SelectRegionofInterestforPointCloudProcessingPanel.TitlePosition = 'centertop';
            app.SelectRegionofInterestforPointCloudProcessingPanel.Title = 'Select Region of Interest for Point Cloud Processing';
            app.SelectRegionofInterestforPointCloudProcessingPanel.Position = [31 559 332 78];

            % Create Label_2
            app.Label_2 = uilabel(app.SelectRegionofInterestforPointCloudProcessingPanel);
            app.Label_2.HorizontalAlignment = 'right';
            app.Label_2.Position = [66 21 25 22];
            app.Label_2.Text = '';

            % Create DropDownSelectROIForPCProcessing
            app.DropDownSelectROIForPCProcessing = uidropdown(app.SelectRegionofInterestforPointCloudProcessingPanel);
            app.DropDownSelectROIForPCProcessing.Items = {'Full Object', 'ROI'};
            app.DropDownSelectROIForPCProcessing.ValueChangedFcn = createCallbackFcn(app, @DropDownSelectROIForPCProcessingValueChanged, true);
            app.DropDownSelectROIForPCProcessing.Position = [66 21 203 22];
            app.DropDownSelectROIForPCProcessing.Value = 'Full Object';

            % Create PointCloudDownsamplingPanel
            app.PointCloudDownsamplingPanel = uipanel(app.POINTCLOUDPROCESSINGTab);
            app.PointCloudDownsamplingPanel.TitlePosition = 'centertop';
            app.PointCloudDownsamplingPanel.Title = 'Point Cloud Downsampling';
            app.PointCloudDownsamplingPanel.Position = [32 328 331 221];

            % Create GridBoxFilterSizemmSpinnerLabel
            app.GridBoxFilterSizemmSpinnerLabel = uilabel(app.PointCloudDownsamplingPanel);
            app.GridBoxFilterSizemmSpinnerLabel.HorizontalAlignment = 'right';
            app.GridBoxFilterSizemmSpinnerLabel.Position = [28 156 140 22];
            app.GridBoxFilterSizemmSpinnerLabel.Text = 'Grid Box Filter Size (mm)';

            % Create GridBoxFilterSizemmSpinner
            app.GridBoxFilterSizemmSpinner = uispinner(app.PointCloudDownsamplingPanel);
            app.GridBoxFilterSizemmSpinner.ValueChangingFcn = createCallbackFcn(app, @GridBoxFilterSizemmSpinnerValueChanging, true);
            app.GridBoxFilterSizemmSpinner.Position = [183 156 100 22];

            % Create CropButton
            app.CropButton = uibutton(app.PointCloudDownsamplingPanel, 'push');
            app.CropButton.Position = [29 97 100 22];
            app.CropButton.Text = 'Crop';

            % Create RemovePointsButton
            app.RemovePointsButton = uibutton(app.PointCloudDownsamplingPanel, 'push');
            app.RemovePointsButton.Position = [30 59 100 22];
            app.RemovePointsButton.Text = 'Remove Points';

            % Create DensifyCloudButton
            app.DensifyCloudButton = uibutton(app.PointCloudDownsamplingPanel, 'push');
            app.DensifyCloudButton.Position = [31 21 100 22];
            app.DensifyCloudButton.Text = 'Densify Cloud';

            % Create Button
            app.Button = uibutton(app.PointCloudDownsamplingPanel, 'push');
            app.Button.Position = [200 97 100 22];

            % Create Button2
            app.Button2 = uibutton(app.PointCloudDownsamplingPanel, 'push');
            app.Button2.Position = [201 59 100 22];
            app.Button2.Text = 'Button2';

            % Create Button3
            app.Button3 = uibutton(app.PointCloudDownsamplingPanel, 'push');
            app.Button3.Position = [201 21 100 22];
            app.Button3.Text = 'Button3';

            % Create ExitButton_2
            app.ExitButton_2 = uibutton(app.POINTCLOUDPROCESSINGTab, 'push');
            app.ExitButton_2.Position = [998 -36 100 22];
            app.ExitButton_2.Text = 'Exit';

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

            % 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