File size: 10,392 Bytes
942ebad
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
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)