FarmFriend / app.py
haripatel07's picture
Upload 2 files
942ebad verified
import base64
import os
import io
import joblib
import numpy as np
import requests
import tensorflow as tf
from flask import Flask, request, jsonify
from flask_cors import CORS
from PIL import Image
from tensorflow.keras.applications import MobileNetV2
from tensorflow.keras.layers import GlobalAveragePooling2D, Dense, BatchNormalization, Dropout
from tensorflow.keras.models import Model
from dotenv import load_dotenv
app = Flask(__name__)
CORS(app, resources={r"/*": {"origins": "*"}})
# Force CPU to avoid GPU errors
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
# Load Models
irrigation_model, scaler = joblib.load("models/irrigation_model.pkl")
base_model = MobileNetV2(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
x = Dense(512, activation='relu')(x)
x = BatchNormalization()(x)
x = Dropout(0.2)(x)
prediction = Dense(15, activation='softmax')(x)
plant_model = Model(inputs=base_model.input, outputs=prediction)
plant_model.load_weights("models/plant_disease_model.h5")
# Weather API Key
load_dotenv()
WEATHER_API_KEY = os.getenv("WEATHER_API_KEY")
# Image Preprocessing
def preprocess_image(img):
img = img.resize((224, 224))
img_array = tf.keras.preprocessing.image.img_to_array(img)
img_array = np.expand_dims(img_array, axis=0)
img_array = img_array / 255.0 # Normalize
return img_array
class_names = [
"Pepper Bell - Bacterial Spot",
"Pepper Bell - Healthy",
"Potato - Early Blight",
"Potato - Late Blight",
"Potato - Healthy",
"Tomato - Bacterial Spot",
"Tomato - Early Blight",
"Tomato - Late Blight",
"Tomato - Leaf Mold",
"Tomato - Septoria Leaf Spot",
"Tomato - Spider Mites (Two-Spotted Spider Mite)",
"Tomato - Target Spot",
"Tomato - Yellow Leaf Curl Virus",
"Tomato - Mosaic Virus",
"Tomato - Healthy"
]
causes = {
"Pepper Bell - Bacterial Spot": "Xanthomonas campestris bacteria",
"Potato - Early Blight": "Alternaria solani fungus",
"Potato - Late Blight": "Phytophthora infestans pathogen",
"Tomato - Bacterial Spot": "Xanthomonas campestris bacteria",
"Tomato - Early Blight": "Alternaria solani fungus",
"Tomato - Late Blight": "Phytophthora infestans pathogen",
"Tomato - Leaf Mold": "Passalora fulva fungus",
"Tomato - Septoria Leaf Spot": "Septoria lycopersici fungus",
"Tomato - Spider Mites (Two-Spotted Spider Mite)": "Tetranychus urticae mites",
"Tomato - Target Spot": "Corynespora cassiicola fungus",
"Tomato - Yellow Leaf Curl Virus": "Tomato yellow leaf curl virus (spread by whiteflies)",
"Tomato - Mosaic Virus": "Tobacco mosaic virus (TMV)",
}
symptoms = {
"Pepper Bell - Bacterial Spot": "Small, dark, water-soaked spots on leaves and fruit; can lead to defoliation and reduced yield.",
"Potato - Early Blight": "Brown lesions with concentric rings on lower leaves, leading to defoliation.",
"Potato - Late Blight": "Dark, water-soaked lesions on leaves and stems; rapid plant death in humid conditions.",
"Tomato - Bacterial Spot": "Dark, water-soaked leaf spots that merge and cause yellowing; fruit may have scabby spots.",
"Tomato - Early Blight": "Dark spots with concentric rings on lower leaves; can cause plant defoliation.",
"Tomato - Late Blight": "Large, water-soaked lesions on leaves and stems, leading to rapid plant collapse.",
"Tomato - Leaf Mold": "Yellow patches on upper leaves, fuzzy olive-green mold underneath.",
"Tomato - Septoria Leaf Spot": "Numerous small, circular spots with dark margins on leaves; causes defoliation.",
"Tomato - Spider Mites (Two-Spotted Spider Mite)": "Yellow speckling on leaves, fine webbing, leaf curling, and drying.",
"Tomato - Target Spot": "Circular brown spots with concentric rings, leading to premature leaf drop.",
"Tomato - Yellow Leaf Curl Virus": "Upward curling, yellowing of leaves, and stunted growth.",
"Tomato - Mosaic Virus": "Mottled yellow and green leaf pattern, distorted leaf growth, and reduced fruit production.",
}
treatments = {
"Pepper Bell - Bacterial Spot": "Apply copper-based fungicides. Avoid overhead watering. Use disease-resistant varieties.",
"Pepper Bell - Healthy": "No treatment needed. Maintain proper watering and nutrient balance.",
"Potato - Early Blight": "Use fungicides containing chlorothalonil or mancozeb. Rotate crops and remove infected plants.",
"Potato - Late Blight": "Apply fungicides like metalaxyl or chlorothalonil. Improve air circulation and avoid wet conditions.",
"Potato - Healthy": "No treatment needed. Maintain soil health and proper irrigation.",
"Tomato - Bacterial Spot": "Use copper sprays and bactericides. Avoid handling plants when wet.",
"Tomato - Early Blight": "Apply fungicides such as chlorothalonil or mancozeb. Prune lower leaves and use mulch to prevent soil splash.",
"Tomato - Late Blight": "Use fungicides like copper-based sprays or chlorothalonil. Remove and destroy infected plants.",
"Tomato - Leaf Mold": "Increase air circulation, reduce humidity, and apply fungicides containing chlorothalonil or mancozeb.",
"Tomato - Septoria Leaf Spot": "Use fungicides like copper-based sprays. Remove infected leaves and ensure good airflow.",
"Tomato - Spider Mites (Two-Spotted Spider Mite)": "Use insecticidal soap, neem oil, or predatory mites to control infestations.",
"Tomato - Target Spot": "Apply fungicides such as azoxystrobin or chlorothalonil. Remove infected leaves and avoid overhead watering.",
"Tomato - Yellow Leaf Curl Virus": "Control whiteflies with neem oil or insecticidal soap. Use virus-resistant tomato varieties.",
"Tomato - Mosaic Virus": "Remove infected plants immediately. Control aphids that spread the virus using neem oil or insecticidal soap.",
"Tomato - Healthy": "No treatment needed. Maintain good growing conditions."
}
# API Routes
@app.route("/check_weather", methods=["GET"])
def check_weather():
location = request.args.get("location", "default_location")
url = f"http://api.openweathermap.org/data/2.5/weather?q={location}&appid={WEATHER_API_KEY}&units=metric"
response = requests.get(url)
if response.status_code == 200:
weather_data = response.json()
rain_forecast = "rain" in weather_data["weather"][0]["description"].lower()
altitude = weather_data["coord"]["lat"] * 0.1
return jsonify({
"rain_expected": rain_forecast,
"temperature": weather_data["main"]["temp"],
"pressure": weather_data["main"]["pressure"],
"altitude": altitude
})
return jsonify({"error": "Could not fetch weather data"}), 400
@app.route("/predict/irrigation", methods=["POST"])
def predict_irrigation():
try:
data = request.json
required_fields = ["temperature", "soil_moisture", "pressure", "altitude"]
if not all(k in data for k in required_fields):
return jsonify({"error": "Missing required fields"}), 400
# Convert input values
temp = float(data["temperature"])
soil = float(data["soil_moisture"])
pressure = float(data["pressure"])
altitude = float(data["altitude"])
X = np.array([[temp, pressure, altitude, soil]])
X_scaled = scaler.transform(X)
prediction = irrigation_model.predict(X_scaled)[0]
if prediction in [0, 1]:
if temp > 35:
advice = "High temperature detected, irrigation is strongly recommended to prevent heat stress."
elif pressure < 1000:
advice = "Low atmospheric pressure detected, indicating possible weather changes. Irrigation is advised."
else:
advice = "Soil moisture is low, irrigation is recommended."
elif prediction in [2, 3]:
if temp < 15:
advice = "Low temperature detected, moisture evaporation is slow. No irrigation needed."
elif pressure > 1020:
advice = "High atmospheric pressure detected, reducing evaporation. No irrigation required."
else:
advice = "Soil is sufficiently wet, irrigation is not required."
else:
advice = "Unexpected model output. Please verify input data."
return jsonify({"prediction": advice})
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route("/predict/plant", methods=["POST"])
def predict_plant_disease():
try:
if "image" in request.files:
file = request.files["image"]
img = Image.open(file).convert("RGB")
elif "image" in request.json:
image_data = request.json["image"].split(",")[1]
img = Image.open(io.BytesIO(base64.b64decode(image_data))).convert("RGB")
else:
return jsonify({"error": "No image provided"}), 400
img_array = preprocess_image(img)
prediction = plant_model.predict(img_array)
predicted_class_idx = np.argmax(prediction, axis=1)[0]
confidence = float(np.max(prediction)) * 100
predicted_class = class_names[predicted_class_idx]
if predicted_class == "Pepper Bell - Healthy" or predicted_class == "Tomato - Healthy" or predicted_class == "Potato - Healthy":
return jsonify({"healthy": "Plant is healthy", "confidence": confidence})
cause = causes.get(predicted_class, "Cause details not available")
symptom = symptoms.get(predicted_class, "Symptom details not available")
treatment = treatments.get(predicted_class, "No treatment details available")
return jsonify({
"disease": predicted_class,
"confidence": confidence,
"cause": cause,
"symptoms": symptom,
"treatment": treatment
})
except Exception as e:
return jsonify({"error": str(e)}), 500
# Run the Flask app
if __name__ == "__main__":
port = int(os.environ.get("PORT", 5000))
app.run(debug=False, host="0.0.0.0", port=port)