MdMahamudulHasan's picture
Create app.py
e624b92 verified
Raw
History Blame Contribute Delete
4.88 kB
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:
# Download first then load - more reliable in HF Space
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
# Load models
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."}
# 1. Read and fix image orientation
image_bytes = await image.read()
img = Image.open(io.BytesIO(image_bytes))
img = ImageOps.exif_transpose(img).convert("RGB")
results_data = {}
# 2. YOLO Bounding Box Extraction
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() # [x1, y1, x2, y2]
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": []}
# 3. MobileNet Disease Detection
try:
# Preprocessing
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)
# Inference
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
}
# 4. Integrate YOLO boxes with MobileNet labels
# We use YOLO for WHERE the disease is (with YOLO confidence), but MobileNet for WHAT the disease is.
for box in results_data["yolo"]["boxes"]:
box["label"] = predicted_class # MobileNet's disease name
# Keep YOLO's confidence (box already has "yolo_confidence" key)
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)