# app.py import uvicorn from fastapi import FastAPI, UploadFile, File import tensorflow as tf from tensorflow.keras.preprocessing import image import numpy as np import json import io from PIL import Image from huggingface_hub import hf_hub_download # 1. تعريف مسارات النموذج والتسميات # سيتم تحميلها محليًا بواسطة hf_hub_download MODEL_REPO_ID = "abdulrhmanHelmy/PlantVillage-Classifier" MODEL_FILENAME = "mobilenetv2_finetuned_model.h5" LABELS_FILENAME = "labels.json" IMAGE_SIZE = (224, 224) # 2. تهيئة التطبيق app = FastAPI(title="Plant Disease Classifier API") # تحميل النموذج وملف التسميات عند بدء التشغيل try: # تحميل ملف النموذج من Hugging Face Hub model_path = hf_hub_download(repo_id=MODEL_REPO_ID, filename=MODEL_FILENAME, repo_type="model") model = tf.keras.models.load_model(model_path) # تحميل ملف التسميات labels_path = hf_hub_download(repo_id=MODEL_REPO_ID, filename=LABELS_FILENAME, repo_type="model") with open(labels_path, 'r', encoding='utf-8') as f: idx_to_class = json.load(f) print("✅ النموذج والتسميات تم تحميلهما بنجاح من Hugging Face Hub.") except Exception as e: print(f"❌ فشل تحميل النموذج أو التسميات: {e}") model = None idx_to_class = None # 3. نقطة النهاية للتنبؤ @app.post("/predict") async def predict_image(file: UploadFile = File(...)): if not model: return {"error": "Model failed to load on the server."} try: # قراءة الصورة وتحويلها contents = await file.read() img = Image.open(io.BytesIO(contents)).convert('RGB') # المعالجة المُسبقة (Preprocessing) img = img.resize(IMAGE_SIZE) img_array = image.img_to_array(img) img_array = np.expand_dims(img_array, axis=0) processed_img = tf.keras.applications.mobilenet_v2.preprocess_input(img_array) # التنبؤ predictions = model.predict(processed_img) predicted_index = np.argmax(predictions[0]) confidence = float(np.max(predictions[0])) # ترجمة النتيجة (مفتاح القاموس نصي) predicted_label = idx_to_class.get(str(predicted_index), "Unknown Disease Index") return { "predicted_label": predicted_label, "confidence": f"{confidence * 100:.2f}%" } except Exception as e: return {"error": f"Processing failed: {e}. Check image format."}