File size: 17,004 Bytes
f2531f3
 
 
 
00fd610
 
 
 
 
 
 
 
 
 
ed4e2ee
00fd610
 
 
195f610
 
d0b577e
195f610
00fd610
 
db96a98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f2531f3
195f610
00fd610
 
195f610
 
 
 
e3e224d
195f610
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
00fd610
 
 
 
f2531f3
00fd610
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f2531f3
00fd610
ed4e2ee
f2531f3
 
 
 
 
 
00fd610
f2531f3
00fd610
ed4e2ee
 
 
 
 
00fd610
 
f2531f3
00fd610
 
 
 
 
 
 
 
f2531f3
00fd610
 
 
 
 
 
 
 
 
 
f2531f3
00fd610
 
 
 
 
 
 
 
 
 
f2531f3
00fd610
 
 
 
ed4e2ee
 
 
 
 
 
00fd610
 
bd220ad
5da2740
371e770
6f4b334
 
 
 
 
 
a8a4375
371e770
 
 
 
 
 
 
6f4b334
 
 
00fd610
 
 
 
 
 
 
 
 
a8a4375
 
00fd610
 
 
 
 
 
 
 
 
ed4e2ee
 
 
 
00fd610
 
 
 
 
 
 
a8a4375
 
00fd610
 
 
 
 
 
 
 
 
 
ed4e2ee
 
 
00fd610
 
 
 
 
 
 
 
 
 
 
 
ed4e2ee
00fd610
 
 
 
 
 
 
 
ed4e2ee
00fd610
 
 
 
 
 
 
db96a98
00fd610
db96a98
 
a8a4375
 
db96a98
195f610
db96a98
 
 
 
d14f936
 
00fd610
 
 
 
195f610
00fd610
 
 
 
 
ed4e2ee
00fd610
ed4e2ee
00fd610
 
 
 
 
 
 
 
 
 
 
a8a4375
 
00fd610
 
 
 
 
 
 
 
 
a8a4375
 
00fd610
 
 
 
 
 
 
 
 
 
a8a4375
 
00fd610
 
 
 
 
 
 
 
 
 
ed4e2ee
a8a4375
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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
import os
# Force the use of legacy Keras (Keras 2 behavior) so that hub.KerasLayer is recognized properly.
os.environ["TF_USE_LEGACY_KERAS"] = "1"

import streamlit as st
import tensorflow as tf
import tensorflow_hub as hub
import numpy as np
from PIL import Image
import requests
from googletrans import Translator
import asyncio
import nest_asyncio

# Allow nested event loops in Streamlit
nest_asyncio.apply()

st.set_page_config(
        page_title="Krushi Mitra 🌱",
        page_icon="🌱",
        layout="wide",  # Change to centered layout
        initial_sidebar_state="auto"  # Auto-hide sidebar on small screens
)

# Improved translations dictionary
TRANSLATIONS = {
    # Common Website Words
    "Upload": "अपलोड करा",
    "Select": "निवडा",
    "Image": "प्रतिमा",
    "Settings": "सेटिंग्ज",
    "Language": "भाषा",
    "Plant": "पीक",
    "Disease": "रोग",
    "Classify": "वर्गीकृत करा",
    "Recommended": "शिफारस केलेला",
    "More": "अधिक",
    "Read": "वाचा",
    
    # Specific Phrases
    "Krushi Mitra": "कृषी मित्र",
    "Plant Disease Classification and Pesticide Recommendation": "पीक रोग वर्गीकरण आणि कीटकनाशक शिफारस",
    "Upload a plant image...": "पीक प्रतिमा अपलोड करा...",
    "Select an image of your plant to detect diseases": "रोग शोधण्यासाठी आपल्या पीकाची प्रतिमा निवडा",
    "Uploaded Image": "अपलोड केलेली प्रतिमा",
    "Classifying...": "वर्गीकरण करत आहे...",
    "Classification Complete!": "वर्गीकरण पूर्ण झाले!",
    "Predicted Class": "अनुमानित वर्ग",
    "Recommended Pesticide": "शिफारस केलेला कीटकनाशक",
    "Detailed Info": "विस्तृत माहिती",
    "Commercial Products": "व्यावसायिक उत्पादने",
    "More Articles": "अधिक लेख",
    "Retrieving detailed plant information...": "पीकाची विस्तृत माहिती मिळवत आहे...",
    "Detailed Plant Disease Information": "पीक रोगाची विस्तृत माहिती",
    "Detailed information is not available at the moment.": "सध्या विस्तृत माहिती उपलब्ध नाही.",
    "Additional Pesticide Recommendations": "अतिरिक्त कीटकनाशक शिफारसी",
    "Title": "शीर्षक",
    "Summary": "सारांश",
    "Retrieving commercial product details...": "व्यावसायिक उत्पादन तपशील मिळवत आहे...",
    "No commercial product details available.": "कोणतेही व्यावसायिक उत्पादन तपशील उपलब्ध नाहीत.",
    "Retrieving additional articles...": "अतिरिक्त लेख मिळवत आहे...",
    "No additional articles available.": "अतिरिक्त लेख उपलब्ध नाहीत.",
    "Error in classification. Please try again.": "वर्गीकरणमध्ये त्रुटी. कृपया पुन्हा प्रयत्न करा.",
    "Please upload an image from the sidebar to get started.": "सुरुवात करण्यासाठी कृपया बाजूच्या पट्टीतून एक प्रतिमा अपलोड करा."
}

