import gradio as gr import tensorflow as tf import pandas as pd import numpy as np from datetime import datetime from PIL import Image MODEL_PATH = "best_model.h5" class_names = ['layak', 'rusak'] history_data = [] try: best_model = tf.keras.models.load_model(MODEL_PATH) print("✅ Model berhasil dimuat.") except Exception as e: print(f"❌ Gagal memuat model: {e}") # Dummy model untuk mencegah crash saat build jika file belum ada best_model = None # --- 2. Fungsi Helper --- def get_detailed_info(label, confidence): if label == 'layak': if confidence > 0.85: return "### ✅ STATUS: SANGAT LAYAK\n**Analisis:** Bangunan dalam kondisi prima. Struktur utama terlihat utuh dan sangat aman untuk dihuni." return "### ⚠️ STATUS: LAYAK (DENGAN CATATAN)\n**Analisis:** Bangunan aman dihuni, namun ditemukan indikasi kerusakan minor. Disarankan pengecekan rutin pada area retakan." else: if confidence > 0.85: return "### 🚨 STATUS: RUSAK PARAH\n**Analisis:** BAHAYA! Ditemukan kerusakan struktur fatal. Segera kosongkan area dan hubungi pihak berwenang." return "### 🚧 STATUS: RUSAK RINGAN\n**Analisis:** Terdeteksi kerusakan fisik pada beberapa bagian. Perlu perbaikan teknis sebelum bangunan dinyatakan aman sepenuhnya." def predict_image(img): if best_model is None: return {}, "Model belum dimuat." # Preprocessing img = img.resize((224, 224)) img_array = tf.keras.preprocessing.image.img_to_array(img) img_array = tf.expand_dims(img_array, 0) / 255.0 # Prediksi predictions = best_model.predict(img_array)[0] result = {class_names[i]: float(predictions[i]) for i in range(len(class_names))} top_label = max(result, key=result.get) description = get_detailed_info(top_label, result[top_label]) return result, description # --- 3. Fungsi Logic Dashboard --- def handle_upload(img): if img is None: return {}, "_Menunggu foto bangunan..._" return predict_image(img) def handle_report(img, location): if img is None: return {}, pd.DataFrame(history_data, columns=["Waktu", "Status", "Lokasi"]), None, "❌ Gagal: Foto kosong." output_dict, desc = predict_image(img) status = max(output_dict, key=output_dict.get).upper() now = datetime.now().strftime("%H:%M | %d-%m-%Y") history_data.insert(0, [now, status, location if location else "Pusat Kota"]) df = pd.DataFrame(history_data, columns=["Waktu", "Status", "Lokasi"]) return output_dict, df, None, "✅ Laporan berhasil disimpan ke riwayat!" # --- 4. UI Layout HomeCheck --- with gr.Blocks(title="HomeCheck AI") as demo: # Header Area with gr.Row(): with gr.Column(scale=8): gr.Markdown("# 🏠 HomeCheck AI") gr.Markdown("### *Sistem Deteksi Kelayakan Bangunan Cerdas*") with gr.Column(scale=2): gr.Markdown("![Logo](https://img.icons8.com/fluency/96/home.png)") gr.Markdown("---") with gr.Tabs(): with gr.TabItem("🔍 Analisis Baru"): with gr.Row(): # Kolom Kiri: Input with gr.Column(variant="panel"): gr.Markdown("#### 📥 Input Data") input_img = gr.Image(sources=["upload", "webcam"], type="pil", label="Foto Bangunan") input_loc = gr.Textbox( label="Titik Lokasi", placeholder="Contoh: Perumahan Indah Blok A, Medan", lines=1 ) btn_report = gr.Button("🚀 SIMPAN LAPORAN", variant="primary") # Kolom Kanan: Hasil with gr.Column(): gr.Markdown("#### 📊 Hasil Diagnosa") output_label = gr.Label(num_top_classes=2, label="Probabilitas Akurasi") with gr.Group(): output_description = gr.Markdown( "**Instruksi:**\nSilakan ambil atau upload foto bagian bangunan yang ingin diperiksa.", ) with gr.TabItem("📜 Riwayat Pemeriksaan"): gr.Markdown("#### 📑 Log Laporan Tersimpan") output_history = gr.Dataframe( headers=["Waktu", "Status", "Lokasi"], datatype=["str", "str", "str"], interactive=False ) gr.Markdown("---") gr.Markdown("© 2026 HomeCheck AI") # --- Interaction Logic --- input_img.change(fn=handle_upload, inputs=input_img, outputs=[output_label, output_description]) btn_report.click( fn=handle_report, inputs=[input_img, input_loc], outputs=[output_label, output_history, input_img, output_description] ) if __name__ == "__main__": demo.launch(server_name="0.0.0.0", server_port=7860)