Ferdinann commited on
Commit
5490bd4
Β·
verified Β·
1 Parent(s): 46c06d6

Upload 4 files

Browse files
Files changed (4) hide show
  1. Dockerfile +21 -0
  2. app.py +93 -0
  3. model.h5 +3 -0
  4. requirements.txt +13 -0
Dockerfile ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Gunakan image Python resmi yang ringan
2
+ FROM python:3.10-slim
3
+
4
+ # Set lingkungan kerja di dalam container
5
+ WORKDIR /app
6
+
7
+ # Salin requirements dan instal library
8
+ COPY requirements.txt .
9
+ RUN pip install --no-cache-dir -r requirements.txt
10
+
11
+ # Salin seluruh isi folder proyek ke dalam container
12
+ COPY . .
13
+
14
+ # Berikan izin akses folder (untuk Hugging Face)
15
+ RUN chmod -R 777 /app
16
+
17
+ # Port yang digunakan Gradio
18
+ EXPOSE 7860
19
+
20
+ # Jalankan aplikasi
21
+ CMD ["python", "app.py"]
app.py ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import tensorflow as tf
3
+ import numpy as np
4
+ import pandas as pd
5
+ from datetime import datetime
6
+ from PIL import Image
7
+
8
+ # --- KONFIGURASI GLOBAL ---
9
+ IMG_SIZE = (224, 224)
10
+ MODEL_PATH = 'model.h5'
11
+ class_names = ['Aluvial', 'Andosol', 'Entisol', 'Humus', 'Inceptisol', 'Laterit', 'Kapur', 'Pasir']
12
+ num_classes = len(class_names)
13
+ history_data = []
14
+
15
+ # --- LOAD MODEL ---
16
+ try:
17
+ best_model = tf.keras.models.load_model(MODEL_PATH)
18
+ print("βœ… Model loaded successfully")
19
+ except Exception as e:
20
+ best_model = None
21
+ print(f"❌ Error loading model: {e}")
22
+
23
+ incident_descriptions = {
24
+ 'Aluvial': ("🌾 **Aluvial (Tanah Endapan Sungai)**\n\n**Karakteristik:** Sangat subur karena membawa mineral dari hulu sungai.\n**Rekomendasi Tanaman:** Padi, jagung, kedelai, atau tebu.\n**Langkah Pemulihan:**\n1. **Bersihkan Lumpur Pekat:** Buang lapisan lumpur keras agar akar bisa bernapas.\n2. **Cek Saluran Air:** Pastikan air tidak menggenang (becek).\n3. **Gemburkan Ulang:** Cangkul ringan agar oksigen masuk ke tanah."),
25
+ 'Andosol': ("πŸŒ‹ **Andosol (Tanah Vulkanik)**\n\n**Karakteristik:** Tanah hitam sangat kaya nutrisi abu gunung berapi.\n**Rekomendasi Tanaman:** Sayuran, kopi, atau teh.\n**Langkah Pemulihan:**\n1. **Terasering:** Buat gundukan bertingkat pada lahan miring.\n2. **Lindungi dari Angin:** Tanam pohon pelindung di pinggir lahan.\n3. **Siram Teratur:** Tanah ini cepat kering jika terpapar matahari langsung."),
26
+ 'Entisol': ("🌱 **Entisol (Tanah Muda)**\n\n**Karakteristik:** Tanah baru terbentuk, agak kasar dan belum matang.\n**Rekomendasi Tanaman:** Rumput pakan, ubi kayu, atau kacang tanah.\n**Langkah Pemulihan:**\n1. **Beri 'Makan' Tanah:** Campur pupuk kandang/kompos sebanyak mungkin.\n2. **Tanam Kacang-kacangan:** Membantu tanah mengambil nitrogen alami dari udara.\n3. **Hindari Bahan Kimia:** Gunakan pupuk alami agar struktur tanah tidak rusak."),
27
+ 'Humus': ("πŸ‚ **Humus (Tanah Organik)**\n\n**Karakteristik:** Tanah paling subur dari pembusukan vegetasi alami.\n**Rekomendasi Tanaman:** Semua jenis tanaman pangan dan sayuran.\n**Langkah Pemulihan:**\n1. **Selimut Tanah (Mulsa):** Tutupi tanah dengan jerami/daun kering.\n2. **Jangan Dibakar:** Hindari membakar sampah di atas tanah ini.\n3. **Jaga Kelembapan:** Cukup siram secukupnya, jangan berlebihan."),
28
+ 'Inceptisol': ("🌳 **Inceptisol (Tanah Perkebunan)**\n\n**Karakteristik:** Tanah perkebunan yang nutrisinya mulai berkurang.\n**Rekomendasi Tanaman:** Kelapa sawit, karet, atau buah-buahan.\n**Langkah Pemulihan:**\n1. **Pupuk Berkala:** Gunakan pupuk NPK sesuai dosis rutin.\n2. **Bersihkan Gulma:** Cabut rumput liar di sekitar batang pohon.\n3. **Cangkul Melingkar:** Cangkul di sekitar pohon agar pupuk meresap ke akar."),
29
+ 'Laterit': ("πŸ”΄ **Laterit (Tanah Merah/Asam)**\n\n**Karakteristik:** Tanah tua kemerahan dan terasa masam.\n**Rekomendasi Tanaman:** Cengkeh, jambu mete, atau karet.\n**Langkah Pemulihan:**\n1. **Tabur Kapur (Dolomit):** Gunakan kapur putih untuk menetralkan asam.\n2. **Tambah Pupuk Organik:** Campurkan pupuk kandang untuk memperbaiki warna.\n3. **Hindari Genangan:** Jangan biarkan air mengendap agar tanah tidak memadat."),
30
+ 'Kapur': ("βšͺ **Kapur (Tanah Mediteran)**\n\n**Karakteristik:** Berbatu putih, gersang, dan cepat kering.\n**Rekomendasi Tanaman:** Pohon jati, mahoni, atau srikaya.\n**Langkah Pemulihan:**\n1. **Tanam Pohon Keras:** Pilih pohon dengan akar kuat penembus batu.\n2. **Pupuk Hijau:** Tanam tumbuhan merambat sebagai penutup tanah.\n3. **Lubang Tanam Besar:** Isi lubang tanam dengan banyak kompos."),
31
+ 'Pasir': ("πŸ–οΈ **Pasir (Tanah Berpori)**\n\n**Karakteristik:** Butiran kasar, tidak simpan air, cepat panas.\n**Rekomendasi Tanaman:** Kelapa, buah naga, atau ubi jalar.\n**Langkah Pemulihan:**\n1. **Ikat Tanah:** Campur pupuk kandang dalam jumlah besar.\n2. **Siram Sore Hari:** Siram saat matahari tidak terik agar air tidak menguap.\n3. **Pupuk Sedikit tapi Sering:** Beri dosis kecil secara rutin.")
32
+ }
33
+
34
+ def predict_image(image_input):
35
+ if best_model is None:
36
+ return {}, "Model tidak tersedia."
37
+
38
+ img = image_input.resize(IMG_SIZE)
39
+ img_array = tf.keras.utils.img_to_array(img)
40
+ img_array = tf.expand_dims(img_array, 0) / 255.0
41
+
42
+ predictions = best_model.predict(img_array)
43
+ scores = tf.nn.softmax(predictions[0]).numpy()
44
+
45
+ output_dict = {class_names[i]: float(scores[i]) for i in range(num_classes)}
46
+ top_label = max(output_dict, key=output_dict.get)
47
+ top_confidence = output_dict[top_label]
48
+
49
+ description = incident_descriptions.get(top_label, "Deskripsi tidak tersedia.")
50
+
51
+ return output_dict, f"### πŸ“ Prediksi: **{top_label}** ({top_confidence:.2%})\n\n{description}"
52
+
53
+ def predict_only(img):
54
+ if img is None: return {}, "Silakan upload gambar."
55
+ return predict_image(img)
56
+
57
+ def predict_with_metadata(img, location):
58
+ if img is None:
59
+ return {}, pd.DataFrame(history_data, columns=["Waktu", "Jenis Tanah", "Lokasi"]), None, "Tidak ada gambar."
60
+
61
+ output_dict, formatted_desc = predict_image(img)
62
+ top_label = max(output_dict, key=output_dict.get)
63
+ now = datetime.now().strftime("%Y-%m-%d %H:%M")
64
+
65
+ history_data.append([now, top_label, location if location else "-"])
66
+ history_df = pd.DataFrame(history_data, columns=["Waktu", "Jenis Tanah", "Lokasi"])
67
+
68
+ return output_dict, history_df, None, formatted_desc
69
+
70
+ # --- UI GRADIO ---
71
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="emerald")) as demo:
72
+ gr.Markdown("# 🌍 GeoHeal AI Dashboard")
73
+ gr.Markdown("Deteksi jenis tanah untuk pemulihan lahan pertanian pasca bencana.")
74
+
75
+ with gr.Tabs():
76
+ with gr.TabItem("πŸ“Έ Analisis Real-time"):
77
+ with gr.Row():
78
+ with gr.Column():
79
+ input_img = gr.Image(sources=["upload", "webcam"], type="pil", label="Foto Tanah")
80
+ input_loc = gr.Textbox(label="Lokasi (Opsional)", placeholder="Contoh: Medan, Sumut")
81
+ btn_report = gr.Button("πŸ“‹ LAPORKAN KONDISI", variant="primary")
82
+ with gr.Column():
83
+ output_label = gr.Label(num_top_classes=3, label="Hasil Prediksi")
84
+ output_desc = gr.Markdown("_Hasil akan muncul di sini_")
85
+
86
+ with gr.TabItem("πŸ“œ Riwayat Laporan"):
87
+ output_history = gr.Dataframe(headers=["Waktu", "Jenis Tanah", "Lokasi"], interactive=False)
88
+
89
+ input_img.change(fn=predict_only, inputs=input_img, outputs=[output_label, output_desc])
90
+ btn_report.click(fn=predict_with_metadata, inputs=[input_img, input_loc], outputs=[output_label, output_history, input_img, output_desc])
91
+
92
+ if __name__ == "__main__":
93
+ demo.launch(server_name="0.0.0.0", server_port=7860)
model.h5 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8e510a1f33ddeb02a1087e00f5420327c5c2ff4394368ba41252e62d46486a93
3
+ size 41589144
requirements.txt ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ tensorflow==2.19.0
2
+ keras==3.10.0
3
+ numpy==2.0.2
4
+ matplotlib==3.10.0
5
+ seaborn==0.13.2
6
+ google-colab==1.0.0
7
+ tensorflow-hub==0.16.1
8
+ kagglehub==0.3.13
9
+ scikit-learn==1.6.1
10
+ tensorflowjs==4.22.0
11
+ gradio==5.50.0
12
+ Pillow==11.3.0
13
+ pandas==2.2.2