classdef AppFinalAquisicaoImagem < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        UIFigure                        matlab.ui.Figure
        OBJECTDETECTIONPanel            matlab.ui.container.Panel
        ViewFullPointCloudButton        matlab.ui.control.Button
        SelectRegionofInterestforContoursPanel  matlab.ui.container.Panel
        DropDownSelectROIForContour     matlab.ui.control.DropDown
        Label                           matlab.ui.control.Label
        CONTOURSPanel                   matlab.ui.container.Panel
        ShowContoursButton              matlab.ui.control.Button
        StructuringElementRadiusSlider  matlab.ui.control.Slider
        StructuringElementRadiusSliderLabel  matlab.ui.control.Label
        UIAxesObjectContours            matlab.ui.control.UIAxes
        REGIONOFINTERESTPanel           matlab.ui.container.Panel
        SelectROIButton                 matlab.ui.control.Button
        SelectFullObjectButton          matlab.ui.control.Button
        TargetAreaPanel                 matlab.ui.container.Panel
        GetTargetAreaButton             matlab.ui.control.Button
        ROICoordinatesLabel             matlab.ui.control.Label
        Image                           matlab.ui.control.Image
        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
        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)
            % FUNÇAO TRANSFORMA IMAGEM DEPTH EM NUVEM DE PONTOS
            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)
            % 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)
            %% 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 further steps','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),'uint8'));

            % MOSTRAR RGB STREAM
            axis(app.UIAxesRGBStream,'image');
            preview(RGBDisp,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
            DEPTHDisp = videoinput('kinect',2,'Depth_640x480');

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

            % MOSTRAR DEPTH STREAM
            axis(app.UIAxesDEPTHStream)
            preview(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')

        end

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

            % 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(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);

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

        end

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

            % FECHAR JANELA DO BROWSER JÁ ABERTA ANTERIORMENTE
            close(figure(PointCloudBrowser))

            % MOSTAR NUVEM DE PONTOS
            figure("Name",'Point Cloud Browser','NumberTitle','off')
            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.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:ptCloudRot.Count;
            tempPtCloud = select(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(ptCloudRot.Location,1),size(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(ptCloudRot,roi,camMatrix);

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

            % MOSTRAR A NUVEM DE PONTOS COM A TARGER AREA
            figure(1);
            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)')

            % DEFINIÇÃO DOS PONTOS DOS VERTICES DO CUBO DA ROI
            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]';

            % 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)
              %% GLOBALS
            global ptcloudB
            global pclimpa

             % 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(ptcloudB,maxDistance,referenceVector);
            remainPtCloud = select(ptcloudB,outlierIndices);

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

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

        end

        % Button pushed function: SelectROIButton
        function SelectROIButtonPushed(app, event)
            %% GLOBALS
            global ptCloudRot
            global DEPTHDisp
            global RGBDisp
            global ROI_RGB_cropped
            global pcloud

            % 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(ptCloudRot.Location(:,:,1),[],1) reshape(ptCloudRot.Location(:,:,2),[],1) reshape(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)+10;
            minrow3 = min(ROWNOVA1)-10;
            maxcol3 = max(COLNOVA1)+10;
            mincol3 = min(COLNOVA1)-10;

            % RETIRAR UM FRAME DA CAMARA RGB E DEPTH
            DEPTHFrameFlipped2 = flip(getsnapshot(DEPTHDisp),2);
            RGBFrameFlipped2 = flip(getsnapshot(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 = imrect;

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

            % RECORTAR A IMAGEM PELA POSIÇAO DEFINIDA ANTERIORMENTE
            ROI_RGB_cropped = imcrop(RGB_ROI, position1);

            % RECORTAR A IMAGEM DEPTH PELA MESMA POSIÇAO QUE A RGB
            ROI_DEPTH_cropped =  imcrop(DEPTH_ROI, position1);

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

            % DEFINIR A PROFUNDIDADE MAXIMA DA NUVEM DA ROI PARA ELIMINAR PERTURBAÇOES DE FUNDO
            profmax=(app.EditField_Zmax.Value)*1000;

            % CRIAR A NUVEM DE PONTOS COM OS PONTOS SELECIONADOS PELA ROI
            [pcloud, ~] = depthToCloud(app,ROI_DEPTH_cropped,position1,profmax);

            % MOSTRAR A NUVEM DE PONTOS DA ROI
            figure("Name",'ROI Point Cloud Viewer','NumberTitle','off')
            pcshow(pcloud,"VerticalAxis","Y",VerticalAxisDir="Down")
            title('ROI Point Cloud')
            xlabel('X(m)')
            ylabel('Y(m)')
            zlabel('Z(m)')

        end

        % Button pushed function: ShowContoursButton
        function ShowContoursButtonPushed(app, event)
          %% GLOBALS
            global pclimpa
            global pcloud

            % 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 = pclimpa.Location(:,1);
                    ynuvem = pclimpa.Location(:,2);

%                     % 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,8);
%                     j = imclose(inverseimg,se);
%               
%                     ImgpContorno = j;

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

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

%                     % FAZER PLOT DOS PONTOS X E Y DO OBJETO E RODAR O PLOT
%                     plot(app.UIAxesObjectContours,xnuvem_roi,ynuvem_roi,'.k')
%                     set(app.UIAxesObjectContours,'ydir','reverse')
%                     axis(app.UIAxesObjectContours,'off')
% 
%                     % RETIRAR FRAME DO PLOT ANTERIOR
%                     frameplot_roi = frame2im(getframe(app.UIAxesObjectContours));
% 
%                     % BINARIZAR IMG E INVERTER COR
%                     imgbin_roi = imbinarize(im2gray(frameplot_roi));
%                     inverseimg_roi = uint8(255) - im2uint8(imgbin_roi);
% 
%                     % PREENCHER ESPAÇOS ABERTOS NO OBJETO
%                     raio_strel_roi = round(app.StructuringElementRadiusSlider.Value);
%                     se_roi = strel('disk',raio_strel_roi);
%                     j_roi = imclose(inverseimg_roi,se_roi);

%                     ImgpContorno = j_roi;
            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
            ImgEdge = edge(ImgClosed,"canny");

            % ENCONTRAR LINHAS E COLUNAS DOS PONTOS BRANCOS ( AKA CONTORNOS)
            [rowbw1,colbw1] = find(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(ImgEdge,1)
                rowmax12 = size(ImgEdge,1);
            end

            if colmin12 < 0
                colmin12 = 1;
            end

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

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

        end

        % Button pushed function: ExitButton
        function ExitButtonPushed(app, event)
            % FECHAR APLICAÇAO E TODAS AS JANELAS ABERTAS
            app.delete
            close all
        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 1156 724];
            app.UIFigure.Name = 'MATLAB App';

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

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

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

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

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

            % Create DepthVideoStreamLabel
            app.DepthVideoStreamLabel = uilabel(app.VIDEOSTREAMSPanel);
            app.DepthVideoStreamLabel.Position = [121 357 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 = [1014 18 100 22];
            app.ExitButton.Text = 'Exit';

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

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

            % Create TargetAreaPanel
            app.TargetAreaPanel = uipanel(app.OBJECTDETECTIONPanel);
            app.TargetAreaPanel.TitlePosition = 'centertop';
            app.TargetAreaPanel.Title = 'Target Area';
            app.TargetAreaPanel.Position = [18 333 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 = [95 158 34 22];
            app.XLabel.Text = '< X <';

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

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

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

            % Create ROICoordinatesLabel
            app.ROICoordinatesLabel = uilabel(app.TargetAreaPanel);
            app.ROICoordinatesLabel.Position = [65 190 95 22];
            app.ROICoordinatesLabel.Text = 'ROI Coordinates';

            % Create GetTargetAreaButton
            app.GetTargetAreaButton = uibutton(app.TargetAreaPanel, 'push');
            app.GetTargetAreaButton.ButtonPushedFcn = createCallbackFcn(app, @GetTargetAreaButtonPushed, true);
            app.GetTargetAreaButton.Position = [37 33 150 39];
            app.GetTargetAreaButton.Text = 'Get Target Area';

            % Create REGIONOFINTERESTPanel
            app.REGIONOFINTERESTPanel = uipanel(app.OBJECTDETECTIONPanel);
            app.REGIONOFINTERESTPanel.Title = 'REGION OF INTEREST';
            app.REGIONOFINTERESTPanel.Position = [18 109 247 207];

            % Create SelectFullObjectButton
            app.SelectFullObjectButton = uibutton(app.REGIONOFINTERESTPanel, 'push');
            app.SelectFullObjectButton.ButtonPushedFcn = createCallbackFcn(app, @SelectFullObjectButtonPushed, true);
            app.SelectFullObjectButton.Position = [18 107 203 61];
            app.SelectFullObjectButton.Text = 'Select Full Object';

            % Create SelectROIButton
            app.SelectROIButton = uibutton(app.REGIONOFINTERESTPanel, 'push');
            app.SelectROIButton.ButtonPushedFcn = createCallbackFcn(app, @SelectROIButtonPushed, true);
            app.SelectROIButton.Position = [18 20 203 61];
            app.SelectROIButton.Text = 'Select ROI';

            % Create CONTOURSPanel
            app.CONTOURSPanel = uipanel(app.OBJECTDETECTIONPanel);
            app.CONTOURSPanel.Title = 'CONTOURS';
            app.CONTOURSPanel.Position = [280 21 435 295];

            % Create UIAxesObjectContours
            app.UIAxesObjectContours = uiaxes(app.CONTOURSPanel);
            app.UIAxesObjectContours.Box = 'on';
            app.UIAxesObjectContours.Position = [6 51 324 218];

            % Create StructuringElementRadiusSliderLabel
            app.StructuringElementRadiusSliderLabel = uilabel(app.CONTOURSPanel);
            app.StructuringElementRadiusSliderLabel.HorizontalAlignment = 'center';
            app.StructuringElementRadiusSliderLabel.WordWrap = 'on';
            app.StructuringElementRadiusSliderLabel.Position = [336 3 91 62];
            app.StructuringElementRadiusSliderLabel.Text = 'Structuring Element Radius';

            % Create StructuringElementRadiusSlider
            app.StructuringElementRadiusSlider = uislider(app.CONTOURSPanel);
            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.Orientation = 'vertical';
            app.StructuringElementRadiusSlider.MinorTicks = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16];
            app.StructuringElementRadiusSlider.Position = [376 62 3 194];
            app.StructuringElementRadiusSlider.Value = 5;

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

            % Create SelectRegionofInterestforContoursPanel
            app.SelectRegionofInterestforContoursPanel = uipanel(app.OBJECTDETECTIONPanel);
            app.SelectRegionofInterestforContoursPanel.TitlePosition = 'centertop';
            app.SelectRegionofInterestforContoursPanel.Title = 'Select Region of Interest for Contours';
            app.SelectRegionofInterestforContoursPanel.Position = [18 21 247 89];

            % Create Label
            app.Label = uilabel(app.SelectRegionofInterestforContoursPanel);
            app.Label.HorizontalAlignment = 'right';
            app.Label.Position = [18 27 25 22];
            app.Label.Text = '';

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

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

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

            % 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