Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import tensorflow as tf | |
| from PIL import Image | |
| import numpy as np | |
| import os | |
| import json | |
| # ========================================== | |
| # 1. KONFIGURASI HALAMAN | |
| # ========================================== | |
| st.set_page_config(page_title="Plant Disease Expert System", layout="wide", page_icon="πΏ") | |
| # ========================================== | |
| # 2. PATH DEFINISI (MENGGUNAKAN PATH RELATIF) | |
| # ========================================== | |
| # Di Hugging Face, gunakan path relatif terhadap root aplikasi | |
| BASE_MODEL_DIR = "model" | |
| MODEL_PATHS = { | |
| "MobileNetV2 (Best Fine-Tuned)": os.path.join(BASE_MODEL_DIR, "model_skripsi_mobilenet_final_FT.h5"), | |
| "InceptionV3 (Fine-Tuned)": os.path.join(BASE_MODEL_DIR, "model_skripsi_inception_finetuned.h5"), | |
| "Deep Custom CNN": os.path.join(BASE_MODEL_DIR, "model_skripsi_cnn_deep.h5"), | |
| "MobileNetV2 (Standard)": os.path.join(BASE_MODEL_DIR, "model_skripsi_mobilenet.h5"), | |
| "InceptionV3 (Standard)": os.path.join(BASE_MODEL_DIR, "model_skripsi_inception.h5") | |
| } | |
| # Path untuk Knowledge Base / Label | |
| PATH_JSON = os.path.join(BASE_MODEL_DIR, "knowledge_base.json") | |
| # ========================================== | |
| # 3. FUNGSI LOAD DATA & MODEL (CACHED) | |
| # ========================================== | |
| def get_labels_from_json(path): | |
| """Mengambil label dari knowledge_base.json agar tidak bergantung pada folder dataset""" | |
| try: | |
| if not os.path.exists(path): | |
| st.error(f"File {path} tidak ditemukan!") | |
| return {} | |
| with open(path, 'r') as f: | |
| return json.load(f) | |
| except Exception as e: | |
| st.error(f"Gagal membaca label JSON: {e}") | |
| return {} | |
| def load_my_model(path): | |
| """Memuat model h5""" | |
| return tf.keras.models.load_model(path) | |
| # ========================================== | |
| # 4. SIDEBAR: KONTROL & VALIDASI | |
| # ========================================== | |
| st.sidebar.header("βοΈ Kontrol Sistem") | |
| model_choice = st.sidebar.selectbox("Pilih Arsitektur Model:", list(MODEL_PATHS.keys())) | |
| # Ambil Knowledge Base (JSON) | |
| KB_DATA = get_labels_from_json(PATH_JSON) | |
| # Ambil list nama penyakit untuk mapping index | |
| CLASS_NAMES = [KB_DATA[str(i)]['jenis'] if str(i) in KB_DATA else f"Class {i}" for i in range(len(KB_DATA))] | |
| # Loading Model | |
| current_model_path = MODEL_PATHS[model_choice] | |
| if os.path.exists(current_model_path): | |
| model = load_my_model(current_model_path) | |
| # Deteksi info model otomatis | |
| num_classes_model = model.output_shape[-1] | |
| model_input_h = model.input_shape[1] | |
| model_input_w = model.input_shape[2] | |
| st.sidebar.divider() | |
| st.sidebar.success("β Model Loaded") | |
| st.sidebar.write(f"π Output Model: **{num_classes_model} Kelas**") | |
| st.sidebar.info(f"Dimensi Input: {model_input_h}x{model_input_w}") | |
| else: | |
| st.sidebar.error(f"β File Model Tidak Ditemukan di: {current_model_path}") | |
| st.stop() # Hentikan eksekusi jika model tidak ada | |
| # ========================================== | |
| # 5. HALAMAN UTAMA: PREDIKSI | |
| # ========================================== | |
| st.title("πΏ Identifikasi Penyakit Tanaman") | |
| st.write(f"Model Aktif: **{model_choice}**") | |
| uploaded_file = st.file_uploader("Unggah foto daun...", type=["jpg", "jpeg", "png"]) | |
| if uploaded_file: | |
| col1, col2 = st.columns([1, 1]) | |
| img_display = Image.open(uploaded_file).convert("RGB") | |
| with col1: | |
| st.image(img_display, caption="Preview Foto", use_container_width=True) | |
| with col2: | |
| if st.button("π Jalankan Diagnosa"): | |
| with st.spinner('Menganalisis pola penyakit...'): | |
| # Preprocessing sesuai input shape model | |
| target_size = (model_input_h, model_input_w) | |
| img = img_display.resize(target_size) | |
| img_array = np.array(img) / 255.0 | |
| img_array = np.expand_dims(img_array, axis=0) | |
| # Prediksi | |
| preds = model.predict(img_array) | |
| idx = np.argmax(preds) | |
| confidence = np.max(preds) * 100 | |
| # Tampilan Hasil Diagnosa | |
| st.markdown("### π Hasil Analisis") | |
| res_data = KB_DATA.get(str(idx)) | |
| if res_data: | |
| st.success(f"**Terdeteksi:** \n\n ### {res_data['jenis']}") | |
| st.metric("Tingkat Keyakinan", f"{confidence:.2f}%") | |
| with st.expander("Lihat Detail Kondisi & Saran"): | |
| st.write(f"**Kondisi:** {res_data.get('kondisi', 'N/A')}") | |
| st.write(f"**Deskripsi:** {res_data.get('deskripsi', 'N/A')}") | |
| else: | |
| st.error(f"Index {idx} tidak ditemukan di Knowledge Base.") | |
| # ========================================== | |
| # 6. FOOTER | |
| # ========================================== | |
| st.markdown("---") | |
| st.caption("Aplikasi Prediksi Penyakit Tanaman - Penelitian Skripsi 2026") |