Ferdinann commited on
Commit
ce1ca74
·
verified ·
1 Parent(s): 631a8b8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +181 -181
app.py CHANGED
@@ -1,182 +1,182 @@
1
- import gradio as gr
2
- import tensorflow as tf
3
- import numpy as np
4
- from PIL import Image
5
-
6
- # --- KONFIGURASI ---
7
- IMG_SIZE = (224, 224) # Sesuaikan dengan input shape model Anda
8
- MODEL_PATH = "best_model.h5" # Pastikan nama file sesuai
9
-
10
- # Definisi Kelas (Sesuai urutan training model Anda)
11
- class_names = [
12
- 'Abrasions', 'Bruises', 'Burns', 'Cut', 'Diabetic Wounds',
13
- 'Laceration', 'Normal', 'Pressure Wounds', 'Surgical Wounds', 'Venous Wounds'
14
- ]
15
-
16
- # Mapping Bahasa Inggris -> Indonesia untuk UI
17
- translation_map = {
18
- 'Abrasions': 'Luka Lecet (Abrasi)',
19
- 'Bruises': 'Memar',
20
- 'Burns': 'Luka Bakar',
21
- 'Cut': 'Luka Sayat',
22
- 'Diabetic Wounds': 'Luka Diabetes',
23
- 'Laceration': 'Luka Robek',
24
- 'Normal': 'Normal/Sehat',
25
- 'Pressure Wounds': 'Luka Tekan (Dekubitus)',
26
- 'Surgical Wounds': 'Luka Operasi',
27
- 'Venous Wounds': 'Luka Vena'
28
- }
29
-
30
- # --- LOAD MODEL ---
31
- try:
32
- best_model = tf.keras.models.load_model(MODEL_PATH)
33
- print("✅ Model berhasil dimuat.")
34
- except Exception as e:
35
- best_model = None
36
- print(f"❌ Error memuat model: {e}")
37
-
38
- # --- LOGIKA REKOMENDASI ---
39
- def get_first_aid_recommendation(wound_class):
40
- rekomendasi = {
41
- 'Abrasions': (
42
- "1. Bersihkan luka dengan air mengalir untuk membuang kotoran.\n"
43
- "2. Gunakan sabun lembut di sekitar luka (jangan terkena luka langsung).\n"
44
- "3. Oleskan salep antibiotik atau petroleum jelly untuk menjaga kelembapan.\n"
45
- "4. Tutup dengan plester bersih jika luka berada di area yang mudah tergesek."
46
- ),
47
- 'Bruises': (
48
- "1. Istirahatkan area yang memar.\n"
49
- "2. Kompres dingin selama 15-20 menit untuk mengurangi pembengkakan.\n"
50
- "3. Posisikan bagian tubuh yang memar lebih tinggi dari jantung.\n"
51
- "4. Gunakan obat pereda nyeri jika diperlukan."
52
- ),
53
- 'Burns': (
54
- "1. Alirkan air biasa (bukan air es) pada area luka selama 10-20 menit.\n"
55
- "2. Lepaskan perhiasan atau pakaian yang ketat sebelum area membengkak.\n"
56
- "3. Tutup longgar dengan kain bersih atau kasa steril.\n"
57
- "4. **Jangan** memecahkan lepuh yang muncul."
58
- ),
59
- 'Cut': (
60
- "1. Tekan luka kuat-kuat dengan kain bersih selama 5-10 menit hingga darah berhenti.\n"
61
- "2. Bersihkan luka dengan air mengalir.\n"
62
- "3. Oleskan antiseptik pada pinggiran luka.\n"
63
- "4. Rekatkan plester atau perban steril."
64
- ),
65
- 'Diabetic Wounds': (
66
- "**Peringatan:** Luka diabetes membutuhkan perhatian khusus.\n"
67
- "1. Cuci luka dengan cairan saline (NaCl 0.9%).\n"
68
- "2. Jaga luka tetap kering dan tutup dengan kasa steril.\n"
69
- "3. Periksa tanda-tanda infeksi seperti nanah atau bau.\n"
70
- "4. Segera hubungi dokter spesialis luka."
71
- ),
72
- 'Laceration': (
73
- "1. Hentikan perdarahan dengan menekan luka secara stabil.\n"
74
- "2. Jika luka dalam dan robekannya lebar, segera tutup dengan kasa.\n"
75
- "3. Jangan mencoba mencuci luka jika perdarahan sangat deras.\n"
76
- "4. **Segera ke IGD** karena mungkin memerlukan jahitan medis."
77
- ),
78
- 'Normal': "Kulit terlihat normal dan sehat. Tetap jaga kebersihan area tersebut.",
79
- 'Pressure Wounds': (
80
- "1. Hilangkan tekanan pada area luka dengan mengubah posisi tubuh.\n"
81
- "2. Gunakan bantal atau bantalan pelindung khusus.\n"
82
- "3. Bersihkan area secara lembut dengan cairan saline.\n"
83
- "4. Jaga kulit di sekitarnya tetap lembap."
84
- ),
85
- 'Surgical Wounds': (
86
- "1. Ikuti instruksi penggantian perban dari dokter bedah Anda.\n"
87
- "2. Jangan menggaruk area jahitan.\n"
88
- "3. Jaga agar luka tetap kering saat mandi (gunakan penutup tahan air).\n"
89
- "4. Lapor dokter jika jahitan terbuka atau muncul kemerahan hebat."
90
- ),
91
- 'Venous Wounds': (
92
- "1. Gunakan stoking kompresi jika disarankan oleh medis.\n"
93
- "2. Angkat kaki lebih tinggi dari jantung saat berbaring.\n"
94
- "3. Lakukan aktivitas fisik ringan secara teratur.\n"
95
- "4. Jaga kelembapan kulit di sekitar luka."
96
- )
97
- }
98
- return rekomendasi.get(wound_class, "Rekomendasi belum tersedia. Silakan konsultasi dengan petugas medis.")
99
-
100
- # --- FUNGSI PREDIKSI ---
101
- def predict_image(image_input):
102
- if best_model is None:
103
- return {}, "⚠️ Model tidak ditemukan. Harap upload file model (.h5)."
104
-
105
- if image_input is None:
106
- return {}, "Silakan upload gambar."
107
-
108
- # Preprocessing
109
- img = image_input.resize(IMG_SIZE)
110
- img_array = tf.keras.utils.img_to_array(img)
111
- img_array = tf.expand_dims(img_array, 0)
112
- img_array = img_array / 255.0
113
-
114
- # Prediksi
115
- predictions = best_model.predict(img_array)
116
- scores = tf.nn.softmax(predictions[0]).numpy()
117
-
118
- # Mapping hasil untuk UI (Bahasa Indonesia)
119
- translated_output_dict = {
120
- translation_map.get(class_names[i], class_names[i]): float(scores[i])
121
- for i in range(len(class_names))
122
- }
123
-
124
- # Ambil label tertinggi
125
- top_idx = np.argmax(scores)
126
- top_label_en = class_names[top_idx]
127
- top_confidence = scores[top_idx]
128
-
129
- # --- LOGIKA THRESHOLD ---
130
- THRESHOLD = 0.50
131
-
132
- if top_confidence < THRESHOLD:
133
- top_label_id = "Normal (Tidak Terdeteksi)"
134
- rekomendasi_teks = (
135
- "**Mohon Maaf:** Model kurang akurat dalam menganalisis foto ini.\n\n"
136
- "**Saran:**\n"
137
- "1. Pastikan area luka terlihat jelas dan tidak blur.\n"
138
- "2. Gunakan pencahayaan yang cukup (terang).\n"
139
- "3. Ambil foto dari sudut tegak lurus ke arah luka.\n\n"
140
- "Jika Anda merasa luka ini serius, segera hubungi tenaga medis meskipun hasil analisis tidak muncul."
141
- )
142
- else:
143
- top_label_id = translation_map.get(top_label_en, top_label_en)
144
- rekomendasi_teks = get_first_aid_recommendation(top_label_en)
145
-
146
- # Format Markdown untuk Gradio
147
- formatted_output = (
148
- f"### Analisis: **{top_label_id}**\n\n"
149
- f"**Langkah Pertolongan:**\n{rekomendasi_teks}\n\n"
150
- f"--- \n*Tingkat Keyakinan AI: {top_confidence:.2%}*"
151
- )
152
-
153
- return translated_output_dict, formatted_output
154
-
155
- # --- UI INTERFACE ---
156
- with gr.Blocks(theme=gr.themes.Soft(primary_hue="red", secondary_hue="slate")) as demo:
157
- gr.Markdown("# 🚨 FirstAidLens")
158
- gr.Markdown("Deteksi jenis luka secara instan dan dapatkan panduan pertolongan pertama yang tepat.")
159
-
160
- with gr.Row():
161
- with gr.Column(scale=1):
162
- input_img = gr.Image(
163
- sources=["upload", "webcam"],
164
- type="pil",
165
- label="Ambil Foto Luka"
166
- )
167
- gr.Markdown("> **Penting:** Hasil AI ini hanya referensi awal. Jika luka parah atau pendarahan tidak berhenti, segera hubungi **112**.")
168
-
169
- with gr.Column(scale=1):
170
- output_label = gr.Label(num_top_classes=3, label="Hasil Analisis Jenis Luka")
171
- output_markdown = gr.Markdown("### Panduan Pertolongan Pertama\n_Upload atau ambil foto untuk melihat rekomendasi._")
172
-
173
- # Trigger otomatis saat gambar diupload/diambil
174
- input_img.change(
175
- fn=predict_image,
176
- inputs=input_img,
177
- outputs=[output_label, output_markdown]
178
- )
179
-
180
- # Launch (Server Name 0.0.0.0 wajib untuk Docker)
181
- if __name__ == "__main__":
182
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
1
+ import gradio as gr
2
+ import tensorflow as tf
3
+ import numpy as np
4
+ from PIL import Image
5
+
6
+ # --- KONFIGURASI ---
7
+ IMG_SIZE = (224, 224) # Sesuaikan dengan input shape model Anda
8
+ MODEL_PATH = "best_model.h5" # Pastikan nama file sesuai
9
+
10
+ # Definisi Kelas (Sesuai urutan training model Anda)
11
+ class_names = [
12
+ 'Abrasions', 'Bruises', 'Burns', 'Cut', 'Diabetic Wounds',
13
+ 'Laceration', 'Normal', 'Pressure Wounds', 'Surgical Wounds', 'Venous Wounds'
14
+ ]
15
+
16
+ # Mapping Bahasa Inggris -> Indonesia untuk UI
17
+ translation_map = {
18
+ 'Abrasions': 'Luka Lecet (Abrasi)',
19
+ 'Bruises': 'Memar',
20
+ 'Burns': 'Luka Bakar',
21
+ 'Cut': 'Luka Sayat',
22
+ 'Diabetic Wounds': 'Luka Diabetes',
23
+ 'Laceration': 'Luka Robek',
24
+ 'Normal': 'Normal/Sehat',
25
+ 'Pressure Wounds': 'Luka Tekan (Dekubitus)',
26
+ 'Surgical Wounds': 'Luka Operasi',
27
+ 'Venous Wounds': 'Luka Vena'
28
+ }
29
+
30
+ # --- LOAD MODEL ---
31
+ try:
32
+ best_model = tf.keras.models.load_model(MODEL_PATH)
33
+ print("✅ Model berhasil dimuat.")
34
+ except Exception as e:
35
+ best_model = None
36
+ print(f"❌ Error memuat model: {e}")
37
+
38
+ # --- LOGIKA REKOMENDASI ---
39
+ def get_first_aid_recommendation(wound_class):
40
+ rekomendasi = {
41
+ 'Abrasions': (
42
+ "1. Bersihkan luka dengan air mengalir untuk membuang kotoran.\n"
43
+ "2. Gunakan sabun lembut di sekitar luka (jangan terkena luka langsung).\n"
44
+ "3. Oleskan salep antibiotik atau petroleum jelly untuk menjaga kelembapan.\n"
45
+ "4. Tutup dengan plester bersih jika luka berada di area yang mudah tergesek."
46
+ ),
47
+ 'Bruises': (
48
+ "1. Istirahatkan area yang memar.\n"
49
+ "2. Kompres dingin selama 15-20 menit untuk mengurangi pembengkakan.\n"
50
+ "3. Posisikan bagian tubuh yang memar lebih tinggi dari jantung.\n"
51
+ "4. Gunakan obat pereda nyeri jika diperlukan."
52
+ ),
53
+ 'Burns': (
54
+ "1. Alirkan air biasa (bukan air es) pada area luka selama 10-20 menit.\n"
55
+ "2. Lepaskan perhiasan atau pakaian yang ketat sebelum area membengkak.\n"
56
+ "3. Tutup longgar dengan kain bersih atau kasa steril.\n"
57
+ "4. **Jangan** memecahkan lepuh yang muncul."
58
+ ),
59
+ 'Cut': (
60
+ "1. Tekan luka kuat-kuat dengan kain bersih selama 5-10 menit hingga darah berhenti.\n"
61
+ "2. Bersihkan luka dengan air mengalir.\n"
62
+ "3. Oleskan antiseptik pada pinggiran luka.\n"
63
+ "4. Rekatkan plester atau perban steril."
64
+ ),
65
+ 'Diabetic Wounds': (
66
+ "**Peringatan:** Luka diabetes membutuhkan perhatian khusus.\n"
67
+ "1. Cuci luka dengan cairan saline (NaCl 0.9%).\n"
68
+ "2. Jaga luka tetap kering dan tutup dengan kasa steril.\n"
69
+ "3. Periksa tanda-tanda infeksi seperti nanah atau bau.\n"
70
+ "4. Segera hubungi dokter spesialis luka."
71
+ ),
72
+ 'Laceration': (
73
+ "1. Hentikan perdarahan dengan menekan luka secara stabil.\n"
74
+ "2. Jika luka dalam dan robekannya lebar, segera tutup dengan kasa.\n"
75
+ "3. Jangan mencoba mencuci luka jika perdarahan sangat deras.\n"
76
+ "4. **Segera ke IGD** karena mungkin memerlukan jahitan medis."
77
+ ),
78
+ 'Normal': "Kulit terlihat normal dan sehat. Tetap jaga kebersihan area tersebut.",
79
+ 'Pressure Wounds': (
80
+ "1. Hilangkan tekanan pada area luka dengan mengubah posisi tubuh.\n"
81
+ "2. Gunakan bantal atau bantalan pelindung khusus.\n"
82
+ "3. Bersihkan area secara lembut dengan cairan saline.\n"
83
+ "4. Jaga kulit di sekitarnya tetap lembap."
84
+ ),
85
+ 'Surgical Wounds': (
86
+ "1. Ikuti instruksi penggantian perban dari dokter bedah Anda.\n"
87
+ "2. Jangan menggaruk area jahitan.\n"
88
+ "3. Jaga agar luka tetap kering saat mandi (gunakan penutup tahan air).\n"
89
+ "4. Lapor dokter jika jahitan terbuka atau muncul kemerahan hebat."
90
+ ),
91
+ 'Venous Wounds': (
92
+ "1. Gunakan stoking kompresi jika disarankan oleh medis.\n"
93
+ "2. Angkat kaki lebih tinggi dari jantung saat berbaring.\n"
94
+ "3. Lakukan aktivitas fisik ringan secara teratur.\n"
95
+ "4. Jaga kelembapan kulit di sekitar luka."
96
+ )
97
+ }
98
+ return rekomendasi.get(wound_class, "Rekomendasi belum tersedia. Silakan konsultasi dengan petugas medis.")
99
+
100
+ # --- FUNGSI PREDIKSI ---
101
+ def predict_image(image_input):
102
+ if best_model is None:
103
+ return {}, "⚠️ Model tidak ditemukan. Harap upload file model (.h5)."
104
+
105
+ if image_input is None:
106
+ return {}, "Silakan upload gambar."
107
+
108
+ # Preprocessing
109
+ img = image_input.resize(IMG_SIZE)
110
+ img_array = tf.keras.utils.img_to_array(img)
111
+ img_array = tf.expand_dims(img_array, 0)
112
+ img_array = img_array / 255.0
113
+
114
+ # Prediksi
115
+ predictions = best_model.predict(img_array)
116
+ scores = tf.nn.softmax(predictions[0]).numpy()
117
+
118
+ # Mapping hasil untuk UI (Bahasa Indonesia)
119
+ translated_output_dict = {
120
+ translation_map.get(class_names[i], class_names[i]): float(scores[i])
121
+ for i in range(len(class_names))
122
+ }
123
+
124
+ # Ambil label tertinggi
125
+ top_idx = np.argmax(scores)
126
+ top_label_en = class_names[top_idx]
127
+ top_confidence = scores[top_idx]
128
+
129
+ # --- LOGIKA THRESHOLD ---
130
+ THRESHOLD = 0.20
131
+
132
+ if top_confidence < THRESHOLD:
133
+ top_label_id = "Normal (Tidak Terdeteksi)"
134
+ rekomendasi_teks = (
135
+ "**Mohon Maaf:** Model kurang akurat dalam menganalisis foto ini.\n\n"
136
+ "**Saran:**\n"
137
+ "1. Pastikan area luka terlihat jelas dan tidak blur.\n"
138
+ "2. Gunakan pencahayaan yang cukup (terang).\n"
139
+ "3. Ambil foto dari sudut tegak lurus ke arah luka.\n\n"
140
+ "Jika Anda merasa luka ini serius, segera hubungi tenaga medis meskipun hasil analisis tidak muncul."
141
+ )
142
+ else:
143
+ top_label_id = translation_map.get(top_label_en, top_label_en)
144
+ rekomendasi_teks = get_first_aid_recommendation(top_label_en)
145
+
146
+ # Format Markdown untuk Gradio
147
+ formatted_output = (
148
+ f"### Analisis: **{top_label_id}**\n\n"
149
+ f"**Langkah Pertolongan:**\n{rekomendasi_teks}\n\n"
150
+ f"--- \n*Tingkat Keyakinan AI: {top_confidence:.2%}*"
151
+ )
152
+
153
+ return translated_output_dict, formatted_output
154
+
155
+ # --- UI INTERFACE ---
156
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="red", secondary_hue="slate")) as demo:
157
+ gr.Markdown("# 🚨 FirstAidLens")
158
+ gr.Markdown("Deteksi jenis luka secara instan dan dapatkan panduan pertolongan pertama yang tepat.")
159
+
160
+ with gr.Row():
161
+ with gr.Column(scale=1):
162
+ input_img = gr.Image(
163
+ sources=["upload", "webcam"],
164
+ type="pil",
165
+ label="Ambil Foto Luka"
166
+ )
167
+ gr.Markdown("> **Penting:** Hasil AI ini hanya referensi awal. Jika luka parah atau pendarahan tidak berhenti, segera hubungi **112**.")
168
+
169
+ with gr.Column(scale=1):
170
+ output_label = gr.Label(num_top_classes=3, label="Hasil Analisis Jenis Luka")
171
+ output_markdown = gr.Markdown("### Panduan Pertolongan Pertama\n_Upload atau ambil foto untuk melihat rekomendasi._")
172
+
173
+ # Trigger otomatis saat gambar diupload/diambil
174
+ input_img.change(
175
+ fn=predict_image,
176
+ inputs=input_img,
177
+ outputs=[output_label, output_markdown]
178
+ )
179
+
180
+ # Launch (Server Name 0.0.0.0 wajib untuk Docker)
181
+ if __name__ == "__main__":
182
  demo.launch(server_name="0.0.0.0", server_port=7860)