def translate_text(text):
    if st.session_state.get("language", "English") == "Marathi":
        return TRANSLATIONS.get(text, text)
    return text

# Custom CSS for styling
# Update custom CSS
custom_css = """
<style>
body { 
    background-color: #f0f2f6; 
    font-family: 'Inter', sans-serif; 
}
.stApp {  
    margin: 0 auto; 
}
.stButton>button { 
    background-color: #2ecc71; 
    color: white; 
    border: none; 
    padding: 10px 20px; 
    border-radius: 8px; 
    font-weight: bold; 
    transition: all 0.3s ease;
}
.stButton>button:hover {
    background-color: #27ae60;
    transform: scale(1.05);
}
.stTabs [data-baseweb="tab-list"] {
    background-color: #ecf0f1;
    border-radius: 10px;
}
.stTabs [data-baseweb="tab"] {
    padding: 10px 15px;
    font-weight: 600;
}
</style>
"""
st.markdown(custom_css, unsafe_allow_html=True)

# Dictionary mapping diseases to recommended pesticides
pesticide_recommendations = {
    'Bacterial Blight': 'Copper-based fungicides, Streptomycin',
    'Red Rot': 'Fungicides containing Mancozeb or Copper',
    'Blight': 'Fungicides containing Chlorothalonil',
    'Common_Rust': 'Fungicides containing Azoxystrobin or Propiconazole',
    'Gray_Leaf_Spot,Healthy': 'Fungicides containing Azoxystrobin or Propiconazole',
    'Bacterial blight': 'Copper-based fungicides, Streptomycin',
    'curl_virus': 'Insecticides such as Imidacloprid or Pyrethroids',
    'fussarium_wilt': 'Soil fumigants, Fungicides containing Thiophanate-methyl',
    'Bacterial_blight': 'Copper-based fungicides, Streptomycin',
    'Blast': 'Fungicides containing Tricyclazole or Propiconazole',
    'Brownspot': 'Fungicides containing Azoxystrobin or Propiconazole',
    'Tungro': 'Insecticides such as Neonicotinoids or Pyrethroids',
    'septoria': 'Fungicides containing Azoxystrobin or Propiconazole',
    'strip_rust': 'Fungicides containing Azoxystrobin or Propiconazole'
}

def recommend_pesticide(predicted_class):
    if predicted_class == 'Healthy':
        return 'No need for any pesticide, plant is healthy'
    return pesticide_recommendations.get(predicted_class, "No recommendation available")

# Use st.cache_resource to load H5 models.
@st.cache_resource(show_spinner=False)
def load_h5_model(model_path):
    # This will load your H5 Keras model (which contains hub.KerasLayer)
    return tf.keras.models.load_model(
        model_path,
        custom_objects={"KerasLayer": hub.KerasLayer},
        compile=False
    )

# Define your models dictionary (update paths as needed)
models = {
    'sugarcane': load_h5_model("models/sugercane_model.h5"),
    'maize': load_h5_model("models/maize_model.h5"),
    'cotton': load_h5_model("models/cotton_model.h5"),
    'rice': load_h5_model("models/rice.h5"),
    'wheat': load_h5_model("models/wheat_model.h5"),
}

