Spaces:
Sleeping
Sleeping
File size: 5,836 Bytes
06eb7dd 5eda14f 06eb7dd 84d05bd 06eb7dd 0609674 cf380e1 06eb7dd 5eda14f 06eb7dd 5eda14f 06eb7dd 0609674 73709e3 0609674 73709e3 0609674 73709e3 0609674 1baf335 73709e3 5eda14f 06eb7dd 5eda14f 06eb7dd 5eda14f 06eb7dd 5eda14f 73709e3 cf380e1 0609674 73709e3 1baf335 73709e3 0609674 73709e3 5eda14f 0717775 5eda14f 73709e3 5eda14f 1baf335 5eda14f 73709e3 5eda14f 0717775 73709e3 cf380e1 5eda14f 0717775 73709e3 06eb7dd 73709e3 1baf335 73709e3 06eb7dd 5eda14f 73709e3 5eda14f 0609674 06eb7dd 0717775 06eb7dd cf380e1 06eb7dd 1baf335 cf380e1 06eb7dd cf380e1 06eb7dd cf380e1 73709e3 06eb7dd 5eda14f 0609674 5eda14f cf380e1 | 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 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | import os
import io
import logging
import numpy as np
import onnxruntime as ort
import requests
from PIL import Image
from fastapi import FastAPI, UploadFile, File, Form
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import HTMLResponse
import uvicorn
# -------------------------------------------------------
# App Setup
# -------------------------------------------------------
app = FastAPI(title="AgriCare Disease Detection API")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("agricare_api")
# -------------------------------------------------------
# Root → Docs
# -------------------------------------------------------
@app.get("/", response_class=HTMLResponse)
async def root():
return """
<html>
<head>
<meta http-equiv="refresh" content="0; url=/docs">
<title>AgriCare API</title>
</head>
<body>
<p>Redirecting to <a href="/docs">/docs</a>...</p>
</body>
</html>
"""
@app.get("/health")
def health():
return {"status": "ok"}
# -------------------------------------------------------
# Model Setup
# -------------------------------------------------------
MODEL_PATH = "cassava_efficientnetb3_fp16.onnx"
sess = ort.InferenceSession(MODEL_PATH, providers=["CPUExecutionProvider"])
INPUT_NAME = sess.get_inputs()[0].name
MODEL_DTYPE = np.float16 if "float16" in sess.get_inputs()[0].type else np.float32
CLASS_NAMES = [
"Cassava Bacterial Blight",
"Cassava Brown Streak Disease",
"Cassava Green Mottle",
"Cassava Mosaic Disease",
"Healthy Leaf"
]
IMG_SIZE = 300
LOW_CONF_THRESHOLD = 0.60
# -------------------------------------------------------
# English Source of Truth
# -------------------------------------------------------
DISEASE_RECOMMENDATIONS = {
"Cassava Bacterial Blight":
"Cassava Bacterial Blight was detected. Remove and destroy infected plants. "
"Use clean disease-free planting materials. Apply copper-based bactericides "
"such as Copper Oxychloride. Avoid overhead irrigation.",
"Cassava Brown Streak Disease":
"Cassava Brown Streak Disease was detected. There is no chemical cure. "
"Control whiteflies using Imidacloprid or Thiamethoxam. "
"Plant resistant varieties and remove infected plants early.",
"Cassava Green Mottle":
"Cassava Green Mottle was detected. Control aphids and whiteflies using "
"Lambda-cyhalothrin or Cypermethrin. Maintain field hygiene.",
"Cassava Mosaic Disease":
"Cassava Mosaic Disease was detected. There is no direct chemical cure. "
"Control whiteflies using Imidacloprid or Acetamiprid. "
"Uproot and destroy infected plants immediately.",
"Healthy Leaf":
"The cassava leaf is healthy. No treatment is required. "
"Continue regular monitoring and good farm hygiene."
}
# -------------------------------------------------------
# Hugging Face – N-ATLaS
# -------------------------------------------------------
HF_TOKEN = os.getenv("HF_TOKEN")
NATLAS_URL = "https://router.huggingface.co/hf-inference/models/NCAIR1/N-ATLaS"
HEADERS = {
"Authorization": f"Bearer {HF_TOKEN}",
"Content-Type": "application/json"
}
LANGUAGE_MAP = {
"yoruba": "Yoruba language",
"hausa": "Hausa language",
"igbo": "Igbo language"
}
# -------------------------------------------------------
# Utilities
# -------------------------------------------------------
def softmax(x):
e = np.exp(x - np.max(x))
return e / e.sum()
def preprocess(image_bytes):
img = Image.open(io.BytesIO(image_bytes)).convert("RGB")
img = img.resize((IMG_SIZE, IMG_SIZE))
arr = np.array(img).astype("float32") / 255.0
arr = (arr - [0.485, 0.456, 0.406]) / [0.229, 0.224, 0.225]
arr = np.transpose(arr, (2, 0, 1))
return arr[np.newaxis, :].astype(MODEL_DTYPE)
def translate_text(text: str, language: str) -> str:
if language.lower() == "english":
return text
target_lang = LANGUAGE_MAP.get(language.lower(), language)
prompt = (
f"Translate the following agricultural advice into {target_lang}. "
f"Do NOT answer in English.\n\n{text}"
)
r = requests.post(
NATLAS_URL,
headers=HEADERS,
json={"inputs": prompt},
timeout=30
)
r.raise_for_status()
data = r.json()
translated = data[0].get("generated_text", text)
return translated.strip()
# -------------------------------------------------------
# Prediction Endpoint
# -------------------------------------------------------
@app.post("/predict")
async def predict(
file: UploadFile = File(...),
language: str = Form("english")
):
image_bytes = await file.read()
arr = preprocess(image_bytes)
logits = np.squeeze(sess.run(None, {INPUT_NAME: arr})[0])
probs = softmax(logits)
idx = int(np.argmax(probs))
confidence = float(probs[idx])
predicted = CLASS_NAMES[idx]
base_text = DISEASE_RECOMMENDATIONS[predicted]
final_text = translate_text(base_text, language)
return {
"status": "low_confidence" if confidence < LOW_CONF_THRESHOLD else "ok",
"predicted_class": predicted,
"confidence": round(confidence, 4),
"language": language,
"recommendation_text": final_text,
"route_to_expert": confidence < LOW_CONF_THRESHOLD,
"probabilities": probs.tolist()
}
# -------------------------------------------------------
# Run (HF Compatible)
# -------------------------------------------------------
if __name__ == "__main__":
uvicorn.run("app_fastapi:app", host="0.0.0.0", port=7860)
|