leaf_disease_ai / src /streamlit_app.py
BlasterBlade65's picture
Update src/streamlit_app.py
f816975 verified
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)
# ==========================================
@st.cache_data
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 {}
@st.cache_resource
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")