# Class names for each model (ensure these match the order of your model outputs)
class_names = {
    'sugarcane': ['Bacterial Blight', 'Healthy', 'Red Rot'],
    'maize': ['Blight', 'Common_Rust', 'Gray_Leaf_Spot,Healthy'],
    'cotton': ['Bacterial blight', 'curl_virus', 'fussarium_wilt', 'Healthy'],
    'rice': ['Bacterial_blight', 'Blast', 'Brownspot', 'Tungro'],
    'wheat': ['Healthy', 'septoria', 'strip_rust'],
}

# Preprocess the uploaded image
def preprocess_image(image_file):
    try:
        image = Image.open(image_file).convert("RGB")
        image = image.resize((224, 224))
        img_array = np.array(image).astype("float32") / 255.0
        return np.expand_dims(img_array, axis=0)
    except Exception as e:
        st.error("Error processing image. Please upload a valid image file.")
        return None

# Classify the image using the appropriate model
def classify_image(model_name, image_file):
    input_image = preprocess_image(image_file)
    if input_image is None:
        return None, None
    predictions = models[model_name].predict(input_image)
    predicted_index = np.argmax(predictions)
    predicted_class = class_names[model_name][predicted_index]
    recommended_pesticide = recommend_pesticide(predicted_class)
    return predicted_class, recommended_pesticide

# (Optional) Retrieve detailed plant information from LM Studio
def get_plant_info(disease, plant_type="Unknown"):
    prompt = f"""
    Disease Name: {disease}
    Plant Type: {plant_type}
    Explain this disease in a very simple way for a farmer. Include:
    - Symptoms
    - Causes
    - Severity
    - How It Spreads
    - Treatment & Prevention
    """
    try:
        API_URL = "https://api-inference.huggingface.co/models/meta-llama/Llama-3.2-1B-Instruct/v1/chat/completions"
        headers = {"Authorization": f"Bearer {os.getenv('HUGGINGFACE_API_TOKEN')}"}
        try:
            data = {
            "messages": [
                {"role": "system", "content": "You are a helpful assistant."},
                {"role": "user", "content": prompt},
            ]
        }
            response = requests.post(API_URL, headers=headers, json=data)
            response.raise_for_status()
            print("Response:", data)
        except requests.exceptions.HTTPError as http_err:
            print("HTTP error occurred:", http_err)
            print("Response Content:", response.content)
        except Exception as e:
            print("Other error occurred:", str(e))
        response_data  = response.json()
        detailed_info = response_data.get("choices", [{}])[0].get("message", {}).get("content", "")

        return {"detailed_info": detailed_info}
    except Exception as e:
        st.error("Error retrieving detailed plant info.")
        return {"detailed_info": ""}

def get_web_pesticide_info(disease, plant_type="Unknown"):
    query = f"site:agrowon.esakal.com {disease} in {plant_type}"
    url = "https://www.googleapis.com/customsearch/v1"
    params = {
        "key": os.getenv("GOOGLE_API_KEY"),
        "cx": os.getenv("GOOGLE_CX"),
        "q": query,
        "num": 3
    }
    try:
        response = requests.get(url, params=params)
        response.raise_for_status()
        data = response.json()
        if "items" in data and len(data["items"]) > 0:
            item = data["items"][0]
            return {"title": item.get("title", "No title available"),
                    "link": item.get("link", "#"),
                    "snippet": item.get("snippet", "No snippet available"),
                    "summary": item.get("snippet", "No snippet available")}
    except Exception as e:
        st.error("Error retrieving web pesticide info.")
    return None

def get_more_web_info(query):
    url = "https://www.googleapis.com/customsearch/v1"
    params = {
        "key": os.getenv("GOOGLE_API_KEY"),
        "cx": os.getenv("GOOGLE_CX"),
        "q": query,
        "num": 3
    }
    try:
        response = requests.get(url, params=params)
        response.raise_for_status()
        data = response.json()
        results = []
        if "items" in data:
            for item in data["items"]:
                results.append({"title": item.get("title", "No title available"),
                                "link": item.get("link", "#"),
                                "snippet": item.get("snippet", "No snippet available")})
        return results
    except Exception as e:
        st.error("Error retrieving additional articles.")
    return []

def get_commercial_product_info(recommendation):
    indiamart_query = f"site:indiamart.com pesticide '{recommendation}'"
    krishi_query = f"site:krishisevakendra.in/products pesticide '{recommendation}'"
    indiamart_results = get_more_web_info(indiamart_query)
    krishi_results = get_more_web_info(krishi_query)
    return indiamart_results + krishi_results

