Spaces:
Runtime error
Runtime error
AdityaAdaki
commited on
Commit
·
ed4e2ee
1
Parent(s):
b0fc518
aaa
Browse files
app.py
CHANGED
@@ -9,10 +9,9 @@ import asyncio
|
|
9 |
import nest_asyncio
|
10 |
import os
|
11 |
|
12 |
-
#
|
13 |
nest_asyncio.apply()
|
14 |
|
15 |
-
# Set page configuration with a custom title, icon, and wide layout
|
16 |
st.set_page_config(
|
17 |
page_title="Plant Disease Classifier 🌱",
|
18 |
page_icon="🌱",
|
@@ -20,33 +19,17 @@ st.set_page_config(
|
|
20 |
initial_sidebar_state="expanded",
|
21 |
)
|
22 |
|
23 |
-
# Custom CSS
|
24 |
custom_css = """
|
25 |
<style>
|
26 |
-
body {
|
27 |
-
|
28 |
-
}
|
29 |
-
|
30 |
-
color: #2c3e50;
|
31 |
-
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
32 |
-
}
|
33 |
-
.stButton>button {
|
34 |
-
background-color: #27ae60;
|
35 |
-
color: white;
|
36 |
-
border: none;
|
37 |
-
padding: 0.5em 1em;
|
38 |
-
border-radius: 5px;
|
39 |
-
font-size: 16px;
|
40 |
-
}
|
41 |
-
.sidebar .sidebar-content {
|
42 |
-
background-image: linear-gradient(#27ae60, #2ecc71);
|
43 |
-
color: white;
|
44 |
-
}
|
45 |
</style>
|
46 |
"""
|
47 |
st.markdown(custom_css, unsafe_allow_html=True)
|
48 |
|
49 |
-
# Dictionary mapping diseases to recommended pesticides (fallback recommendations)
|
50 |
pesticide_recommendations = {
|
51 |
'Bacterial Blight': 'Copper-based fungicides, Streptomycin',
|
52 |
'Red Rot': 'Fungicides containing Mancozeb or Copper',
|
@@ -64,49 +47,26 @@ pesticide_recommendations = {
|
|
64 |
'strip_rust': 'Fungicides containing Azoxystrobin or Propiconazole'
|
65 |
}
|
66 |
|
67 |
-
|
68 |
def recommend_pesticide(predicted_class):
|
69 |
if predicted_class == 'Healthy':
|
70 |
return 'No need for any pesticide, plant is healthy'
|
71 |
return pesticide_recommendations.get(predicted_class, "No recommendation available")
|
72 |
|
73 |
-
|
74 |
@st.cache_resource(show_spinner=False)
|
75 |
-
def
|
76 |
-
custom_objects
|
77 |
-
return tf.keras.models.load_model(model_path, custom_objects=custom_objects, compile=False)
|
78 |
|
79 |
-
|
80 |
-
# Create the Hub KerasLayer (using your model path)
|
81 |
-
hub_layer = hub.KerasLayer(model_path,
|
82 |
-
custom_objects={"KerasLayer": hub.KerasLayer},
|
83 |
-
trainable=False,
|
84 |
-
# You can pass input_shape if needed (for example, (224,224,3))
|
85 |
-
input_shape=input_shape)
|
86 |
-
# Wrap it inside a Lambda layer so that Keras recognizes it as a native layer.
|
87 |
-
return tf.keras.layers.Lambda(lambda x: hub_layer(x), name="hub_lambda")
|
88 |
-
|
89 |
-
|
90 |
-
# Load models (ensure your model paths are correct)
|
91 |
models = {
|
92 |
-
'sugarcane':
|
93 |
-
|
94 |
-
|
95 |
-
'
|
96 |
-
|
97 |
-
]),
|
98 |
-
'cotton': tf.keras.Sequential([
|
99 |
-
load_hub_layer("models/cotton_model.h5", (224, 224, 3))
|
100 |
-
]),
|
101 |
-
'rice': tf.keras.Sequential([
|
102 |
-
load_hub_layer("models/rice.h5", (224, 224, 3))
|
103 |
-
]),
|
104 |
-
'wheat': tf.keras.Sequential([
|
105 |
-
load_hub_layer("models/wheat_model.h5", (224, 224, 3))
|
106 |
-
]),
|
107 |
}
|
108 |
|
109 |
-
# Class names for each model
|
110 |
class_names = {
|
111 |
'sugarcane': ['Bacterial Blight', 'Healthy', 'Red Rot'],
|
112 |
'maize': ['Blight', 'Common_Rust', 'Gray_Leaf_Spot,Healthy'],
|
@@ -115,9 +75,7 @@ class_names = {
|
|
115 |
'wheat': ['Healthy', 'septoria', 'strip_rust'],
|
116 |
}
|
117 |
|
118 |
-
|
119 |
def preprocess_image(image_file):
|
120 |
-
"""Preprocess the uploaded image: open, convert to RGB, resize, normalize, and add batch dimension."""
|
121 |
try:
|
122 |
image = Image.open(image_file).convert("RGB")
|
123 |
image = image.resize((224, 224))
|
@@ -127,7 +85,6 @@ def preprocess_image(image_file):
|
|
127 |
st.error("Error processing image. Please upload a valid image file.")
|
128 |
return None
|
129 |
|
130 |
-
|
131 |
def classify_image(model_name, image_file):
|
132 |
input_image = preprocess_image(image_file)
|
133 |
if input_image is None:
|
@@ -138,26 +95,20 @@ def classify_image(model_name, image_file):
|
|
138 |
recommended_pesticide = recommend_pesticide(predicted_class)
|
139 |
return predicted_class, recommended_pesticide
|
140 |
|
141 |
-
|
142 |
def get_plant_info(disease, plant_type="Unknown"):
|
143 |
-
"""
|
144 |
-
Retrieve detailed plant disease information from LM Studio using a fixed prompt.
|
145 |
-
"""
|
146 |
prompt = f"""
|
147 |
Disease Name: {disease}
|
148 |
Plant Type: {plant_type}
|
149 |
|
150 |
-
Explain this disease in a very simple
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
-
|
155 |
-
-
|
156 |
-
- Severity: How serious is this disease? Does it spread quickly? How much crop damage can it cause?
|
157 |
-
- How It Spreads: How does this disease grow? What will happen if the farmer does nothing?
|
158 |
-
- Treatment & Prevention: What pesticides or sprays should the farmer use and what steps can be taken to prevent the disease?
|
159 |
"""
|
160 |
try:
|
|
|
161 |
response = requests.post(LM_STUDIO_API_URL, json={"messages": [{"role": "user", "content": prompt}]})
|
162 |
response.raise_for_status()
|
163 |
data = response.json()
|
@@ -167,16 +118,12 @@ def get_plant_info(disease, plant_type="Unknown"):
|
|
167 |
st.error("Error retrieving detailed plant info.")
|
168 |
return {"detailed_info": ""}
|
169 |
|
170 |
-
|
171 |
def get_web_pesticide_info(disease, plant_type="Unknown"):
|
172 |
-
"""
|
173 |
-
Query Google Custom Search for updated pesticide recommendations.
|
174 |
-
"""
|
175 |
query = f"site:agrowon.esakal.com {disease} in {plant_type}"
|
176 |
url = "https://www.googleapis.com/customsearch/v1"
|
177 |
params = {
|
178 |
-
"key": GOOGLE_API_KEY,
|
179 |
-
"cx": GOOGLE_CX,
|
180 |
"q": query,
|
181 |
"num": 3
|
182 |
}
|
@@ -186,23 +133,19 @@ def get_web_pesticide_info(disease, plant_type="Unknown"):
|
|
186 |
data = response.json()
|
187 |
if "items" in data and len(data["items"]) > 0:
|
188 |
item = data["items"][0]
|
189 |
-
title
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
except Exception as e:
|
194 |
st.error("Error retrieving web pesticide info.")
|
195 |
return None
|
196 |
|
197 |
-
|
198 |
def get_more_web_info(query):
|
199 |
-
"""
|
200 |
-
Query Google Custom Search for more articles or information.
|
201 |
-
"""
|
202 |
url = "https://www.googleapis.com/customsearch/v1"
|
203 |
params = {
|
204 |
-
"key": GOOGLE_API_KEY,
|
205 |
-
"cx": GOOGLE_CX,
|
206 |
"q": query,
|
207 |
"num": 3
|
208 |
}
|
@@ -213,53 +156,31 @@ def get_more_web_info(query):
|
|
213 |
results = []
|
214 |
if "items" in data:
|
215 |
for item in data["items"]:
|
216 |
-
title
|
217 |
-
|
218 |
-
|
219 |
-
results.append({"title": title, "link": link, "snippet": snippet})
|
220 |
return results
|
221 |
except Exception as e:
|
222 |
st.error("Error retrieving additional articles.")
|
223 |
return []
|
224 |
|
225 |
-
|
226 |
def get_commercial_product_info(recommendation):
|
227 |
-
"""
|
228 |
-
Query Google Custom Search for commercial product details from IndiaMART and Krishisevakendra.
|
229 |
-
"""
|
230 |
indiamart_query = f"site:indiamart.com pesticide '{recommendation}'"
|
231 |
krishi_query = f"site:krishisevakendra.in/products pesticide '{recommendation}'"
|
232 |
indiamart_results = get_more_web_info(indiamart_query)
|
233 |
krishi_results = get_more_web_info(krishi_query)
|
234 |
return indiamart_results + krishi_results
|
235 |
|
236 |
-
|
237 |
-
# LM Studio API endpoint for detailed info (do not change key prompt values)
|
238 |
-
LM_STUDIO_API_URL = os.getenv("LM_STUDIO_API_URL", "http://192.168.56.1:1234/v1/chat/completions")
|
239 |
-
|
240 |
-
# Google Custom Search API key and CX
|
241 |
-
GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
|
242 |
-
GOOGLE_CX = os.getenv("GOOGLE_CX")
|
243 |
-
|
244 |
-
# Initialize session state for language if not already done
|
245 |
if "language" not in st.session_state:
|
246 |
st.session_state.language = "English"
|
247 |
|
248 |
-
# Initialize Google Translator
|
249 |
-
translator = Translator()
|
250 |
-
|
251 |
-
|
252 |
-
# --- Async translation functions ---
|
253 |
async def async_translate_text(text):
|
254 |
translated = await translator.translate(text, src='en', dest='mr')
|
255 |
return translated.text
|
256 |
|
257 |
-
|
258 |
def translate_text(text):
|
259 |
-
"""
|
260 |
-
Translate text to Marathi if selected, otherwise return original text.
|
261 |
-
"""
|
262 |
-
if st.session_state.language == "Marathi":
|
263 |
try:
|
264 |
return asyncio.get_event_loop().run_until_complete(async_translate_text(text))
|
265 |
except Exception as e:
|
@@ -267,9 +188,7 @@ def translate_text(text):
|
|
267 |
return text
|
268 |
return text
|
269 |
|
270 |
-
|
271 |
def main():
|
272 |
-
# Sidebar with settings and file uploader
|
273 |
st.sidebar.title("Settings")
|
274 |
st.sidebar.info("Choose language and plant type, then upload an image to classify the disease.")
|
275 |
language_option = st.sidebar.radio("Language", options=["English", "Marathi"], index=0)
|
@@ -277,37 +196,25 @@ def main():
|
|
277 |
plant_type = st.sidebar.selectbox("Select Plant Type", options=['sugarcane', 'maize', 'cotton', 'rice', 'wheat'])
|
278 |
uploaded_file = st.sidebar.file_uploader("Upload a plant image...", type=["jpg", "jpeg", "png"])
|
279 |
|
280 |
-
# Header with a banner image and introductory text
|
281 |
col1, col2 = st.columns([1, 2])
|
282 |
with col1:
|
283 |
-
st.image("https://via.placeholder.com/
|
284 |
-
use_container_width=True)
|
285 |
with col2:
|
286 |
-
st.title(translate_text("Krushi Mitra
|
287 |
-
st.write(translate_text(
|
288 |
-
"Plant Disease Classification and Pesticide Recommendation.\n\n"
|
289 |
-
"Upload an image of your plant, select the plant type from the sidebar, and click on Classify to get the diagnosis and recommendations."))
|
290 |
|
291 |
if uploaded_file is not None:
|
292 |
-
# Display the uploaded image in an appealing container
|
293 |
st.markdown("---")
|
294 |
st.subheader(translate_text("Uploaded Image"))
|
295 |
st.image(uploaded_file, use_container_width=True)
|
296 |
-
|
297 |
if st.button(translate_text("Classify")):
|
298 |
with st.spinner(translate_text("Classifying...")):
|
299 |
predicted_class, pesticide = classify_image(plant_type, uploaded_file)
|
300 |
if predicted_class:
|
301 |
st.success(translate_text("Classification Complete!"))
|
302 |
-
st.markdown(
|
303 |
-
f"### {translate_text('Predicted Class')} ({plant_type.capitalize()}): {translate_text(predicted_class)}")
|
304 |
st.markdown(f"### {translate_text('Recommended Pesticide')}: {translate_text(pesticide)}")
|
305 |
-
|
306 |
-
# Display results in tabs for a cleaner layout
|
307 |
-
tabs = st.tabs([translate_text("Detailed Info"), translate_text("Commercial Products"),
|
308 |
-
translate_text("More Articles")])
|
309 |
-
|
310 |
-
# Detailed Info Tab
|
311 |
with tabs[0]:
|
312 |
with st.spinner(translate_text("Retrieving detailed plant information...")):
|
313 |
info = get_plant_info(predicted_class, plant_type)
|
@@ -316,43 +223,34 @@ def main():
|
|
316 |
st.markdown(translate_text(info.get("detailed_info")))
|
317 |
else:
|
318 |
st.info(translate_text("Detailed information is not available at the moment."))
|
319 |
-
|
320 |
-
# Inline web pesticide recommendations
|
321 |
web_recommendation = get_web_pesticide_info(predicted_class, plant_type)
|
322 |
if web_recommendation:
|
323 |
st.markdown(translate_text("#### Additional Pesticide Recommendations"))
|
324 |
-
st.markdown(f"{translate_text('Title')}:** {translate_text(web_recommendation['title'])}")
|
325 |
-
st.markdown(f"{translate_text('Summary')}:** {translate_text(web_recommendation['summary'])}")
|
326 |
if web_recommendation['link']:
|
327 |
st.markdown(f"[{translate_text('Read More')}]({web_recommendation['link']})")
|
328 |
else:
|
329 |
st.info(translate_text("No additional pesticide recommendations available."))
|
330 |
-
|
331 |
-
|
332 |
-
# Commercial Products Tab
|
333 |
with tabs[1]:
|
334 |
with st.spinner(translate_text("Retrieving commercial product details...")):
|
335 |
commercial_products = get_commercial_product_info(pesticide)
|
336 |
if commercial_products:
|
337 |
for item in commercial_products:
|
338 |
-
st.markdown(f"{translate_text('Title')}:** {translate_text(item['title'])}")
|
339 |
-
st.markdown(f"{translate_text('Snippet')}:** {translate_text(item['snippet'])}")
|
340 |
if item['link']:
|
341 |
st.markdown(f"[{translate_text('Read More')}]({item['link']})")
|
342 |
st.markdown("---")
|
343 |
else:
|
344 |
st.info(translate_text("No commercial product details available."))
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
# More Articles Tab
|
349 |
with tabs[2]:
|
350 |
with st.spinner(translate_text("Retrieving additional articles...")):
|
351 |
more_info = get_more_web_info(f"{predicted_class} in {plant_type}")
|
352 |
if more_info:
|
353 |
for item in more_info:
|
354 |
-
st.markdown(f"{translate_text('Title')}:** {translate_text(item['title'])}")
|
355 |
-
st.markdown(f"{translate_text('Snippet')}:** {translate_text(item['snippet'])}")
|
356 |
if item['link']:
|
357 |
st.markdown(f"[{translate_text('Read More')}]({item['link']})")
|
358 |
st.markdown("---")
|
@@ -363,6 +261,5 @@ def main():
|
|
363 |
else:
|
364 |
st.info(translate_text("Please upload an image from the sidebar to get started."))
|
365 |
|
366 |
-
|
367 |
-
|
368 |
-
main()
|
|
|
9 |
import nest_asyncio
|
10 |
import os
|
11 |
|
12 |
+
# Allow nested event loops in Streamlit
|
13 |
nest_asyncio.apply()
|
14 |
|
|
|
15 |
st.set_page_config(
|
16 |
page_title="Plant Disease Classifier 🌱",
|
17 |
page_icon="🌱",
|
|
|
19 |
initial_sidebar_state="expanded",
|
20 |
)
|
21 |
|
22 |
+
# Custom CSS styling
|
23 |
custom_css = """
|
24 |
<style>
|
25 |
+
body { background-color: #f8f9fa; }
|
26 |
+
h1, h2, h3, h4 { color: #2c3e50; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
|
27 |
+
.stButton>button { background-color: #27ae60; color: white; border: none; padding: 0.5em 1em; border-radius: 5px; font-size: 16px; }
|
28 |
+
.sidebar .sidebar-content { background-image: linear-gradient(#27ae60, #2ecc71); color: white; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
</style>
|
30 |
"""
|
31 |
st.markdown(custom_css, unsafe_allow_html=True)
|
32 |
|
|
|
33 |
pesticide_recommendations = {
|
34 |
'Bacterial Blight': 'Copper-based fungicides, Streptomycin',
|
35 |
'Red Rot': 'Fungicides containing Mancozeb or Copper',
|
|
|
47 |
'strip_rust': 'Fungicides containing Azoxystrobin or Propiconazole'
|
48 |
}
|
49 |
|
|
|
50 |
def recommend_pesticide(predicted_class):
|
51 |
if predicted_class == 'Healthy':
|
52 |
return 'No need for any pesticide, plant is healthy'
|
53 |
return pesticide_recommendations.get(predicted_class, "No recommendation available")
|
54 |
|
55 |
+
# Load an H5 Keras model directly.
|
56 |
@st.cache_resource(show_spinner=False)
|
57 |
+
def load_h5_model(model_path):
|
58 |
+
return tf.keras.models.load_model(model_path, custom_objects={"KerasLayer": hub.KerasLayer}, compile=False)
|
|
|
59 |
|
60 |
+
# Define models dictionary.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
models = {
|
62 |
+
'sugarcane': load_h5_model("models/sugercane_model.h5"),
|
63 |
+
'maize': load_h5_model("models/maize_model.h5"),
|
64 |
+
'cotton': load_h5_model("models/cotton_model.h5"),
|
65 |
+
'rice': load_h5_model("models/rice.h5"),
|
66 |
+
'wheat': load_h5_model("models/wheat_model.h5"),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
}
|
68 |
|
69 |
+
# Class names for each model (adjust these to match your models)
|
70 |
class_names = {
|
71 |
'sugarcane': ['Bacterial Blight', 'Healthy', 'Red Rot'],
|
72 |
'maize': ['Blight', 'Common_Rust', 'Gray_Leaf_Spot,Healthy'],
|
|
|
75 |
'wheat': ['Healthy', 'septoria', 'strip_rust'],
|
76 |
}
|
77 |
|
|
|
78 |
def preprocess_image(image_file):
|
|
|
79 |
try:
|
80 |
image = Image.open(image_file).convert("RGB")
|
81 |
image = image.resize((224, 224))
|
|
|
85 |
st.error("Error processing image. Please upload a valid image file.")
|
86 |
return None
|
87 |
|
|
|
88 |
def classify_image(model_name, image_file):
|
89 |
input_image = preprocess_image(image_file)
|
90 |
if input_image is None:
|
|
|
95 |
recommended_pesticide = recommend_pesticide(predicted_class)
|
96 |
return predicted_class, recommended_pesticide
|
97 |
|
|
|
98 |
def get_plant_info(disease, plant_type="Unknown"):
|
|
|
|
|
|
|
99 |
prompt = f"""
|
100 |
Disease Name: {disease}
|
101 |
Plant Type: {plant_type}
|
102 |
|
103 |
+
Explain this disease in a very simple way for a farmer. Include:
|
104 |
+
- Symptoms
|
105 |
+
- Causes
|
106 |
+
- Severity
|
107 |
+
- How It Spreads
|
108 |
+
- Treatment & Prevention
|
|
|
|
|
|
|
109 |
"""
|
110 |
try:
|
111 |
+
LM_STUDIO_API_URL = os.getenv("LM_STUDIO_API_URL", "http://192.168.56.1:1234/v1/chat/completions")
|
112 |
response = requests.post(LM_STUDIO_API_URL, json={"messages": [{"role": "user", "content": prompt}]})
|
113 |
response.raise_for_status()
|
114 |
data = response.json()
|
|
|
118 |
st.error("Error retrieving detailed plant info.")
|
119 |
return {"detailed_info": ""}
|
120 |
|
|
|
121 |
def get_web_pesticide_info(disease, plant_type="Unknown"):
|
|
|
|
|
|
|
122 |
query = f"site:agrowon.esakal.com {disease} in {plant_type}"
|
123 |
url = "https://www.googleapis.com/customsearch/v1"
|
124 |
params = {
|
125 |
+
"key": os.getenv("GOOGLE_API_KEY"),
|
126 |
+
"cx": os.getenv("GOOGLE_CX"),
|
127 |
"q": query,
|
128 |
"num": 3
|
129 |
}
|
|
|
133 |
data = response.json()
|
134 |
if "items" in data and len(data["items"]) > 0:
|
135 |
item = data["items"][0]
|
136 |
+
return {"title": item.get("title", "No title available"),
|
137 |
+
"link": item.get("link", "#"),
|
138 |
+
"snippet": item.get("snippet", "No snippet available"),
|
139 |
+
"summary": item.get("snippet", "No snippet available")}
|
140 |
except Exception as e:
|
141 |
st.error("Error retrieving web pesticide info.")
|
142 |
return None
|
143 |
|
|
|
144 |
def get_more_web_info(query):
|
|
|
|
|
|
|
145 |
url = "https://www.googleapis.com/customsearch/v1"
|
146 |
params = {
|
147 |
+
"key": os.getenv("GOOGLE_API_KEY"),
|
148 |
+
"cx": os.getenv("GOOGLE_CX"),
|
149 |
"q": query,
|
150 |
"num": 3
|
151 |
}
|
|
|
156 |
results = []
|
157 |
if "items" in data:
|
158 |
for item in data["items"]:
|
159 |
+
results.append({"title": item.get("title", "No title available"),
|
160 |
+
"link": item.get("link", "#"),
|
161 |
+
"snippet": item.get("snippet", "No snippet available")})
|
|
|
162 |
return results
|
163 |
except Exception as e:
|
164 |
st.error("Error retrieving additional articles.")
|
165 |
return []
|
166 |
|
|
|
167 |
def get_commercial_product_info(recommendation):
|
|
|
|
|
|
|
168 |
indiamart_query = f"site:indiamart.com pesticide '{recommendation}'"
|
169 |
krishi_query = f"site:krishisevakendra.in/products pesticide '{recommendation}'"
|
170 |
indiamart_results = get_more_web_info(indiamart_query)
|
171 |
krishi_results = get_more_web_info(krishi_query)
|
172 |
return indiamart_results + krishi_results
|
173 |
|
174 |
+
translator = Translator()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
175 |
if "language" not in st.session_state:
|
176 |
st.session_state.language = "English"
|
177 |
|
|
|
|
|
|
|
|
|
|
|
178 |
async def async_translate_text(text):
|
179 |
translated = await translator.translate(text, src='en', dest='mr')
|
180 |
return translated.text
|
181 |
|
|
|
182 |
def translate_text(text):
|
183 |
+
if st.session_state.get("language", "English") == "Marathi":
|
|
|
|
|
|
|
184 |
try:
|
185 |
return asyncio.get_event_loop().run_until_complete(async_translate_text(text))
|
186 |
except Exception as e:
|
|
|
188 |
return text
|
189 |
return text
|
190 |
|
|
|
191 |
def main():
|
|
|
192 |
st.sidebar.title("Settings")
|
193 |
st.sidebar.info("Choose language and plant type, then upload an image to classify the disease.")
|
194 |
language_option = st.sidebar.radio("Language", options=["English", "Marathi"], index=0)
|
|
|
196 |
plant_type = st.sidebar.selectbox("Select Plant Type", options=['sugarcane', 'maize', 'cotton', 'rice', 'wheat'])
|
197 |
uploaded_file = st.sidebar.file_uploader("Upload a plant image...", type=["jpg", "jpeg", "png"])
|
198 |
|
|
|
199 |
col1, col2 = st.columns([1, 2])
|
200 |
with col1:
|
201 |
+
st.image("https://via.placeholder.com/150.png?text=Plant", caption=translate_text("Plant Health"), use_container_width=True)
|
|
|
202 |
with col2:
|
203 |
+
st.title(translate_text("Krushi Mitra"))
|
204 |
+
st.write(translate_text("Plant Disease Classification and Pesticide Recommendation.\n\nUpload an image, select plant type, and click on Classify."))
|
|
|
|
|
205 |
|
206 |
if uploaded_file is not None:
|
|
|
207 |
st.markdown("---")
|
208 |
st.subheader(translate_text("Uploaded Image"))
|
209 |
st.image(uploaded_file, use_container_width=True)
|
|
|
210 |
if st.button(translate_text("Classify")):
|
211 |
with st.spinner(translate_text("Classifying...")):
|
212 |
predicted_class, pesticide = classify_image(plant_type, uploaded_file)
|
213 |
if predicted_class:
|
214 |
st.success(translate_text("Classification Complete!"))
|
215 |
+
st.markdown(f"### {translate_text('Predicted Class')} ({plant_type.capitalize()}): {translate_text(predicted_class)}")
|
|
|
216 |
st.markdown(f"### {translate_text('Recommended Pesticide')}: {translate_text(pesticide)}")
|
217 |
+
tabs = st.tabs([translate_text("Detailed Info"), translate_text("Commercial Products"), translate_text("More Articles")])
|
|
|
|
|
|
|
|
|
|
|
218 |
with tabs[0]:
|
219 |
with st.spinner(translate_text("Retrieving detailed plant information...")):
|
220 |
info = get_plant_info(predicted_class, plant_type)
|
|
|
223 |
st.markdown(translate_text(info.get("detailed_info")))
|
224 |
else:
|
225 |
st.info(translate_text("Detailed information is not available at the moment."))
|
|
|
|
|
226 |
web_recommendation = get_web_pesticide_info(predicted_class, plant_type)
|
227 |
if web_recommendation:
|
228 |
st.markdown(translate_text("#### Additional Pesticide Recommendations"))
|
229 |
+
st.markdown(f"**{translate_text('Title')}:** {translate_text(web_recommendation['title'])}")
|
230 |
+
st.markdown(f"**{translate_text('Summary')}:** {translate_text(web_recommendation['summary'])}")
|
231 |
if web_recommendation['link']:
|
232 |
st.markdown(f"[{translate_text('Read More')}]({web_recommendation['link']})")
|
233 |
else:
|
234 |
st.info(translate_text("No additional pesticide recommendations available."))
|
|
|
|
|
|
|
235 |
with tabs[1]:
|
236 |
with st.spinner(translate_text("Retrieving commercial product details...")):
|
237 |
commercial_products = get_commercial_product_info(pesticide)
|
238 |
if commercial_products:
|
239 |
for item in commercial_products:
|
240 |
+
st.markdown(f"**{translate_text('Title')}:** {translate_text(item['title'])}")
|
241 |
+
st.markdown(f"**{translate_text('Snippet')}:** {translate_text(item['snippet'])}")
|
242 |
if item['link']:
|
243 |
st.markdown(f"[{translate_text('Read More')}]({item['link']})")
|
244 |
st.markdown("---")
|
245 |
else:
|
246 |
st.info(translate_text("No commercial product details available."))
|
|
|
|
|
|
|
|
|
247 |
with tabs[2]:
|
248 |
with st.spinner(translate_text("Retrieving additional articles...")):
|
249 |
more_info = get_more_web_info(f"{predicted_class} in {plant_type}")
|
250 |
if more_info:
|
251 |
for item in more_info:
|
252 |
+
st.markdown(f"**{translate_text('Title')}:** {translate_text(item['title'])}")
|
253 |
+
st.markdown(f"**{translate_text('Snippet')}:** {translate_text(item['snippet'])}")
|
254 |
if item['link']:
|
255 |
st.markdown(f"[{translate_text('Read More')}]({item['link']})")
|
256 |
st.markdown("---")
|
|
|
261 |
else:
|
262 |
st.info(translate_text("Please upload an image from the sidebar to get started."))
|
263 |
|
264 |
+
if __name__ == "__main__":
|
265 |
+
main()
|
|
test.py
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import tensorflow as tf
|
2 |
+
|
3 |
+
# Load your H5 model (using custom_objects if necessary)
|
4 |
+
custom_objects = {"KerasLayer": tf.keras.layers.Layer} # adjust if needed
|
5 |
+
model = tf.keras.models.load_model("models/sugercane_model.h5", custom_objects=custom_objects, compile=False)
|
6 |
+
|
7 |
+
# Save in the SavedModel format
|
8 |
+
tf.keras.models.save_model(model, "models/sugercane_model_saved", save_format="tf")
|