Spaces:
Sleeping
Sleeping
File size: 7,996 Bytes
b875fc4 c9eaea0 b875fc4 80a40ad c9eaea0 b875fc4 | 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 | from fastapi import FastAPI, File, UploadFile, HTTPException
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
import torch
from torchvision import transforms
from torchvision.models import mobilenet_v3_large, MobileNet_V3_Large_Weights
from PIL import Image
import io
import os
app = FastAPI(title="AgroVision API")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# Load models safely
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
VERIFY_MODEL_PATH = os.path.join(SCRIPT_DIR, "Jverify_model.pth")
DISEASE_MODEL_PATH = os.path.join(SCRIPT_DIR, "Jmodel.pth")
# Global dict for caching
MODELS = {
"verify": None,
"verify_classes": [],
"disease": None,
"disease_classes": []
}
def load_model(path):
if not os.path.exists(path):
return None, []
checkpoint = torch.load(path, map_location=device)
classes = checkpoint['classes']
model = mobilenet_v3_large(weights=MobileNet_V3_Large_Weights.IMAGENET1K_V1)
model.classifier[3] = torch.nn.Linear(model.classifier[3].in_features, len(classes))
model.load_state_dict(checkpoint['mobilenet'])
model = model.to(device)
model.eval()
return model, classes
@app.on_event("startup")
def startup_event():
print("Loading models...")
MODELS["verify"], MODELS["verify_classes"] = load_model(VERIFY_MODEL_PATH)
MODELS["disease"], MODELS["disease_classes"] = load_model(DISEASE_MODEL_PATH)
print("Models loaded successfully!")
test_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
@app.post("/analyze")
async def analyze_image(file: UploadFile = File(...)):
if MODELS["verify"] is None or MODELS["disease"] is None:
raise HTTPException(status_code=500, detail="Models not loaded")
try:
contents = await file.read()
if not contents:
raise ValueError("The server received an empty file (0 bytes). This is usually caused by a proxy stripping the file.")
try:
image = Image.open(io.BytesIO(contents)).convert('RGB')
except Exception as pil_err:
raise ValueError(f"Server received {len(contents)} bytes, but PIL failed to read it as an image. Details: {str(pil_err)}")
image_tensor = test_transform(image).unsqueeze(0).to(device)
except Exception as e:
print(f"FAILED TO LOAD IMAGE: {e}")
raise HTTPException(status_code=400, detail=str(e))
with torch.no_grad():
# First verify if it's a tomato leaf
v_out = MODELS["verify"](image_tensor)
v_probs = torch.softmax(v_out, dim=1).cpu().numpy()[0]
v_idx = v_probs.argmax()
is_tomato = MODELS["verify_classes"][v_idx] == "Tomatoes"
if not is_tomato:
return {
"success": True,
"is_tomato": False,
"confidence": float(v_probs[v_idx]),
"message": "This doesn't seem to be a tomato leaf. Please upload a clear image of a tomato leaf for best results.",
"suggestion": "Make sure the leaf fills most of the frame, is well-lit, and in focus."
}
# It's a tomato, check for diseases
d_out = MODELS["disease"](image_tensor)
d_probs = torch.softmax(d_out, dim=1).cpu().numpy()[0]
d_idx = d_probs.argmax()
disease_name = MODELS["disease_classes"][d_idx]
d_confidence = float(d_probs[d_idx])
# Prepare highly professional insights based on common disease labels
insights = {
"Late blight": (
"Overview: A highly destructive fungal disease (Phytophthora infestans) that thrives in cool, wet weather. "
"Symptoms: Dark, water-soaked spots on leaves that rapidly enlarge, white fungal growth on undersides.\n\n"
"🛡️ Treatment & Solutions:\n"
"• Immediate Action: Entirely remove and destroy infected plant parts immediately. Do not compost.\n"
"• Chemical Control: Apply fungicides containing chlorothalonil, copper fungicide, or mancozeb as scheduled sprays.\n"
"• Preventative Care: Maintain excellent air circulation; water at the base of the plant avoiding foliage; space plants properly."
),
"Early blight": (
"Overview: A common fungal disease (Alternaria solani) appearing on older foliage first.\n"
"Symptoms: Brown or black spots with characteristic concentric rings (target-board appearance) surrounded by yellow halos.\n\n"
"🛡️ Treatment & Solutions:\n"
"• Organic Control: Apply copper-based or sulfur-based fungicides organically approved. Neem oil can be used as a preventative measure.\n"
"• Chemical Control: Use chlorothalonil or azoxystrobin early in the infection cycle.\n"
"• Preventative Care: Crop rotation (3-4 years without nightshades), mulch to prevent soil splashing, and remove bottom leaves touching the soil."
),
"Bacterial spot": (
"Overview: Caused by Xanthomonas bacteria, severely impacting yield in warm, humid conditions.\n"
"Symptoms: Small, dark, water-soaked, scabby spots on fruit and leaves.\n\n"
"🛡️ Treatment & Solutions:\n"
"• Immediate Action: Bacteria are notoriously difficult to control once established. Remove infected crop debris post-harvest.\n"
"• Chemical Control: Preventative copper fungicide sprays combined with mancozeb can suppress the spread.\n"
"• Preventative Care: Use certified disease-free seeds/transplants; avoid working among wet plants to prevent spreading bacteria on hands and tools."
),
"Spider Mites": (
"Overview: Tiny arachnids that congregate on the undersides of leaves, thriving in hot, dry conditions.\n"
"Symptoms: Stippling (tiny yellow or white dots on leaves), fine webbing, and eventual leaf yellowing/dropping.\n\n"
"🛡️ Treatment & Solutions:\n"
"• Organic Control: Knock them off with a strong blast of water. Apply insecticidal soap, Neem oil, or introduce predatory mites (Phytoseiulus persimilis).\n"
"• Chemical Control: Use targeted miticides (abamectin or spiromesifen) if the infestation is severe.\n"
"• Preventative Care: Keep plants well-watered (stress increases susceptibility) and maintain higher localized humidity."
),
"Healthy": (
"Overview: Your tomato plant exhibits strong, vigorous growth with no current signs of widespread pathogens or pests.\n\n"
"🌱 Ongoing Best Practices:\n"
"• Nutrition: Ensure a balanced supply of Phosphorus and Potassium during fruiting.\n"
"• Watering: Maintain consistent soil moisture (avoiding wet-dry extremes to prevent blossom end rot).\n"
"• Maintenance: Continue pruning suckers for indeterminate varieties to maximize airflow and sunlight penetration."
)
}
suggestion = insights.get(disease_name, "Consult a local agricultural expert for treatment options tailored to your region.")
return {
"success": True,
"is_tomato": True,
"prediction": disease_name,
"confidence": d_confidence,
"suggestion": suggestion,
"all_probabilities": {str(cls): float(prob) for cls, prob in zip(MODELS["disease_classes"], d_probs)}
}
if __name__ == "__main__":
uvicorn.run("api:app", host="0.0.0.0", port=8000, reload=True)
|