translator = Translator()
if "language" not in st.session_state:
    st.session_state.language = "English"

async def async_translate_text(text):
    translated = await translator.translate(text, src='en', dest='mr')
    return translated.text

def translate_text(text):
    if st.session_state.get("language", "English") == "Marathi":
        try:
            return asyncio.get_event_loop().run_until_complete(async_translate_text(text))
        except Exception as e:
            st.error("Translation error.")
            return text
    return text


def main():
    st.sidebar.title(translate_text("Settings"))
    st.sidebar.info(translate_text("Choose language and plant type, then upload an image to classify the disease."))
    language_option = st.sidebar.radio(translate_text("Language"), options=["English", "Marathi"], index=0)
    st.session_state.language = language_option
    plant_type = st.sidebar.selectbox(translate_text("Select Plant Type"), options=['sugarcane', 'maize', 'cotton', 'rice', 'wheat'])
    uploaded_file = st.sidebar.file_uploader(
        translate_text("Upload a plant image..."), 
        type=["jpg", "jpeg", "png"],
        help=translate_text("Select an image of your plant to detect diseases")
    )
    st.title(translate_text("Krushi Mitra"))
    st.write(translate_text("Plant Disease Classification and Pesticide Recommendation.\n\nUpload an image, select plant type, and click on Classify."))

    if uploaded_file is not None:
        st.markdown("---")
        st.subheader(translate_text("Uploaded Image"))
        st.image(uploaded_file, width=300)
        if st.button(translate_text("Classify")):
            with st.spinner(translate_text("Classifying...")):
                predicted_class, pesticide = classify_image(plant_type, uploaded_file)
            if predicted_class:
                st.success(translate_text("Classification Complete!"))
                st.markdown(f"### {translate_text('Predicted Class')} ({plant_type.capitalize()}): {translate_text(predicted_class)}")
                st.markdown(f"### {translate_text('Recommended Pesticide')}: {translate_text(pesticide)}")
                tabs = st.tabs([translate_text("Detailed Info"), translate_text("Commercial Products"), translate_text("More Articles")])
                with tabs[0]:
                    with st.spinner(translate_text("Retrieving detailed plant information...")):
                        info = get_plant_info(predicted_class, plant_type)
                    if info and info.get("detailed_info"):
                        st.markdown(translate_text("#### Detailed Plant Disease Information"))
                        st.markdown(translate_text(info.get("detailed_info")))
                    else:
                        st.info(translate_text("Detailed information is not available at the moment."))
                    web_recommendation = get_web_pesticide_info(predicted_class, plant_type)
                    if web_recommendation:
                        st.markdown(translate_text("#### Additional Pesticide Recommendations"))
                        st.markdown(f"{translate_text('Title')}:** {translate_text(web_recommendation['title'])}")
                        st.markdown(f"{translate_text('Summary')}:** {translate_text(web_recommendation['summary'])}")
                        if web_recommendation['link']:
                            st.markdown(f"[{translate_text('Read More')}]({web_recommendation['link']})")
                    else:
                        st.info(translate_text("No additional pesticide recommendations available."))
                with tabs[1]:
                    with st.spinner(translate_text("Retrieving commercial product details...")):
                        commercial_products = get_commercial_product_info(pesticide)
                    if commercial_products:
                        for item in commercial_products:
                            st.markdown(f"{translate_text('Title')}:** {translate_text(item['title'])}")
                            st.markdown(f"{translate_text('Snippet')}:** {translate_text(item['snippet'])}")
                            if item['link']:
                                st.markdown(f"[{translate_text('Read More')}]({item['link']})")
                            st.markdown("---")
                    else:
                        st.info(translate_text("No commercial product details available."))
                with tabs[2]:
                    with st.spinner(translate_text("Retrieving additional articles...")):
                        more_info = get_more_web_info(f"{predicted_class} in {plant_type}")
                    if more_info:
                        for item in more_info:
                            st.markdown(f"{translate_text('Title')}:** {translate_text(item['title'])}")
                            st.markdown(f"{translate_text('Snippet')}:** {translate_text(item['snippet'])}")
                            if item['link']:
                                st.markdown(f"[{translate_text('Read More')}]({item['link']})")
                            st.markdown("---")
                    else:
                        st.info(translate_text("No additional articles available."))
            else:
                st.error(translate_text("Error in classification. Please try again."))
    else:
        st.info(translate_text("Please upload an image from the sidebar to get started."))

if __name__ == "__main__":
    main()