sujoy0011 commited on
Commit
4aefda0
·
verified ·
1 Parent(s): a04d4b0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +182 -175
app.py CHANGED
@@ -1,175 +1,182 @@
1
- import os
2
- from dotenv import load_dotenv
3
- import google.generativeai as genai
4
- from fastapi import FastAPI, UploadFile, File, HTTPException
5
- from pydantic import BaseModel
6
- from typing import Optional
7
- import tensorflow as tf
8
- import numpy as np
9
- from PIL import Image
10
- import json
11
- import pickle
12
- import pandas as pd
13
-
14
- # Load environment variables from .env file
15
- load_dotenv()
16
-
17
- # Configure Google Gemini API
18
- genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
19
- gemini_model = genai.GenerativeModel("gemini-1.5-flash")
20
-
21
- app = FastAPI()
22
-
23
- # Load models for plant disease prediction
24
- plant_disease_model = tf.keras.models.load_model('plant_disease_model.h5')
25
- class_indices = json.load(open('class_indices.json'))
26
- class_indices = {int(k): v for k, v in class_indices.items()} # Ensure keys are int
27
-
28
- # Load models for crop recommendation
29
- with open("model_useing_Location_Seasion_Area.pkl", "rb") as f:
30
- location_model = pickle.load(f)
31
-
32
- with open("model_useing_npk.pkl", "rb") as f:
33
- npk_model = pickle.load(f)
34
-
35
- # Load unique values from the JSON file
36
- with open("unique_values.json", "r") as f:
37
- unique_values = json.load(f)
38
-
39
- class CropRequest(BaseModel):
40
- state: Optional[str] = None
41
- district: Optional[str] = None
42
- season: Optional[str] = None
43
- area: Optional[float] = None
44
- N: Optional[float] = None
45
- P: Optional[float] = None
46
- K: Optional[float] = None
47
- temperature: Optional[float] = None
48
- humidity: Optional[float] = None
49
- ph: Optional[float] = None
50
- rainfall: Optional[float] = None
51
-
52
- def fetch_gemini_advice(crop, disease):
53
- """Fetches step-by-step cure instructions for the given crop and disease using Google Gemini API."""
54
- if disease.lower() == "healthy":
55
- return "The plant is healthy. No action needed."
56
-
57
- base_prompt = (
58
- f"Provide only step-by-step instructions to cure {disease} in {crop}. "
59
- "Do not include any introduction or description, just list the steps clearly and concisely."
60
- )
61
- response = gemini_model.generate_content(base_prompt)
62
- return response.text if response else "No cure information found."
63
-
64
- def parse_prediction(prediction):
65
- """Separates the crop name and disease name from the prediction."""
66
- if "___" in prediction:
67
- crop, disease = prediction.split("___")
68
- else:
69
- crop, disease = prediction, "Unknown"
70
- return crop, disease
71
-
72
- # Image Preprocessing
73
- def load_and_preprocess_image(image_path, target_size=(224, 224)):
74
- img = Image.open(image_path)
75
- img = img.resize(target_size)
76
- img_array = np.array(img)
77
- img_array = np.expand_dims(img_array, axis=0) # Add batch dimension
78
- img_array = img_array.astype('float32') / 255. # Normalize
79
- return img_array
80
-
81
- # Function to Convert Image to JPG
82
- def convert_to_jpg(image_path: str) -> str:
83
- """
84
- Converts any image to JPG format and returns the path to the converted image.
85
- """
86
- # Open the image
87
- img = Image.open(image_path)
88
-
89
- # Ensure the image is in RGB mode (important for non-RGB images like PNG)
90
- img = img.convert("RGB")
91
-
92
- # Define the new file path (adding .jpg extension)
93
- new_image_path = os.path.splitext(image_path)[0] + ".jpg"
94
-
95
- # Save the image as JPG
96
- img.save(new_image_path, "JPEG")
97
-
98
- # Return the path of the new image
99
- return new_image_path
100
-
101
- # Prediction Function for Plant Disease
102
- def predict_image_class(image_path):
103
- preprocessed_img = load_and_preprocess_image(image_path)
104
- predictions = plant_disease_model.predict(preprocessed_img)
105
- predicted_class_index = np.argmax(predictions, axis=1)[0]
106
- return class_indices[predicted_class_index]
107
-
108
- @app.post('/predict_disease')
109
- async def predict_disease(file: UploadFile = File(...)):
110
- # Save the uploaded file to /tmp directory
111
- file_path = os.path.join('/tmp', file.filename)
112
- with open(file_path, 'wb') as buffer:
113
- buffer.write(await file.read())
114
-
115
- # Convert the image to JPG if it's not already in JPG format
116
- if not file.filename.lower().endswith(".jpg"):
117
- file_path = convert_to_jpg(file_path)
118
-
119
- # Predict the class
120
- prediction = predict_image_class(file_path)
121
- crop, disease = parse_prediction(prediction)
122
-
123
- # Get cure steps from Google Gemini
124
- cure_steps = fetch_gemini_advice(crop, disease)
125
-
126
- # Remove the temporary file
127
- os.remove(file_path)
128
-
129
- return {
130
- "crop": crop,
131
- "predicted_disease": disease,
132
- "cure_steps": cure_steps
133
- }
134
-
135
- # Helper function to get top recommendations from the model
136
- def get_top_recommendations(model, input_data, top_n=3):
137
- if hasattr(model, "predict_proba"):
138
- proba = model.predict_proba(input_data)
139
- top_indices = np.argsort(proba[0])[-top_n:][::-1]
140
- return [model.classes_[i] for i in top_indices]
141
- return model.predict(input_data).tolist()
142
-
143
- @app.post("/predict_crop")
144
- def predict_crop(request: CropRequest):
145
- location_recommendations = []
146
- npk_recommendations = []
147
-
148
- if request.state and request.district and request.season and request.area:
149
- try:
150
- input_data = pd.DataFrame([[request.state, request.district, request.season, np.log1p(request.area)]],
151
- columns=['State_Name', 'District_Name', 'Season', 'Area'])
152
- location_recommendations = get_top_recommendations(location_model, input_data, top_n=3)
153
- except ValueError:
154
- pass # Handle invalid input
155
-
156
- if request.N is not None and request.P is not None and request.K is not None and request.temperature is not None \
157
- and request.humidity is not None and request.ph is not None and request.rainfall is not None:
158
- try:
159
- input_data = np.array([[request.N, request.P, request.K, request.temperature,
160
- request.humidity, request.ph, request.rainfall]])
161
- npk_recommendations = get_top_recommendations(npk_model, input_data, top_n=3)
162
- except ValueError:
163
- pass # Handle invalid input
164
-
165
- location_lower = {crop.lower(): crop for crop in location_recommendations}
166
- common_crops_lower = set(location_lower.keys()) & set(crop.lower() for crop in npk_recommendations)
167
- common_crops = [location_lower[crop] for crop in common_crops_lower]
168
-
169
- location_recommendations = [crop for crop in location_recommendations if crop.lower() not in common_crops_lower]
170
- npk_recommendations = [crop for crop in npk_recommendations if crop.lower() not in common_crops_lower]
171
-
172
- merged_crops = common_crops + npk_recommendations + location_recommendations
173
- final_recommendations = [crop.lower() for crop in merged_crops[:4]]
174
-
175
- return {"recommendations": final_recommendations if final_recommendations else []}
 
 
 
 
 
 
 
 
1
+ import os
2
+ from dotenv import load_dotenv
3
+ import google.generativeai as genai
4
+ from fastapi import FastAPI, UploadFile, File, HTTPException
5
+ from pydantic import BaseModel
6
+ from typing import Optional
7
+ import tensorflow as tf
8
+ import numpy as np
9
+ from PIL import Image
10
+ import json
11
+ import pickle
12
+ import pandas as pd
13
+
14
+ # Load environment variables from .env file
15
+ load_dotenv()
16
+
17
+ # Configure Google Gemini API
18
+ genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
19
+ gemini_model = genai.GenerativeModel("gemini-1.5-flash")
20
+
21
+ app = FastAPI()
22
+
23
+ # Load models for plant disease prediction
24
+ plant_disease_model = tf.keras.models.load_model('plant_disease_model.h5')
25
+ class_indices = json.load(open('class_indices.json'))
26
+ class_indices = {int(k): v for k, v in class_indices.items()} # Ensure keys are int
27
+
28
+ # Load models for crop recommendation
29
+ with open("model_useing_Location_Seasion_Area.pkl", "rb") as f:
30
+ location_model = pickle.load(f)
31
+
32
+ with open("model_useing_npk.pkl", "rb") as f:
33
+ npk_model = pickle.load(f)
34
+
35
+ # Load unique values from the JSON file
36
+ with open("unique_values.json", "r") as f:
37
+ unique_values = json.load(f)
38
+
39
+ class CropRequest(BaseModel):
40
+ state: Optional[str] = None
41
+ district: Optional[str] = None
42
+ season: Optional[str] = None
43
+ area: Optional[float] = None
44
+ N: Optional[float] = None
45
+ P: Optional[float] = None
46
+ K: Optional[float] = None
47
+ temperature: Optional[float] = None
48
+ humidity: Optional[float] = None
49
+ ph: Optional[float] = None
50
+ rainfall: Optional[float] = None
51
+
52
+ def fetch_gemini_advice(crop, disease):
53
+ """Fetches step-by-step cure instructions for the given crop and disease using Google Gemini API."""
54
+ if disease.lower() == "healthy":
55
+ return "The plant is healthy. No action needed."
56
+
57
+ base_prompt = (
58
+ f"Provide only step-by-step instructions to cure {disease} in {crop}. "
59
+ "Do not include any introduction or description, just list the steps clearly and concisely."
60
+ )
61
+ response = gemini_model.generate_content(base_prompt)
62
+ return response.text if response else "No cure information found."
63
+
64
+ def parse_prediction(prediction):
65
+ """Separates the crop name and disease name from the prediction."""
66
+ if "___" in prediction:
67
+ crop, disease = prediction.split("___")
68
+ else:
69
+ crop, disease = prediction, "Unknown"
70
+ return crop, disease
71
+
72
+ # Image Preprocessing
73
+ def load_and_preprocess_image(image_path, target_size=(224, 224)):
74
+ img = Image.open(image_path)
75
+ img = img.resize(target_size)
76
+ img_array = np.array(img)
77
+ img_array = np.expand_dims(img_array, axis=0) # Add batch dimension
78
+ img_array = img_array.astype('float32') / 255. # Normalize
79
+ return img_array
80
+
81
+ # Function to Convert Image to JPG
82
+ def convert_to_jpg(image_path: str) -> str:
83
+ """
84
+ Converts any image to JPG format and returns the path to the converted image.
85
+ """
86
+ # Open the image
87
+ img = Image.open(image_path)
88
+
89
+ # Ensure the image is in RGB mode (important for non-RGB images like PNG)
90
+ img = img.convert("RGB")
91
+
92
+ # Define the new file path (adding .jpg extension)
93
+ new_image_path = os.path.splitext(image_path)[0] + ".jpg"
94
+
95
+ # Save the image as JPG
96
+ img.save(new_image_path, "JPEG")
97
+
98
+ # Return the path of the new image
99
+ return new_image_path
100
+
101
+ # Prediction Function for Plant Disease
102
+ def predict_image_class(image_path):
103
+ preprocessed_img = load_and_preprocess_image(image_path)
104
+ predictions = plant_disease_model.predict(preprocessed_img)
105
+ predicted_class_index = np.argmax(predictions, axis=1)[0]
106
+ return class_indices[predicted_class_index]
107
+
108
+ @app.post('/predict_disease')
109
+ async def predict_disease(file: UploadFile = File(...)):
110
+ # Save the uploaded file to /tmp directory
111
+ file_path = os.path.join('/tmp', file.filename)
112
+ with open(file_path, 'wb') as buffer:
113
+ buffer.write(await file.read())
114
+
115
+ # Convert the image to JPG if it's not already in JPG format
116
+ if not file.filename.lower().endswith(".jpg"):
117
+ file_path = convert_to_jpg(file_path)
118
+
119
+ # Predict the class
120
+ prediction = predict_image_class(file_path)
121
+ crop, disease = parse_prediction(prediction)
122
+
123
+ # Get cure steps from Google Gemini
124
+ cure_steps = fetch_gemini_advice(crop, disease)
125
+
126
+ # Remove the temporary file
127
+ os.remove(file_path)
128
+
129
+ return {
130
+ "crop": crop,
131
+ "predicted_disease": disease,
132
+ "cure_steps": cure_steps
133
+ }
134
+
135
+ # Helper function to get top recommendations from the model
136
+ def get_top_recommendations(model, input_data, top_n=3):
137
+ if hasattr(model, "predict_proba"):
138
+ proba = model.predict_proba(input_data)
139
+ top_indices = np.argsort(proba[0])[-top_n:][::-1]
140
+ return [model.classes_[i] for i in top_indices]
141
+ return model.predict(input_data).tolist()
142
+
143
+ @app.post("/predict_crop")
144
+ def predict_crop(request: CropRequest):
145
+ location_recommendations = []
146
+ npk_recommendations = []
147
+
148
+ if request.state and request.district and request.season and request.area:
149
+ try:
150
+ input_data = pd.DataFrame([[request.state, request.district, request.season, np.log1p(request.area)]],
151
+ columns=['State_Name', 'District_Name', 'Season', 'Area'])
152
+ location_recommendations = get_top_recommendations(location_model, input_data, top_n=3)
153
+ except ValueError:
154
+ pass # Handle invalid input
155
+
156
+ if request.N is not None and request.P is not None and request.K is not None and request.temperature is not None \
157
+ and request.humidity is not None and request.ph is not None and request.rainfall is not None:
158
+ try:
159
+ input_data = np.array([[request.N, request.P, request.K, request.temperature,
160
+ request.humidity, request.ph, request.rainfall]])
161
+ npk_recommendations = get_top_recommendations(npk_model, input_data, top_n=3)
162
+ except ValueError:
163
+ pass # Handle invalid input
164
+
165
+ location_lower = {crop.lower(): crop for crop in location_recommendations}
166
+ common_crops_lower = set(location_lower.keys()) & set(crop.lower() for crop in npk_recommendations)
167
+ common_crops = [location_lower[crop] for crop in common_crops_lower]
168
+
169
+ location_recommendations = [crop for crop in location_recommendations if crop.lower() not in common_crops_lower]
170
+ npk_recommendations = [crop for crop in npk_recommendations if crop.lower() not in common_crops_lower]
171
+
172
+ merged_crops = common_crops + npk_recommendations + location_recommendations
173
+ final_recommendations = [crop.lower() for crop in merged_crops[:4]]
174
+
175
+ return {"recommendations": final_recommendations if final_recommendations else []}
176
+
177
+
178
+
179
+
180
+ @app.get("/")
181
+ def read_root():
182
+ return {"message": "API is running!"}