| import uvicorn |
| from fastapi import FastAPI, File, UploadFile |
| from fastapi.middleware.cors import CORSMiddleware |
| from ultralytics import YOLO |
| from PIL import Image, ImageOps |
| import io |
| import tensorflow as tf |
| import numpy as np |
| from tensorflow.keras.applications.mobilenet_v3 import preprocess_input |
| import os |
| import traceback |
| from huggingface_hub import hf_hub_download |
|
|
| os.environ['YOLO_CONFIG_DIR'] = '/tmp' |
| os.environ["YOLO_OFFLINE"] = "True" |
| os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2" |
|
|
| app = FastAPI(title="ChiliGuard API") |
|
|
| app.add_middleware( |
| CORSMiddleware, |
| allow_origins=["*"], |
| allow_credentials=True, |
| allow_methods=["*"], |
| allow_headers=["*"], |
| ) |
|
|
| CLASS_NAMES = ['Anthracnose', 'Cercospora', 'Fresh Leaf', 'Leaf Curl'] |
|
|
| yolo_model = None |
| mobilenet_model = None |
|
|
| def load_yolo(): |
| global yolo_model |
| print("🔄 Loading YOLOv11...") |
| try: |
| |
| model_path = hf_hub_download( |
| repo_id="MdMahamudulHasan/chili-leaf-detection", |
| filename="YOLOV11nbest.pt" |
| ) |
| yolo_model = YOLO(model_path) |
| print("✅ YOLOv11 Loaded Successfully!") |
| return True |
| except Exception as e: |
| print("❌ YOLO Load Failed:") |
| print(traceback.format_exc()) |
| return False |
|
|
| def load_mobilenet(): |
| global mobilenet_model |
| print("🔄 Loading MobileNetV3...") |
| try: |
| model_path = hf_hub_download( |
| repo_id="MdMahamudulHasan/chili-leaf-classification", |
| filename="mobilenetv3_chili_leaf_global.keras" |
| ) |
| mobilenet_model = tf.keras.models.load_model(model_path, compile=False) |
| print("✅ MobileNetV3 Loaded Successfully!") |
| return True |
| except Exception as e: |
| print("❌ MobileNet Load Failed:") |
| print(traceback.format_exc()) |
| return False |
|
|
| |
| print("=== Model Loading Started ===") |
| yolo_loaded = load_yolo() |
| mobilenet_loaded = load_mobilenet() |
| print("=== Model Loading Finished ===\n") |
|
|
| @app.get("/") |
| def read_root(): |
| return { |
| "message": "ChiliGuard API is Running", |
| "yolo_status": "Loaded" if yolo_model else "Not Loaded", |
| "mobilenet_status": "Loaded" if mobilenet_model else "Not Loaded" |
| } |
|
|
| @app.post("/predict") |
| async def predict(image: UploadFile = File(...)): |
| if not yolo_model or not mobilenet_model: |
| return {"error": "Models are still initializing. Try again in a few seconds."} |
|
|
| |
| image_bytes = await image.read() |
| img = Image.open(io.BytesIO(image_bytes)) |
| img = ImageOps.exif_transpose(img).convert("RGB") |
|
|
| results_data = {} |
|
|
| |
| try: |
| yolo_results = yolo_model(img, imgsz=640, conf=0.15, verbose=False) |
| yolo_res = yolo_results[0] |
| boxes = [] |
| if hasattr(yolo_res, 'boxes') and yolo_res.boxes is not None: |
| for box in yolo_res.boxes: |
| coords = box.xyxy[0].tolist() |
| conf = float(box.conf.item()) * 100 |
| cls_id = int(box.cls.item()) |
| boxes.append({ |
| "id": cls_id, |
| "bbox": coords, |
| "yolo_label": yolo_res.names[cls_id], |
| "yolo_confidence": conf |
| }) |
| results_data["yolo"] = {"boxes": boxes} |
| except Exception as e: |
| print(f"YOLO inference error: {e}") |
| results_data["yolo"] = {"error": str(e), "boxes": []} |
|
|
| |
| try: |
| |
| img_resized = img.resize((224, 224), Image.NEAREST) |
| img_array = np.asarray(img_resized, dtype=np.float32) |
| img_array = np.expand_dims(img_array, axis=0) |
| img_array = preprocess_input(img_array) |
| |
| |
| dataset_pred = mobilenet_model(img_array, training=False) |
| probability = dataset_pred.numpy()[0] |
| predicted_class_index = np.argmax(probability) |
| predicted_class = CLASS_NAMES[predicted_class_index] |
| confidence = float(probability[predicted_class_index]) * 100 |
| |
| results_data["mobilenet"] = { |
| "disease": predicted_class, |
| "confidence": confidence |
| } |
|
|
| |
| |
| for box in results_data["yolo"]["boxes"]: |
| box["label"] = predicted_class |
| |
|
|
| except Exception as e: |
| print(f"MobileNet inference error: {e}") |
| results_data["mobilenet"] = {"error": str(e)} |
|
|
| return results_data |
|
|
| if __name__ == "__main__": |
| uvicorn.run(app, host="0.0.0.0", port=7860) |
|
|