classdef KlasifikasiBatik < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        UIFigure                    matlab.ui.Figure
        HasilDataLatihPanel         matlab.ui.container.Panel
        DataLatihTable              matlab.ui.control.Table
        Panel                       matlab.ui.container.Panel
        KlasifikasiMotifBatikLabel  matlab.ui.control.Label
        HasilEkstraksiCitraPanel    matlab.ui.container.Panel
        GLCMTable                   matlab.ui.control.Table
        HasilKlasifikasiCitraPanel  matlab.ui.container.Panel
        EditField_2                 matlab.ui.control.EditField
        PengolahanPanel             matlab.ui.container.Panel
        CovertGrayscaleButton       matlab.ui.control.Button
        KembaliButton               matlab.ui.control.Button
        DataLatihButton             matlab.ui.control.Button
        ResetButton                 matlab.ui.control.Button
        ClassifyButton              matlab.ui.control.Button
        ExtractGLCMButton           matlab.ui.control.Button
        EditField                   matlab.ui.control.EditField
        OpenImageButton             matlab.ui.control.Button
        HasilProsesCitraPanel       matlab.ui.container.Panel
        axesCrop                    matlab.ui.control.UIAxes
        CitraGrayscalePanel         matlab.ui.container.Panel
        axesGray                    matlab.ui.control.UIAxes
        CitraRGBPanel               matlab.ui.container.Panel
        axesRGB                     matlab.ui.control.UIAxes
    end

    
    properties (Access = private)
    imageRGB % Menyimpan gambar RGB
    resizedImage %Menyimpan gambar resize
    imageGray % Menyimpan gambar grayscale
    croppedImage % Menyimpan gambar hasil cropping
    featureVector % Menyimpan vektor fitur GLCM
    end
    
    properties (Access = public)
    ModelKnn % Model KNN
    end
    

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

        % Button pushed function: OpenImageButton
        function OpenImageButtonPushed(app, event)
        [file, path] = uigetfile({'*.jpg; *.jpeg; *.png;*.bmp', 'Images (*.jpg, *.jpeg, *.png, *.bmp)'});
        if isequal(file, 0)
            return;
        end
    
        % Menyimpan path lengkap file yang dipilih
        fullFilePath = fullfile(path, file);
    
        % Membaca dan menampilkan gambar RGB
        app.imageRGB = imread(fullFilePath);
        
        % Resize the grayscale image to 300x300 pixels
        resizedImage = imresize(app.imageRGB, [300 300]);
        imshow(resizedImage, 'Parent', app.axesRGB);
        
        % Store the resized image for further use
        app.resizedImage = resizedImage;
    
        % Menampilkan nama file pada EditField
        app.EditField.Value = file;
        end

        % Button pushed function: CovertGrayscaleButton
        function CovertGrayscaleButtonPushed(app, event)
        % Check if an image has been selected and resized
        if isempty(app.resizedImage)
            errordlg('Citra belum dipilih, silakan pilih citra terlebih dahulu.', 'Error');
            return; % Exit the function if no image is selected
        end

        % Convert the RGB image to grayscale and display it
        app.imageGray = rgb2gray(app.resizedImage);
        imshow(app.imageGray, 'Parent', app.axesGray);
        
        % Crop the resized image manually using interactive cropping tool
        croppedImage = imcrop(app.axesGray);
        
        % Check if the user has selected a region
        if ~isempty(croppedImage)
            % Store the cropped image
            app.croppedImage = croppedImage;
            imshow(app.croppedImage, 'Parent', app.axesCrop);
        else
            disp('Cropping was cancelled or no region was selected.');
        end
        end

        % Button pushed function: ExtractGLCMButton
        function ExtractGLCMButtonPushed(app, event)
        % Check if the cropped image exists
        if isempty(app.croppedImage)
            errordlg('Proses citra belum dilakukan, silakan pilih citra terlebih dahulu.', 'Error');
            return; % Exit the function if no cropped image is available
        end

        % Definisikan offset untuk GLCM
        offsets = [0 1; -1 1; -1 0; -1 -1];
        
        % Hitung GLCM
        glcm = graycomatrix(app.croppedImage, 'Offset', offsets);
        
        % Hitung properti GLCM
        stats = graycoprops(glcm, {'Contrast', 'Correlation', 'Energy', 'Homogeneity'});
        
        % Hitung Entropi untuk setiap arah
        entropyValues = zeros(1, size(glcm, 3));
        for k = 1:size(glcm, 3)
            glcmNormalized = glcm(:, :, k) / sum(glcm(:, :, k), 'all');
            entropyValues(k) = -sum(glcmNormalized(:) .* log2(glcmNormalized(:) + eps));
        end

        % Buat vektor fitur yang mencakup entropi
        contrast = mean(stats.Contrast);
        correlation = mean(stats.Correlation);
        energy = mean(stats.Energy);
        homogeneity = mean(stats.Homogeneity);
        entropy = mean(entropyValues);
        
        app.featureVector = [contrast, correlation, energy, homogeneity, entropy];
        
        % Menyiapkan data untuk ditampilkan di UITable
        data = cell(5, 6);
        
        % Menyiapkan judul kolom dan baris di UITable
        data(1,:) = {'ASM'};
        data(2,1) = {'Kontras'};
        data(3,1) = {'IDM'};
        data(4,1) = {'Entropi'};
        data(5,1) = {'Korelasi'};
        
        % Energy digunakan sebagai ASM
        data(1, 2:5) = num2cell(stats.Energy);
        data(1, 6) = {energy};
        
        data(2, 2:5) = num2cell(stats.Contrast);
        data(2, 6) = {contrast};
        
        % IDM (Inverse Difference Moment) dapat dihitung dari Homogeneity
        data(3, 2:5) = num2cell(stats.Homogeneity);
        data(3, 6) = {homogeneity};
        
        data(4, 2:5) = num2cell(entropyValues);
        data(4, 6) = {entropy};
        
        data(5, 2:5) = num2cell(stats.Correlation);
        data(5, 6) = {correlation};
        
        % Menampilkan data di UITable
        app.GLCMTable.Data = data;
        app.GLCMTable.ForegroundColor = [0 0 0];
        
        % Menyiapkan judul kolom di UITable
        app.GLCMTable.ColumnName = {'Properti','0°','45°','90°','135°','Rata-Rata'};
        app.GLCMTable.RowName = {};
        end

        % Button pushed function: DataLatihButton
        function DataLatihButtonPushed(app, event)
        % Tentukan path dan nama file secara langsung
        file = 'DataLatih1.xlsx';
        path = 'F:\SKRIPSI\MATLAB\Matlab Batik\';  % Ganti dengan path yang sesuai
        
        % Menggabungkan path dan nama file
        fullpath = fullfile(path, file);
        
        % Membaca data dari file Excel
        data = readtable(fullpath);
        
        % Menampilkan data pada UI Table
        app.DataLatihTable.Data = data;
        
        % Mengatur nama kolom dan baris pada UI Table
        app.DataLatihTable.ColumnName = {'ASM', 'Kontras', 'IDM', 'Entropi', 'Korelasi', 'Kelas'};
        end

        % Button pushed function: ClassifyButton
        function ClassifyButtonPushed(app, event)
        % Check if feature extraction has been performed
        if isempty(app.featureVector)
            errordlg('Hasil klasifikasi belum tersedia, silakan lakukan ekstraksi fitur citra terlebih dahulu.', 'Error');
            return; % Exit the function if no feature vector is available
        end

        % Membaca data dari file Excel
        filename = 'DataLatih1.xlsx'; % Pastikan file Excel Anda memiliki nama ini
        training = readmatrix(filename);
        
        % Menentukan kelompok (kelas) dan data latih
        group = training(:,6); % Kolom ke-6 adalah kelas
        data = training(:, 1:5); % Kolom 1-5 adalah fitur
        
        % Melatih KNN classifier
        Mdl = fitcknn(data, group, 'NumNeighbors', 1);
        
        % Melakukan klasifikasi data baru berdasarkan fitur ekstraksi GLCM yang disimpan dalam app.featureVector
        newData = app.featureVector; % Asumsikan app.featureVector berukuran sama dengan fitur latih (kolom 1-5)
        
        % Prediksi kelas untuk data baru
        hasil = predict(Mdl, newData);

        % Menentukan klasifikasi berdasarkan hasil
        klasifikasi = cell(size(hasil)); % Inisialisasi cell array untuk menyimpan hasil klasifikasi
        for i = 1:length(hasil)
            if hasil(i) == 1
                klasifikasi{i} = 'Motif Batik Tembakau';
            elseif hasil(i) == 2
                klasifikasi{i} = 'Motif Batik Kopi';
            end
        end

        % Menampilkan hasil klasifikasi pada app.EditField_2
        app.EditField_2.Value = klasifikasi{1}; % Asumsi hanya satu hasil klasifikasi yang akan ditampilkan
        
        % Jika Anda ingin menampilkan semua hasil klasifikasi (misalnya dalam satu field atau daftar):
        % app.EditField_2.Value = strjoin(klasifikasi, ', ');
        end

        % Button pushed function: ResetButton
        function ResetButtonPushed(app, event)
        % Reset all UIAxes
        axesHandles = findall(app.UIFigure, 'Type', 'axes');
        for i = 1:length(axesHandles)
            cla(axesHandles(i));
        end
        
        % Reset all UITables
        tableHandles = findall(app.UIFigure, 'Type', 'uitable');
        for i = 1:length(tableHandles)
            tableHandles(i).Data = {};
        end
            
        % Reset all EditFields
        editFieldHandles = findall(app.UIFigure, 'Type', 'uieditfield');
        for i = 1:length(editFieldHandles)
            editFieldHandles(i).Value = '';
        end
        end

        % Button pushed function: KembaliButton
        function KembaliButtonPushed(app, event)
        % Fungsi untuk menutup aplikasi
        delete(app.UIFigure); % Hapus atau tutup figure utama aplikasi
        app = BerandaKlasifikasiBatik; % Mengalihkan ke panduan sistem (misalkan membuat instance baru)
        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.Color = [0.8 0.8 0.8];
            app.UIFigure.Position = [100 100 1222 650];
            app.UIFigure.Name = 'MATLAB App';

            % Create CitraRGBPanel
            app.CitraRGBPanel = uipanel(app.UIFigure);
            app.CitraRGBPanel.Title = 'Citra RGB';
            app.CitraRGBPanel.BackgroundColor = [0.9412 0.9412 0.9412];
            app.CitraRGBPanel.FontWeight = 'bold';
            app.CitraRGBPanel.Position = [147 323 221 223];

            % Create axesRGB
            app.axesRGB = uiaxes(app.CitraRGBPanel);
            app.axesRGB.XTick = [];
            app.axesRGB.YTick = [];
            app.axesRGB.Position = [8 2 205 188];

            % Create CitraGrayscalePanel
            app.CitraGrayscalePanel = uipanel(app.UIFigure);
            app.CitraGrayscalePanel.Title = 'Citra Grayscale';
            app.CitraGrayscalePanel.FontWeight = 'bold';
            app.CitraGrayscalePanel.Position = [389 323 219 223];

            % Create axesGray
            app.axesGray = uiaxes(app.CitraGrayscalePanel);
            app.axesGray.XTick = [];
            app.axesGray.YTick = [];
            app.axesGray.Position = [7 1 205 188];

            % Create HasilProsesCitraPanel
            app.HasilProsesCitraPanel = uipanel(app.UIFigure);
            app.HasilProsesCitraPanel.Title = 'Hasil Proses Citra';
            app.HasilProsesCitraPanel.FontWeight = 'bold';
            app.HasilProsesCitraPanel.Position = [629 323 225 223];

            % Create axesCrop
            app.axesCrop = uiaxes(app.HasilProsesCitraPanel);
            app.axesCrop.XTick = [];
            app.axesCrop.YTick = [];
            app.axesCrop.Position = [10 1 205 188];

            % Create PengolahanPanel
            app.PengolahanPanel = uipanel(app.UIFigure);
            app.PengolahanPanel.Title = 'Pengolahan';
            app.PengolahanPanel.FontWeight = 'bold';
            app.PengolahanPanel.Position = [23 28 288 275];

            % Create OpenImageButton
            app.OpenImageButton = uibutton(app.PengolahanPanel, 'push');
            app.OpenImageButton.ButtonPushedFcn = createCallbackFcn(app, @OpenImageButtonPushed, true);
            app.OpenImageButton.Position = [9 215 126 22];
            app.OpenImageButton.Text = 'Pilih Citra';

            % Create EditField
            app.EditField = uieditfield(app.PengolahanPanel, 'text');
            app.EditField.Position = [150 215 121 22];

            % Create ExtractGLCMButton
            app.ExtractGLCMButton = uibutton(app.PengolahanPanel, 'push');
            app.ExtractGLCMButton.ButtonPushedFcn = createCallbackFcn(app, @ExtractGLCMButtonPushed, true);
            app.ExtractGLCMButton.Position = [8 151 125 22];
            app.ExtractGLCMButton.Text = 'Ekstraksi Citra';

            % Create ClassifyButton
            app.ClassifyButton = uibutton(app.PengolahanPanel, 'push');
            app.ClassifyButton.ButtonPushedFcn = createCallbackFcn(app, @ClassifyButtonPushed, true);
            app.ClassifyButton.Position = [8 117 126 22];
            app.ClassifyButton.Text = 'Klasifikasi';

            % Create ResetButton
            app.ResetButton = uibutton(app.PengolahanPanel, 'push');
            app.ResetButton.ButtonPushedFcn = createCallbackFcn(app, @ResetButtonPushed, true);
            app.ResetButton.Position = [8 83 126 22];
            app.ResetButton.Text = 'Reset';

            % Create DataLatihButton
            app.DataLatihButton = uibutton(app.PengolahanPanel, 'push');
            app.DataLatihButton.ButtonPushedFcn = createCallbackFcn(app, @DataLatihButtonPushed, true);
            app.DataLatihButton.Position = [9 19 126 22];
            app.DataLatihButton.Text = 'Data Latih';

            % Create KembaliButton
            app.KembaliButton = uibutton(app.PengolahanPanel, 'push');
            app.KembaliButton.ButtonPushedFcn = createCallbackFcn(app, @KembaliButtonPushed, true);
            app.KembaliButton.Position = [9 51 126 22];
            app.KembaliButton.Text = 'Kembali';

            % Create CovertGrayscaleButton
            app.CovertGrayscaleButton = uibutton(app.PengolahanPanel, 'push');
            app.CovertGrayscaleButton.ButtonPushedFcn = createCallbackFcn(app, @CovertGrayscaleButtonPushed, true);
            app.CovertGrayscaleButton.Position = [8 183 126 22];
            app.CovertGrayscaleButton.Text = 'Proses Citra';

            % Create HasilKlasifikasiCitraPanel
            app.HasilKlasifikasiCitraPanel = uipanel(app.UIFigure);
            app.HasilKlasifikasiCitraPanel.Title = 'Hasil Klasifikasi Citra';
            app.HasilKlasifikasiCitraPanel.FontWeight = 'bold';
            app.HasilKlasifikasiCitraPanel.Position = [877 323 237 223];

            % Create EditField_2
            app.EditField_2 = uieditfield(app.HasilKlasifikasiCitraPanel, 'text');
            app.EditField_2.HorizontalAlignment = 'center';
            app.EditField_2.FontSize = 14;
            app.EditField_2.FontWeight = 'bold';
            app.EditField_2.Position = [21 83 196 27];

            % Create HasilEkstraksiCitraPanel
            app.HasilEkstraksiCitraPanel = uipanel(app.UIFigure);
            app.HasilEkstraksiCitraPanel.Title = 'Hasil Ekstraksi Citra';
            app.HasilEkstraksiCitraPanel.FontWeight = 'bold';
            app.HasilEkstraksiCitraPanel.Position = [330 28 425 275];

            % Create GLCMTable
            app.GLCMTable = uitable(app.HasilEkstraksiCitraPanel);
            app.GLCMTable.ColumnName = {''; '0°'; '45°'; '90°'; '135°'; 'Rata-Rata'};
            app.GLCMTable.RowName = {'ASM, Kontras, IDM, Entropi, Korelasi'};
            app.GLCMTable.ColumnEditable = true;
            app.GLCMTable.Position = [20 20 375 218];

            % Create Panel
            app.Panel = uipanel(app.UIFigure);
            app.Panel.Position = [-15 577 1305 87];

            % Create KlasifikasiMotifBatikLabel
            app.KlasifikasiMotifBatikLabel = uilabel(app.Panel);
            app.KlasifikasiMotifBatikLabel.HorizontalAlignment = 'center';
            app.KlasifikasiMotifBatikLabel.FontName = 'Edwardian Script ITC';
            app.KlasifikasiMotifBatikLabel.FontSize = 50;
            app.KlasifikasiMotifBatikLabel.FontWeight = 'bold';
            app.KlasifikasiMotifBatikLabel.Position = [425 10 403 66];
            app.KlasifikasiMotifBatikLabel.Text = 'Klasifikasi  Motif  Batik';

            % Create HasilDataLatihPanel
            app.HasilDataLatihPanel = uipanel(app.UIFigure);
            app.HasilDataLatihPanel.Title = 'Hasil Data Latih';
            app.HasilDataLatihPanel.FontWeight = 'bold';
            app.HasilDataLatihPanel.Position = [772 28 425 275];

            % Create DataLatihTable
            app.DataLatihTable = uitable(app.HasilDataLatihPanel);
            app.DataLatihTable.ColumnName = {'ASM'; 'Kontras'; 'IDM'; 'Entropi'; 'Korelasi'};
            app.DataLatihTable.RowName = {'ASM, Kontras, IDM, Entropi, Korelasi'};
            app.DataLatihTable.ColumnEditable = true;
            app.DataLatihTable.Position = [20 20 375 218];

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

            % Create UIFigure and components
            createComponents(app)

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

            if nargout == 0
                clear app
            end
        end

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

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