Spaces:
Running
Running
Commit
·
f3f9af9
1
Parent(s):
8ae36de
add code
Browse files- Dockerfile +13 -0
- LICENSE +21 -0
- app/main.py +119 -0
- requirements.txt +7 -0
- vercel.json +14 -0
Dockerfile
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.10-slim
|
2 |
+
|
3 |
+
# Set working directory
|
4 |
+
WORKDIR /app
|
5 |
+
|
6 |
+
# Copy files
|
7 |
+
COPY requirements.txt .
|
8 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
9 |
+
|
10 |
+
COPY app ./app
|
11 |
+
|
12 |
+
# Run the FastAPI server using Uvicorn
|
13 |
+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "7860"]
|
LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2025 Shahzad Ali
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
provided to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
app/main.py
ADDED
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from tensorflow import keras
|
2 |
+
from fastapi import FastAPI, File, UploadFile
|
3 |
+
from fastapi.middleware.cors import CORSMiddleware
|
4 |
+
import numpy as np
|
5 |
+
from io import BytesIO
|
6 |
+
from PIL import Image
|
7 |
+
import logging
|
8 |
+
from huggingface_hub import hf_hub_download
|
9 |
+
logging.basicConfig(level=logging.DEBUG)
|
10 |
+
|
11 |
+
app = FastAPI()
|
12 |
+
|
13 |
+
|
14 |
+
app.add_middleware(
|
15 |
+
CORSMiddleware,
|
16 |
+
allow_origins=["*"],
|
17 |
+
allow_credentials=True,
|
18 |
+
allow_methods=["*"],
|
19 |
+
allow_headers=["*"],
|
20 |
+
)
|
21 |
+
|
22 |
+
model_path = hf_hub_download(repo_id="ShahzadAli44/rice_cnn", filename="rice_cnn_model.keras")
|
23 |
+
|
24 |
+
|
25 |
+
try:
|
26 |
+
MODEL = keras.saving.load_model(model_path)
|
27 |
+
logging.info("Model loaded successfully.")
|
28 |
+
except Exception as e:
|
29 |
+
logging.error(f"Error loading model: {e}")
|
30 |
+
MODEL = None
|
31 |
+
|
32 |
+
CLASS_NAMES = [
|
33 |
+
"bacterial_leaf_blight", "brown_spot", "healthy", "leaf_blast",
|
34 |
+
"leaf_scald", "narrow_brown_spot", "rice_hispa", "sheath_blight", "tungro"
|
35 |
+
]
|
36 |
+
|
37 |
+
DISEASE_DETAILS = {
|
38 |
+
"bacterial_leaf_blight": {
|
39 |
+
"symptoms": "Leaves turn yellow with wet-looking spots that spread and dry out.",
|
40 |
+
"treatment": "Use disease-resistant rice seeds. Spray copper-based fungicides. Apply balanced fertilizers with nitrogen and phosphorus."
|
41 |
+
},
|
42 |
+
"brown_spot": {
|
43 |
+
"symptoms": "Small brown spots appear on leaves, which later turn yellow.",
|
44 |
+
"treatment": "Use potassium-rich fertilizers. Spray Mancozeb fungicide. Maintain good drainage to avoid water stress."
|
45 |
+
},
|
46 |
+
"healthy": {
|
47 |
+
"symptoms": "Leaves are green and strong, with no signs of disease.",
|
48 |
+
"treatment": "No treatment needed. Keep the soil healthy by using compost and balanced fertilizers."
|
49 |
+
},
|
50 |
+
"leaf_blast": {
|
51 |
+
"symptoms": "Leaves get white or gray spots that spread and kill the leaf.",
|
52 |
+
"treatment": "Spray Tricyclazole fungicide. Keep the right water level in the field. Use silica-based fertilizers to strengthen plants."
|
53 |
+
},
|
54 |
+
"leaf_scald": {
|
55 |
+
"symptoms": "Leaf edges turn yellow or brown, and the leaf dries up.",
|
56 |
+
"treatment": "Use resistant rice varieties. Avoid too much nitrogen fertilizer. Spray Propiconazole fungicide if needed."
|
57 |
+
},
|
58 |
+
"narrow_brown_spot": {
|
59 |
+
"symptoms": "Thin, dark brown streaks appear on leaves.",
|
60 |
+
"treatment": "Reduce plant overcrowding. Spray Propiconazole fungicide. Use potassium and phosphorus fertilizers to improve plant health."
|
61 |
+
},
|
62 |
+
"rice_hispa": {
|
63 |
+
"symptoms": "Leaves get white scars and small holes due to insect feeding.",
|
64 |
+
"treatment": "Remove infected leaves. Spray Chlorpyrifos insecticide. Keep fields clean to reduce insect attacks."
|
65 |
+
},
|
66 |
+
"sheath_blight": {
|
67 |
+
"symptoms": "White or gray patches appear on the lower part of the plant, leading to weak stems.",
|
68 |
+
"treatment": "Keep enough space between plants. Apply Azoxystrobin fungicide. Use compost and phosphorus-rich fertilizers."
|
69 |
+
},
|
70 |
+
"tungro": {
|
71 |
+
"symptoms": "Plants grow slowly, and leaves turn yellow or orange.",
|
72 |
+
"treatment": "Use virus-free seedlings. Spray insecticides like Imidacloprid to control pests. Apply nitrogen fertilizers to strengthen plants."
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
76 |
+
|
77 |
+
def read_file_as_image(data) -> np.ndarray:
|
78 |
+
try:
|
79 |
+
image = Image.open(BytesIO(data)).convert("RGB")
|
80 |
+
logging.debug(f"Image size: {image.size}")
|
81 |
+
return np.array(image)
|
82 |
+
except Exception as e:
|
83 |
+
logging.error("Error reading image file: %s", str(e))
|
84 |
+
raise ValueError("Invalid image data")
|
85 |
+
|
86 |
+
|
87 |
+
@app.get("/")
|
88 |
+
def home():
|
89 |
+
return {"message": "Agrico API is live!"}
|
90 |
+
|
91 |
+
@app.post("/predict")
|
92 |
+
async def predict(file: UploadFile = File(...)):
|
93 |
+
if MODEL is None:
|
94 |
+
return {"error": "Model is not loaded properly."}
|
95 |
+
|
96 |
+
try:
|
97 |
+
image_data = await file.read()
|
98 |
+
image = read_file_as_image(image_data)
|
99 |
+
img_batch = np.expand_dims(image, 0)
|
100 |
+
logging.debug(f"Image batch shape: {img_batch.shape}")
|
101 |
+
|
102 |
+
predictions = MODEL.predict(img_batch)
|
103 |
+
logging.debug(f"Predictions: {predictions}")
|
104 |
+
|
105 |
+
predicted_class = CLASS_NAMES[np.argmax(predictions[0])]
|
106 |
+
confidence = np.max(predictions[0])
|
107 |
+
if confidence < 0.5:
|
108 |
+
return {"error": "The uploaded image does not appear to be a rice crop leaf."}
|
109 |
+
disease_details = DISEASE_DETAILS.get(predicted_class, {})
|
110 |
+
|
111 |
+
return {
|
112 |
+
'class': predicted_class,
|
113 |
+
'confidence': float(confidence),
|
114 |
+
'symptoms': disease_details.get("symptoms", "No symptoms available."),
|
115 |
+
'treatment': disease_details.get("treatment", "No treatment information available.")
|
116 |
+
}
|
117 |
+
except Exception as e:
|
118 |
+
logging.error("Error during prediction: %s", str(e))
|
119 |
+
return {"error": "An error occurred while processing the image."}
|
requirements.txt
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
fastapi
|
2 |
+
uvicorn
|
3 |
+
numpy
|
4 |
+
pillow
|
5 |
+
tensorflow-cpu
|
6 |
+
huggingface_hub
|
7 |
+
python-multipart
|
vercel.json
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"builds": [
|
3 |
+
{
|
4 |
+
"src": "main.py",
|
5 |
+
"use": "@vercel/python"
|
6 |
+
}
|
7 |
+
],
|
8 |
+
"routes": [
|
9 |
+
{
|
10 |
+
"src": "/(.*)",
|
11 |
+
"dest": "main.py"
|
12 |
+
}
|
13 |
+
]
|
14 |
+
}
|