Spaces:
Sleeping
Sleeping
File size: 3,496 Bytes
d5d8aa3 181924b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | import io
import numpy as np
import tensorflow as tf
from fastapi import FastAPI, File, UploadFile, Form, HTTPException
from PIL import Image
app = FastAPI(
title="Freshly API",
description="API deteksi kematangan buah dan sayur.",
version="1.0.2"
)
# 1. Konfigurasi Model
CONFIG = {
"banana": ['banana_ripe', 'banana_rotten', 'banana_unripe'],
"mango": ['mango_ripe', 'mango_rotten', 'mango_unripe'],
"orange": ['orange_ripe', 'orange_rotten', 'orange_unripe'],
"chili": ['chili_ripe', 'chili_rotten', 'chili_unripe'],
"paprika": ['paprika_ripe', 'paprika_rotten', 'paprika_unripe'],
"tomato": ['tomato_ripe', 'tomato_rotten', 'tomato_unripe']
}
IMG_SIZE = (224, 224)
MEAN = np.array([0.485, 0.456, 0.406])
STD = np.array([0.229, 0.224, 0.225])
# 2. Memuat Semua Model ke Memori
models = {}
print("Memulai proses pemuatan semua model...")
for fruit_type in CONFIG.keys():
model_folder = f"{fruit_type}_saved_model"
try:
models[fruit_type] = tf.keras.models.load_model(model_folder)
print(f" -> Model {fruit_type.upper()} berhasil dimuat.")
except Exception as e:
print(f" [X] Gagal memuat model {fruit_type}: {e}")
# 3. Fungsi Preprocessing
def preprocess_image(image_bytes):
try:
img = Image.open(io.BytesIO(image_bytes)).convert('RGB')
img = img.resize(IMG_SIZE)
img_array = tf.keras.utils.img_to_array(img)
img_array = img_array / 255.0
img_array = (img_array - MEAN) / STD
img_array = np.expand_dims(img_array, axis=0)
return img_array
except Exception as e:
raise ValueError(f"Gagal memproses gambar: {str(e)}")
# ENDPOINT HEALTH CHECK (Untuk UptimeRobot)
@app.get("/health")
def health_check():
return {"status": "active", "message": "Server is awake and ready!"}
# ENDPOINT PREDIKSI (Satu URL untuk semua model)
@app.post("/predict")
async def predict_fruit(
# Menerima teks (jenis buah) dan file (gambar) dalam satu Form yang sama
fruit_type: str = Form(..., description="Tulis: banana, mango, orange, chili, paprika, atau tomato"),
file: UploadFile = File(...)
):
fruit_type = fruit_type.lower()
# Validasi jenis buah
if fruit_type not in models:
raise HTTPException(
status_code=404,
detail=f"Model '{fruit_type}' tidak ada. Pilihan: {list(models.keys())}"
)
# Validasi file
if not file.content_type.startswith('image/'):
raise HTTPException(status_code=400, detail="File harus berupa gambar.")
try:
contents = await file.read()
img_tensor = preprocess_image(contents)
# Prediksi
active_model = models[fruit_type]
class_names = CONFIG[fruit_type]
predictions = active_model.predict(img_tensor)
pred_index = np.argmax(predictions[0])
confidence = float(predictions[0][pred_index])
return {
"fruit_type": fruit_type,
"filename": file.filename,
"predicted_class": class_names[pred_index],
"confidence": round(confidence * 100, 2),
"all_probabilities": {
class_names[i]: round(float(predictions[0][i]) * 100, 2) for i in range(len(class_names))
}
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) |