Ferdinann commited on
Commit
4d3afde
·
verified ·
1 Parent(s): a79b65e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -51
app.py CHANGED
@@ -5,9 +5,9 @@ from PIL import Image
5
 
6
  # --- KONFIGURASI ---
7
  IMG_SIZE = (224, 224)
8
- MODEL_PATH = "best_model.h5"
9
 
10
- # Definisi Kelas (Sesuai urutan training model)
11
  class_names = [
12
  'Abrasions', 'Bruises', 'Burns', 'Cut', 'Diabetic Wounds',
13
  'Laceration', 'Normal', 'Pressure Wounds', 'Surgical Wounds', 'Venous Wounds'
@@ -97,87 +97,86 @@ def get_first_aid_recommendation(wound_class):
97
  }
98
  return rekomendasi.get(wound_class, "Rekomendasi belum tersedia. Silakan konsultasi dengan petugas medis.")
99
 
100
- # --- SCRIPT JAVASCRIPT FINAL (ULTRA STABLE) ---
101
- get_location_js = """
102
- async function getLoc() {
103
- try {
104
- const position = await new Promise((resolve, reject) => {
105
- navigator.geolocation.getCurrentPosition(resolve, reject, {timeout: 8000});
106
- });
107
- return `${position.coords.latitude}, ${position.coords.longitude}`;
108
- } catch (e) {
109
- return "Lokasi tidak tersedia (Izin ditolak/Timeout)";
110
- }
111
- }
112
- """
113
-
114
- def predict_image(image_input, location_data):
115
- # Validasi input dasar
116
- if image_input is None:
117
- return {}, "Silakan upload gambar.", "⚠️ Foto belum diunggah."
118
  if best_model is None:
119
- return {}, "⚠️ Model gagal dimuat di server.", "N/A"
120
 
121
- # Status lokasi
122
- status_lokasi = f"📍 **Koordinat:** {location_data}" if location_data and "tidak" not in location_data.lower() else f"⚠️ {location_data or 'Gagal mengambil lokasi'}"
123
 
124
- # --- Preprocessing & Prediksi ---
125
  img = image_input.resize(IMG_SIZE)
126
- img_array = tf.keras.utils.img_to_array(img) / 255.0
127
- img_array = np.expand_dims(img_array, 0)
128
-
 
 
129
  predictions = best_model.predict(img_array)
130
- # Gunakan softmax jika model Anda belum memilikinya di layer terakhir
131
  scores = tf.nn.softmax(predictions[0]).numpy()
132
 
 
133
  translated_output_dict = {
134
  translation_map.get(class_names[i], class_names[i]): float(scores[i])
135
  for i in range(len(class_names))
136
  }
137
 
 
138
  top_idx = np.argmax(scores)
139
  top_label_en = class_names[top_idx]
140
  top_confidence = scores[top_idx]
141
 
142
- # Logika Threshold
143
- if top_confidence < 0.20:
 
 
144
  top_label_id = "Normal (Tidak Terdeteksi)"
145
- rekomendasi_teks = "Model tidak yakin. Pastikan luka terlihat jelas."
 
 
 
 
 
 
 
146
  else:
147
  top_label_id = translation_map.get(top_label_en, top_label_en)
148
  rekomendasi_teks = get_first_aid_recommendation(top_label_en)
149
 
 
150
  formatted_output = (
151
  f"### Analisis: **{top_label_id}**\n\n"
152
  f"**Langkah Pertolongan:**\n{rekomendasi_teks}\n\n"
153
  f"--- \n*Tingkat Keyakinan AI: {top_confidence:.2%}*"
154
  )
155
-
156
- return translated_output_dict, formatted_output, status_lokasi
157
 
158
  # --- UI INTERFACE ---
159
- # Pindahkan theme ke launch() atau hapus dari Blocks untuk menghindari error versi 6.0
160
- with gr.Blocks() as demo:
161
  gr.Markdown("# 🚨 FirstAidLens")
162
-
163
- location_hidden = gr.Textbox(visible=False)
164
-
165
  with gr.Row():
166
- with gr.Column():
167
- input_img = gr.Image(sources=["upload", "webcam"], type="pil", label="Foto Luka")
168
- btn_predict = gr.Button("Analisis Luka & Ambil Lokasi", variant="primary")
169
-
170
- with gr.Column():
171
- output_label = gr.Label(num_top_classes=3, label="Hasil Analisis")
172
- output_markdown = gr.Markdown("### Panduan Pertolongan Pertama")
173
- output_location = gr.Markdown("")
174
-
175
- btn_predict.click(
 
 
 
 
176
  fn=predict_image,
177
- inputs=[input_img, location_hidden],
178
- outputs=[output_label, output_markdown, output_location],
179
- js=get_location_js
180
  )
181
 
 
182
  if __name__ == "__main__":
183
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
5
 
6
  # --- KONFIGURASI ---
7
  IMG_SIZE = (224, 224)
8
+ MODEL_PATH = "best_model.h5"
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'
 
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)