Dinaliah commited on
Commit
5902df4
·
verified ·
1 Parent(s): 48a7ad3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +101 -29
app.py CHANGED
@@ -1,40 +1,112 @@
1
- import streamlit as st
2
  import tensorflow as tf
3
  import numpy as np
4
  from PIL import Image
 
 
5
  from tensorflow.keras.applications.resnet50 import preprocess_input
6
 
7
- @st.cache_resource
8
- def load_model():
9
- return tf.keras.models.load_model("cnn_kfold_best_model.h5", compile=False)
10
 
11
- model = load_model()
12
- class_names = ["normal", "buried"]
 
 
 
 
 
 
13
 
14
- def prepare_image(img):
15
- img = img.convert("RGB")
16
- img = img.resize((224, 224))
17
- img_array = np.array(img)
18
- img_array = np.expand_dims(img_array, axis=0)
19
- img_array = preprocess_input(img_array)
20
- return img_array
21
 
22
- st.set_page_config(page_title="Ashoka Classifier")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
- st.title("🧠 Ashoka Hipospadia Classifier")
25
- st.write("Upload gambar untuk klasifikasi")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
- uploaded_file = st.file_uploader("Upload Image", type=["jpg","png","jpeg"])
 
 
 
 
 
 
 
 
28
 
29
- if uploaded_file:
30
- image = Image.open(uploaded_file)
31
- st.image(image, use_container_width=True)
32
-
33
- if st.button("Predict"):
34
- with st.spinner("Predicting..."):
35
- pred = model.predict(prepare_image(image))[0][0]
36
-
37
- if pred > 0.5:
38
- st.success(f"Buried ({pred*100:.2f}%)")
39
- else:
40
- st.success(f"Normal ({(1-pred)*100:.2f}%)")
 
1
+ from fastapi import FastAPI, File, UploadFile, HTTPException
2
  import tensorflow as tf
3
  import numpy as np
4
  from PIL import Image
5
+ import io
6
+ import sys
7
  from tensorflow.keras.applications.resnet50 import preprocess_input
8
 
9
+ # 1. Inisialisasi Aplikasi
10
+ app = FastAPI(title="Ashoka Hipospadia Classifier API")
 
11
 
12
+ # 2. Load Model
13
+ print("Sedang memuat model...")
14
+ try:
15
+ model = tf.keras.models.load_model('cnn_kfold_best_model.h5')
16
+ print("Model berhasil dimuat!")
17
+ except Exception as e:
18
+ print(f"Error memuat model: {e}")
19
+ sys.exit(1) # Matikan server jika model gagal load
20
 
21
+ # Label kelas: 0 = normal, 1 = buried
22
+ class_names = ['normal', 'buried']
 
 
 
 
 
23
 
24
+ # 3. Fungsi Preprocessing
25
+ def prepare_image(image_bytes):
26
+ """
27
+ Preprocessing gambar untuk model ResNet50
28
+ - Konversi ke RGB (3 channel)
29
+ - Resize ke 224x224
30
+ - Preprocessing ResNet50
31
+ """
32
+ try:
33
+ img = Image.open(io.BytesIO(image_bytes))
34
+
35
+ # Paksa ubah ke RGB agar PNG transparan tidak error
36
+ img = img.convert("RGB")
37
+
38
+ # Resize ke ukuran input model (224x224 untuk ResNet50)
39
+ img = img.resize((224, 224))
40
+
41
+ # Convert ke numpy array
42
+ img_array = np.array(img)
43
+
44
+ # Tambah batch dimension
45
+ img_array = np.expand_dims(img_array, axis=0)
46
+
47
+ # Preprocessing ResNet50 (HARUS sama dengan training!)
48
+ img_array = preprocess_input(img_array)
49
+
50
+ return img_array
51
+ except Exception as e:
52
+ print(f"Error saat memproses gambar: {e}")
53
+ return None
54
 
55
+ # 4. Endpoint Prediksi
56
+ @app.post("/predict")
57
+ async def predict(file: UploadFile = File(...)):
58
+ """
59
+ Endpoint untuk prediksi gambar
60
+ Input: File gambar (JPG, PNG, BMP)
61
+ Output: JSON dengan class dan confidence
62
+ """
63
+ try:
64
+ # Baca file gambar
65
+ image_bytes = await file.read()
66
+
67
+ # Proses gambar
68
+ processed_image = prepare_image(image_bytes)
69
+
70
+ if processed_image is None:
71
+ raise HTTPException(status_code=400, detail="File bukan gambar yang valid")
72
+
73
+ # Prediksi
74
+ prediction = model.predict(processed_image)
75
+ pred_value = float(prediction[0][0])
76
+
77
+ # Hitung probabilitas
78
+ # Model output: 0 = normal, 1 = buried
79
+ prob_normal = (1 - pred_value) * 100
80
+ prob_buried = pred_value * 100
81
+
82
+ # Tentukan kelas berdasarkan threshold 0.5
83
+ top_class_idx = 1 if pred_value > 0.5 else 0
84
+
85
+ # Hasil dalam format JSON
86
+ result = {
87
+ "class": class_names[top_class_idx],
88
+ "confidence": float(max(prob_normal, prob_buried)),
89
+ "probabilities": {
90
+ "normal": float(prob_normal),
91
+ "buried": float(prob_buried)
92
+ }
93
+ }
94
+ return result
95
+
96
+ except Exception as e:
97
+ # Cetak error ke log
98
+ print(f"CRITICAL ERROR: {e}")
99
+ raise HTTPException(status_code=500, detail=str(e))
100
 
101
+ # 5. Endpoint Home
102
+ @app.get("/")
103
+ def home():
104
+ """Endpoint root untuk testing API"""
105
+ return {
106
+ "message": "Ashoka Hipospadia Classifier API Online! 🚀"\n,
107
+ "model": "ResNet50 Binary Classification"\n,
108
+ "classes": class_names
109
+ }
110
 
111
+ # API siap digunakan dengan uvicorn
112
+ # Jalankan dengan: uvicorn app:app --host 0.0.0.0 --port 7860