Spaces:
Runtime error
Runtime error
| 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 import MobileNetV2 | |
| from tensorflow.keras.applications.mobilenet_v2 import preprocess_input | |
| from tensorflow.keras.layers import GlobalAveragePooling2D, Dense, Dropout | |
| from tensorflow.keras.models import Model | |
| # =============================== | |
| # 1. Inisialisasi Aplikasi | |
| # =============================== | |
| app = FastAPI(title="Ashoka Hipospadia Classifier API") | |
| # =============================== | |
| # 2. Build Model (SAMA DENGAN TRAINING) | |
| # =============================== | |
| def build_model(): | |
| base_model = MobileNetV2( | |
| input_shape=(224, 224, 3), | |
| include_top=False, | |
| weights="imagenet" | |
| ) | |
| base_model.trainable = False | |
| x = base_model.output | |
| x = GlobalAveragePooling2D()(x) | |
| x = Dropout(0.2)(x) | |
| output = Dense(1, activation="sigmoid")(x) | |
| model = Model(inputs=base_model.input, outputs=output) | |
| return model | |
| # =============================== | |
| # 3. Load Weights | |
| # =============================== | |
| print("Sedang memuat model...") | |
| try: | |
| model = build_model() | |
| model.load_weights("sultan_model.weights.h5") | |
| print("Model berhasil dimuat!") | |
| except Exception as e: | |
| print(f"Error memuat model: {e}") | |
| sys.exit(1) | |
| # Label kelas | |
| class_names = ["normal", "buried"] | |
| # =============================== | |
| # 4. Preprocessing Image | |
| # =============================== | |
| def prepare_image(image_bytes): | |
| try: | |
| img = Image.open(io.BytesIO(image_bytes)) | |
| img = img.convert("RGB") | |
| img = img.resize((224, 224)) | |
| img_array = np.array(img) | |
| img_array = np.expand_dims(img_array, axis=0) | |
| img_array = preprocess_input(img_array) | |
| return img_array | |
| except Exception as e: | |
| print(f"Error preprocessing image: {e}") | |
| return None | |
| # =============================== | |
| # 5. Endpoint Prediksi | |
| # =============================== | |
| async def predict(file: UploadFile = File(...)): | |
| try: | |
| image_bytes = await file.read() | |
| processed_image = prepare_image(image_bytes) | |
| if processed_image is None: | |
| raise HTTPException(status_code=400, detail="Invalid image file") | |
| prediction = model.predict(processed_image) | |
| pred_value = float(prediction[0][0]) | |
| prob_normal = (1 - pred_value) * 100 | |
| prob_buried = pred_value * 100 | |
| predicted_class = "buried" if pred_value > 0.5 else "normal" | |
| return { | |
| "class": predicted_class, | |
| "confidence": max(prob_normal, prob_buried), | |
| "probabilities": { | |
| "normal": prob_normal, | |
| "buried": prob_buried | |
| } | |
| } | |
| except Exception as e: | |
| print(f"CRITICAL ERROR: {e}") | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| # =============================== | |
| # 6. Endpoint Root | |
| # =============================== | |
| def home(): | |
| return { | |
| "message": "Ashoka Hipospadia Classifier API Online 🚀", | |
| "model": "MobileNetV2 Binary Classification", | |
| "classes": class_names | |
| } | |