Project-Ashoka / app.py
Xaviant's picture
Update app.py
3f2f973 verified
raw
history blame
3.35 kB
from fastapi import FastAPI, File, UploadFile, HTTPException
import tensorflow as tf
import numpy as np
from PIL import Image
import io
import sys
from tensorflow.keras.applications.densenet import preprocess_input
# 1. Inisialisasi Aplikasi
app = FastAPI(title="Ashoka Hipospadia Classifier API")
# 2. Load Model
print("Sedang memuat model...")
try:
model = tf.keras.models.load_model('cnn_kfold_best_model_v2.h5')
print("Model berhasil dimuat!")
except Exception as e:
print(f"Error memuat model: {e}")
sys.exit(1) # Matikan server jika model gagal load
# Label kelas: 0 = normal, 1 = buried
class_names = ['normal', 'buried']
# 3. Fungsi Preprocessing
def prepare_image(image_bytes):
"""
Preprocessing gambar untuk model ResNet50
- Konversi ke RGB (3 channel)
- Resize ke 224x224
- Preprocessing ResNet50
"""
try:
img = Image.open(io.BytesIO(image_bytes))
# Paksa ubah ke RGB agar PNG transparan tidak error
img = img.convert("RGB")
# Resize ke ukuran input model (224x224 untuk ResNet50)
img = img.resize((224, 224))
# Convert ke numpy array
img_array = np.array(img)
# Tambah batch dimension
img_array = np.expand_dims(img_array, axis=0)
# Preprocessing ResNet50 (HARUS sama dengan training!)
img_array = preprocess_input(img_array)
return img_array
except Exception as e:
print(f"Error saat memproses gambar: {e}")
return None
# 4. Endpoint Prediksi
@app.post("/predict")
async def predict(file: UploadFile = File(...)):
"""
Endpoint untuk prediksi gambar
Input: File gambar (JPG, PNG, BMP)
Output: JSON dengan class dan confidence
"""
try:
# Baca file gambar
image_bytes = await file.read()
# Proses gambar
processed_image = prepare_image(image_bytes)
if processed_image is None:
raise HTTPException(status_code=400, detail="File bukan gambar yang valid")
# Prediksi
prediction = model.predict(processed_image)
pred_value = float(prediction[0][0])
# Hitung probabilitas
# Model output: 0 = normal, 1 = buried
prob_normal = (1 - pred_value) * 100
prob_buried = pred_value * 100
# Tentukan kelas berdasarkan threshold 0.5
top_class_idx = 1 if pred_value > 0.5 else 0
# Hasil dalam format JSON
result = {
"class": class_names[top_class_idx],
"confidence": float(max(prob_normal, prob_buried)),
"probabilities": {
"normal": float(prob_normal),
"buried": float(prob_buried)
}
}
return result
except Exception as e:
# Cetak error ke log
print(f"CRITICAL ERROR: {e}")
raise HTTPException(status_code=500, detail=str(e))
# 5. Endpoint Home
@app.get("/")
def home():
"""Endpoint root untuk testing API"""
return {
"message": "Ashoka Hipospadia Classifier API Online! ๐Ÿš€\n",
"model": "DenseNet Binary Classification\n",
"classes": class_names
}
# API siap digunakan dengan uvicorn
# Jalankan dengan: uvicorn app:app --host 0.0.0.0 --port 7860