MuhammmadRizwanRizwan commited on
Commit
8beeb1a
·
verified ·
1 Parent(s): 52ed7df

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +1104 -79
app.py CHANGED
@@ -1,32 +1,135 @@
1
 
2
- import streamlit as st
3
- import numpy as np
4
- import cv2
5
- import warnings
6
- import os
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
- # Suppress warnings
9
- warnings.filterwarnings("ignore", category=FutureWarning)
10
- warnings.filterwarnings("ignore", category=UserWarning)
11
 
12
- # Try importing TensorFlow
13
- try:
14
- from tensorflow.keras.models import load_model
15
- from tensorflow.keras.preprocessing import image
16
- except ImportError:
17
- st.error("Failed to import TensorFlow. Please make sure it's installed correctly.")
18
 
19
- # Try importing PyTorch and Detectron2
20
- try:
21
- import torch
22
- import detectron2
23
- except ImportError:
24
- with st.spinner("Installing PyTorch and Detectron2..."):
25
- os.system("pip install torch torchvision")
26
- os.system("pip install 'git+https://github.com/facebookresearch/detectron2.git'")
27
 
28
- import torch
29
- import detectron2
30
 
31
 
32
  import streamlit as st
@@ -34,13 +137,23 @@ import numpy as np
34
  import cv2
35
  import torch
36
  import os
37
- from PIL import Image
 
 
 
 
 
 
 
 
 
38
  from tensorflow.keras.models import load_model
39
  from tensorflow.keras.preprocessing import image
40
  from detectron2.engine import DefaultPredictor
41
  from detectron2.config import get_cfg
42
  from detectron2.utils.visualizer import Visualizer
43
  from detectron2.data import MetadataCatalog
 
44
 
45
  # Suppress warnings
46
  import warnings
@@ -48,80 +161,988 @@ import tensorflow as tf
48
  warnings.filterwarnings("ignore")
49
  tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  @st.cache_resource
52
  def load_models():
53
- model_name = load_model('name_model_inception.h5')
54
- model_quality = load_model('type_model_inception.h5')
 
 
 
 
55
  return model_name, model_quality
56
 
57
- model_name, model_quality = load_models()
58
-
59
- # Detectron2 setup
60
  @st.cache_resource
61
  def load_detectron_model(fruit_name):
62
- cfg = get_cfg()
63
- config_path = os.path.join(f"{fruit_name.lower()}_config.yaml")
64
- cfg.merge_from_file(config_path)
65
- model_path = os.path.join(f"{fruit_name}_model.pth")
66
- cfg.MODEL.WEIGHTS = model_path
67
- cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5
68
- cfg.MODEL.DEVICE = 'cpu'
69
- predictor = DefaultPredictor(cfg)
 
 
70
  return predictor, cfg
71
 
72
  # Labels
73
  label_map_name = {
74
  0: "Banana", 1: "Cucumber", 2: "Grape", 3: "Kaki", 4: "Papaya",
75
  5: "Peach", 6: "Pear", 7: "Peeper", 8: "Strawberry", 9: "Watermelon",
76
- 10: "tomato"
77
  }
 
78
  label_map_quality = {0: "Good", 1: "Mild", 2: "Rotten"}
79
 
80
- def predict_fruit(img):
81
- # Preprocess image
82
- img = Image.fromarray(img.astype('uint8'), 'RGB')
83
- img = img.resize((224, 224))
84
- x = image.img_to_array(img)
85
- x = np.expand_dims(x, axis=0)
86
- x = x / 255.0
 
 
 
 
 
 
 
87
 
88
- # Predict
89
- pred_name = model_name.predict(x)
90
- pred_quality = model_quality.predict(x)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
- predicted_name = label_map_name[np.argmax(pred_name, axis=1)[0]]
93
- predicted_quality = label_map_quality[np.argmax(pred_quality, axis=1)[0]]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
- return predicted_name, predicted_quality, img
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
 
97
  def main():
98
- st.title("Automated Fruits Monitoring System")
99
- st.write("Upload an image of a fruit to detect its type, quality, and potential damage.")
100
-
101
- uploaded_file = st.file_uploader("Choose a fruit image...", type=["jpg", "jpeg", "png"])
102
-
103
- if uploaded_file is not None:
104
- image = Image.open(uploaded_file)
105
- st.image(image, caption="Uploaded Image", use_column_width=True)
106
-
107
- if st.button("Analyze"):
108
- predicted_name, predicted_quality, img = predict_fruit(np.array(image))
109
-
110
- st.write(f"Fruits Type Detection: {predicted_name}")
111
- st.write(f"Fruits Quality Classification: {predicted_quality}")
112
-
113
- if predicted_name.lower() in ["kaki", "tomato", "strawberry", "peeper", "pear", "peach", "papaya", "watermelon", "grape", "banana", "cucumber"] and predicted_quality in ["Mild", "Rotten"]:
114
- st.write("Segmentation of Defective Region:")
115
- try:
116
- predictor, cfg = load_detectron_model(predicted_name)
117
- outputs = predictor(cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR))
118
- v = Visualizer(np.array(img), MetadataCatalog.get(cfg.DATASETS.TRAIN[0]), scale=0.8)
119
- out = v.draw_instance_predictions(outputs["instances"].to("cpu"))
120
- st.image(out.get_image(), caption="Damage Detection Result", use_column_width=True)
121
- except Exception as e:
122
- st.error(f"Error in damage detection: {str(e)}")
123
- else:
124
- st.write("No damage detection performed for this fruit or quality level.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
 
126
  if __name__ == "__main__":
127
  main()
@@ -129,6 +1150,10 @@ if __name__ == "__main__":
129
 
130
 
131
 
 
 
 
 
132
  # import streamlit as st
133
  # import numpy as np
134
  # import cv2
 
1
 
2
+ # import streamlit as st
3
+ # import numpy as np
4
+ # import cv2
5
+ # import warnings
6
+ # import os
7
+
8
+ # # Suppress warnings
9
+ # warnings.filterwarnings("ignore", category=FutureWarning)
10
+ # warnings.filterwarnings("ignore", category=UserWarning)
11
+
12
+ # # Try importing TensorFlow
13
+ # try:
14
+ # from tensorflow.keras.models import load_model
15
+ # from tensorflow.keras.preprocessing import image
16
+ # except ImportError:
17
+ # st.error("Failed to import TensorFlow. Please make sure it's installed correctly.")
18
+
19
+ # # Try importing PyTorch and Detectron2
20
+ # try:
21
+ # import torch
22
+ # import detectron2
23
+ # except ImportError:
24
+ # with st.spinner("Installing PyTorch and Detectron2..."):
25
+ # os.system("pip install torch torchvision")
26
+ # os.system("pip install 'git+https://github.com/facebookresearch/detectron2.git'")
27
+
28
+ # import torch
29
+ # import detectron2
30
+
31
+
32
+ # import streamlit as st
33
+ # import numpy as np
34
+ # import cv2
35
+ # import torch
36
+ # import os
37
+ # from PIL import Image
38
+ # from tensorflow.keras.models import load_model
39
+ # from tensorflow.keras.preprocessing import image
40
+ # from detectron2.engine import DefaultPredictor
41
+ # from detectron2.config import get_cfg
42
+ # from detectron2.utils.visualizer import Visualizer
43
+ # from detectron2.data import MetadataCatalog
44
+
45
+ # # Suppress warnings
46
+ # import warnings
47
+ # import tensorflow as tf
48
+ # warnings.filterwarnings("ignore")
49
+ # tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)
50
+
51
+ # @st.cache_resource
52
+ # def load_models():
53
+ # model_name = load_model('name_model_inception.h5')
54
+ # model_quality = load_model('type_model_inception.h5')
55
+ # return model_name, model_quality
56
+
57
+ # model_name, model_quality = load_models()
58
+
59
+ # # Detectron2 setup
60
+ # @st.cache_resource
61
+ # def load_detectron_model(fruit_name):
62
+ # cfg = get_cfg()
63
+ # config_path = os.path.join(f"{fruit_name.lower()}_config.yaml")
64
+ # cfg.merge_from_file(config_path)
65
+ # model_path = os.path.join(f"{fruit_name}_model.pth")
66
+ # cfg.MODEL.WEIGHTS = model_path
67
+ # cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5
68
+ # cfg.MODEL.DEVICE = 'cpu'
69
+ # predictor = DefaultPredictor(cfg)
70
+ # return predictor, cfg
71
+
72
+ # # Labels
73
+ # label_map_name = {
74
+ # 0: "Banana", 1: "Cucumber", 2: "Grape", 3: "Kaki", 4: "Papaya",
75
+ # 5: "Peach", 6: "Pear", 7: "Peeper", 8: "Strawberry", 9: "Watermelon",
76
+ # 10: "tomato"
77
+ # }
78
+ # label_map_quality = {0: "Good", 1: "Mild", 2: "Rotten"}
79
+
80
+ # def predict_fruit(img):
81
+ # # Preprocess image
82
+ # img = Image.fromarray(img.astype('uint8'), 'RGB')
83
+ # img = img.resize((224, 224))
84
+ # x = image.img_to_array(img)
85
+ # x = np.expand_dims(x, axis=0)
86
+ # x = x / 255.0
87
+
88
+ # # Predict
89
+ # pred_name = model_name.predict(x)
90
+ # pred_quality = model_quality.predict(x)
91
+
92
+ # predicted_name = label_map_name[np.argmax(pred_name, axis=1)[0]]
93
+ # predicted_quality = label_map_quality[np.argmax(pred_quality, axis=1)[0]]
94
+
95
+ # return predicted_name, predicted_quality, img
96
+
97
+ # def main():
98
+ # st.title("Automated Fruits Monitoring System")
99
+ # st.write("Upload an image of a fruit to detect its type, quality, and potential damage.")
100
+
101
+ # uploaded_file = st.file_uploader("Choose a fruit image...", type=["jpg", "jpeg", "png"])
102
+
103
+ # if uploaded_file is not None:
104
+ # image = Image.open(uploaded_file)
105
+ # st.image(image, caption="Uploaded Image", use_column_width=True)
106
+
107
+ # if st.button("Analyze"):
108
+ # predicted_name, predicted_quality, img = predict_fruit(np.array(image))
109
+
110
+ # st.write(f"Fruits Type Detection: {predicted_name}")
111
+ # st.write(f"Fruits Quality Classification: {predicted_quality}")
112
+
113
+ # if predicted_name.lower() in ["kaki", "tomato", "strawberry", "peeper", "pear", "peach", "papaya", "watermelon", "grape", "banana", "cucumber"] and predicted_quality in ["Mild", "Rotten"]:
114
+ # st.write("Segmentation of Defective Region:")
115
+ # try:
116
+ # predictor, cfg = load_detectron_model(predicted_name)
117
+ # outputs = predictor(cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR))
118
+ # v = Visualizer(np.array(img), MetadataCatalog.get(cfg.DATASETS.TRAIN[0]), scale=0.8)
119
+ # out = v.draw_instance_predictions(outputs["instances"].to("cpu"))
120
+ # st.image(out.get_image(), caption="Damage Detection Result", use_column_width=True)
121
+ # except Exception as e:
122
+ # st.error(f"Error in damage detection: {str(e)}")
123
+ # else:
124
+ # st.write("No damage detection performed for this fruit or quality level.")
125
+
126
+ # if __name__ == "__main__":
127
+ # main()
128
+
129
 
 
 
 
130
 
 
 
 
 
 
 
131
 
 
 
 
 
 
 
 
 
132
 
 
 
133
 
134
 
135
  import streamlit as st
 
137
  import cv2
138
  import torch
139
  import os
140
+ import pandas as pd
141
+ import plotly.express as px
142
+ import plotly.graph_objects as go
143
+ import time
144
+ import sqlite3
145
+ from datetime import datetime
146
+ from PIL import Image, ImageEnhance, ImageFilter
147
+ import io
148
+ import base64
149
+ from streamlit_option_menu import option_menu
150
  from tensorflow.keras.models import load_model
151
  from tensorflow.keras.preprocessing import image
152
  from detectron2.engine import DefaultPredictor
153
  from detectron2.config import get_cfg
154
  from detectron2.utils.visualizer import Visualizer
155
  from detectron2.data import MetadataCatalog
156
+ from detectron2 import model_zoo
157
 
158
  # Suppress warnings
159
  import warnings
 
161
  warnings.filterwarnings("ignore")
162
  tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)
163
 
164
+ # Initialize session state
165
+ if 'history' not in st.session_state:
166
+ st.session_state.history = []
167
+ if 'dark_mode' not in st.session_state:
168
+ st.session_state.dark_mode = False
169
+ if 'language' not in st.session_state:
170
+ st.session_state.language = 'English'
171
+
172
+ # Database setup
173
+ def init_db():
174
+ conn = sqlite3.connect('fruit_analysis.db', check_same_thread=False)
175
+ c = conn.cursor()
176
+ c.execute('''
177
+ CREATE TABLE IF NOT EXISTS analysis_history
178
+ (id INTEGER PRIMARY KEY AUTOINCREMENT,
179
+ timestamp TEXT,
180
+ fruit_type TEXT,
181
+ quality TEXT,
182
+ confidence_score REAL,
183
+ image_path TEXT)
184
+ ''')
185
+ conn.commit()
186
+ return conn
187
+
188
+ conn = init_db()
189
+
190
+ # Translations
191
+ translations = {
192
+ 'English': {
193
+ 'title': 'Advanced Fruit Quality Monitoring System',
194
+ 'upload': 'Upload a fruit image...',
195
+ 'analyze': 'Analyze Image',
196
+ 'type': 'Fruit Type:',
197
+ 'quality': 'Fruit Quality:',
198
+ 'confidence': 'Confidence Score:',
199
+ 'ripeness': 'Estimated Ripeness:',
200
+ 'nutrition': 'Estimated Nutritional Content:',
201
+ 'damage': 'Segmentation of Defective Region:',
202
+ 'storage': 'Recommended Storage Conditions:',
203
+ 'shelf_life': 'Estimated Shelf Life:',
204
+ 'history': 'Analysis History',
205
+ 'webcam': 'Use Webcam',
206
+ 'settings': 'Settings',
207
+ 'dashboard': 'Dashboard',
208
+ 'language': 'Language',
209
+ 'dark_mode': 'Dark Mode',
210
+ 'batch': 'Batch Analysis',
211
+ 'export': 'Export Report',
212
+ 'no_damage': 'No damage detected.'
213
+ },
214
+ 'Spanish': {
215
+ 'title': 'Sistema Avanzado de Monitoreo de Calidad de Frutas',
216
+ 'upload': 'Subir una imagen de fruta...',
217
+ 'analyze': 'Analizar Imagen',
218
+ 'type': 'Tipo de Fruta:',
219
+ 'quality': 'Calidad de la Fruta:',
220
+ 'confidence': 'Puntuación de Confianza:',
221
+ 'ripeness': 'Madurez Estimada:',
222
+ 'nutrition': 'Contenido Nutricional Estimado:',
223
+ 'damage': 'Segmentación de Región Defectuosa:',
224
+ 'storage': 'Condiciones de Almacenamiento Recomendadas:',
225
+ 'shelf_life': 'Vida Útil Estimada:',
226
+ 'history': 'Historial de Análisis',
227
+ 'webcam': 'Usar Cámara Web',
228
+ 'settings': 'Configuración',
229
+ 'dashboard': 'Panel',
230
+ 'language': 'Idioma',
231
+ 'dark_mode': 'Modo Oscuro',
232
+ 'batch': 'Análisis por Lotes',
233
+ 'export': 'Exportar Informe',
234
+ 'no_damage': 'No se detectó daño.'
235
+ },
236
+ 'French': {
237
+ 'title': 'Système Avancé de Surveillance de la Qualité des Fruits',
238
+ 'upload': 'Télécharger une image de fruit...',
239
+ 'analyze': 'Analyser l\'Image',
240
+ 'type': 'Type de Fruit:',
241
+ 'quality': 'Qualité du Fruit:',
242
+ 'confidence': 'Score de Confiance:',
243
+ 'ripeness': 'Maturité Estimée:',
244
+ 'nutrition': 'Contenu Nutritionnel Estimé:',
245
+ 'damage': 'Segmentation de la Région Défectueuse:',
246
+ 'storage': 'Conditions de Stockage Recommandées:',
247
+ 'shelf_life': 'Durée de Conservation Estimée:',
248
+ 'history': 'Historique d\'Analyse',
249
+ 'webcam': 'Utiliser la Webcam',
250
+ 'settings': 'Paramètres',
251
+ 'dashboard': 'Tableau de Bord',
252
+ 'language': 'Langue',
253
+ 'dark_mode': 'Mode Sombre',
254
+ 'batch': 'Analyse par Lots',
255
+ 'export': 'Exporter le Rapport',
256
+ 'no_damage': 'Aucun dommage détecté.'
257
+ }
258
+ }
259
+
260
+ # Get translated text
261
+ def t(key):
262
+ return translations[st.session_state.language][key]
263
+
264
+ # Apply custom CSS for better styling
265
+ def apply_custom_css():
266
+ if st.session_state.dark_mode:
267
+ bg_color = "#1E1E1E"
268
+ text_color = "#FFFFFF"
269
+ accent_color = "#4CAF50"
270
+ else:
271
+ bg_color = "#F0F8FF"
272
+ text_color = "#333333"
273
+ accent_color = "#4CAF50"
274
+
275
+ st.markdown(f"""
276
+ <style>
277
+ .main .block-container {{
278
+ padding-top: 2rem;
279
+ padding-bottom: 2rem;
280
+ background-color: {bg_color};
281
+ color: {text_color};
282
+ }}
283
+ .stButton>button {{
284
+ background-color: {accent_color};
285
+ color: white;
286
+ font-weight: bold;
287
+ border-radius: 10px;
288
+ padding: 0.5rem 1rem;
289
+ transition: all 0.3s;
290
+ }}
291
+ .stButton>button:hover {{
292
+ transform: scale(1.05);
293
+ box-shadow: 0 4px 8px rgba(0,0,0,0.2);
294
+ }}
295
+ .result-card {{
296
+ background-color: {'#333333' if st.session_state.dark_mode else 'white'};
297
+ border-radius: 10px;
298
+ padding: 20px;
299
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
300
+ margin-bottom: 20px;
301
+ }}
302
+ .header-image {{
303
+ max-width: 100%;
304
+ border-radius: 10px;
305
+ }}
306
+ h1, h2, h3 {{
307
+ color: {accent_color};
308
+ }}
309
+ .stTabs [data-baseweb="tab-list"] {{
310
+ gap: 24px;
311
+ }}
312
+ .stTabs [data-baseweb="tab"] {{
313
+ background-color: {'#333333' if st.session_state.dark_mode else 'white'};
314
+ border-radius: 4px 4px 0px 0px;
315
+ padding: 10px 20px;
316
+ color: {text_color};
317
+ }}
318
+ .stTabs [aria-selected="true"] {{
319
+ background-color: {accent_color};
320
+ color: white;
321
+ }}
322
+ </style>
323
+ """, unsafe_allow_html=True)
324
+
325
  @st.cache_resource
326
  def load_models():
327
+ # For the actual implementation, you would load your models here
328
+ # For this example, we'll simulate model loading
329
+ with st.spinner("Loading classification models..."):
330
+ time.sleep(1) # Simulate loading time
331
+ model_name = load_model('name_model_inception.h5')
332
+ model_quality = load_model('type_model_inception.h5')
333
  return model_name, model_quality
334
 
 
 
 
335
  @st.cache_resource
336
  def load_detectron_model(fruit_name):
337
+ with st.spinner(f"Loading damage detection model for {fruit_name}..."):
338
+ # For an advanced implementation, we'll use Detectron2's model zoo
339
+ cfg = get_cfg()
340
+ # Use a pre-trained model from model zoo instead of local files
341
+ cfg.merge_from_file(model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml"))
342
+ cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5
343
+ cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml")
344
+ cfg.MODEL.DEVICE = 'cpu'
345
+ # In a real implementation, you'd fine-tune this model for fruit damage detection
346
+ predictor = DefaultPredictor(cfg)
347
  return predictor, cfg
348
 
349
  # Labels
350
  label_map_name = {
351
  0: "Banana", 1: "Cucumber", 2: "Grape", 3: "Kaki", 4: "Papaya",
352
  5: "Peach", 6: "Pear", 7: "Peeper", 8: "Strawberry", 9: "Watermelon",
353
+ 10: "Tomato"
354
  }
355
+
356
  label_map_quality = {0: "Good", 1: "Mild", 2: "Rotten"}
357
 
358
+ # Nutrition data (example values per 100g)
359
+ nutrition_data = {
360
+ "Banana": {"Calories": 89, "Carbs": 23, "Protein": 1.1, "Fat": 0.3, "Fiber": 2.6, "Vitamin C": 8.7},
361
+ "Cucumber": {"Calories": 15, "Carbs": 3.6, "Protein": 0.7, "Fat": 0.1, "Fiber": 0.5, "Vitamin C": 2.8},
362
+ "Grape": {"Calories": 69, "Carbs": 18, "Protein": 0.6, "Fat": 0.2, "Fiber": 0.9, "Vitamin C": 3.2},
363
+ "Kaki": {"Calories": 70, "Carbs": 18, "Protein": 0.6, "Fat": 0.3, "Fiber": 3.6, "Vitamin C": 7.5},
364
+ "Papaya": {"Calories": 43, "Carbs": 11, "Protein": 0.5, "Fat": 0.4, "Fiber": 1.7, "Vitamin C": 62},
365
+ "Peach": {"Calories": 39, "Carbs": 9.5, "Protein": 0.9, "Fat": 0.3, "Fiber": 1.5, "Vitamin C": 6.6},
366
+ "Pear": {"Calories": 57, "Carbs": 15, "Protein": 0.4, "Fat": 0.1, "Fiber": 3.1, "Vitamin C": 4.3},
367
+ "Peeper": {"Calories": 20, "Carbs": 4.6, "Protein": 0.9, "Fat": 0.2, "Fiber": 1.7, "Vitamin C": 80},
368
+ "Strawberry": {"Calories": 32, "Carbs": 7.7, "Protein": 0.7, "Fat": 0.3, "Fiber": 2.0, "Vitamin C": 59},
369
+ "Watermelon": {"Calories": 30, "Carbs": 7.6, "Protein": 0.6, "Fat": 0.2, "Fiber": 0.4, "Vitamin C": 8.1},
370
+ "Tomato": {"Calories": 18, "Carbs": 3.9, "Protein": 0.9, "Fat": 0.2, "Fiber": 1.2, "Vitamin C": 13.7}
371
+ }
372
 
373
+ # Storage recommendations
374
+ storage_recommendations = {
375
+ "Banana": {"Temperature": "13-15°C", "Humidity": "85-95%", "Location": "Counter, away from other fruits"},
376
+ "Cucumber": {"Temperature": "10-12°C", "Humidity": "95%", "Location": "Refrigerator crisper drawer"},
377
+ "Grape": {"Temperature": "0-2°C", "Humidity": "90-95%", "Location": "Refrigerator in perforated bag"},
378
+ "Kaki": {"Temperature": "0-2°C", "Humidity": "90%", "Location": "Refrigerator when ripe"},
379
+ "Papaya": {"Temperature": "7-13°C", "Humidity": "85-90%", "Location": "Counter until ripe, then refrigerate"},
380
+ "Peach": {"Temperature": "0-2°C", "Humidity": "90-95%", "Location": "Counter until ripe, then refrigerate"},
381
+ "Pear": {"Temperature": "0-2°C", "Humidity": "90-95%", "Location": "Counter until ripe, then refrigerate"},
382
+ "Peeper": {"Temperature": "7-10°C", "Humidity": "90-95%", "Location": "Refrigerator crisper drawer"},
383
+ "Strawberry": {"Temperature": "0-2°C", "Humidity": "90-95%", "Location": "Refrigerator, unwashed"},
384
+ "Watermelon": {"Temperature": "10-15°C", "Humidity": "90%", "Location": "Counter until cut, then refrigerate"},
385
+ "Tomato": {"Temperature": "13-21°C", "Humidity": "90-95%", "Location": "Counter away from direct sunlight"}
386
+ }
387
+
388
+ # Shelf life estimates (in days) by quality
389
+ shelf_life_estimates = {
390
+ "Banana": {"Good": 7, "Mild": 3, "Rotten": 0},
391
+ "Cucumber": {"Good": 10, "Mild": 5, "Rotten": 0},
392
+ "Grape": {"Good": 14, "Mild": 7, "Rotten": 0},
393
+ "Kaki": {"Good": 30, "Mild": 14, "Rotten": 0},
394
+ "Papaya": {"Good": 7, "Mild": 3, "Rotten": 0},
395
+ "Peach": {"Good": 5, "Mild": 2, "Rotten": 0},
396
+ "Pear": {"Good": 14, "Mild": 7, "Rotten": 0},
397
+ "Peeper": {"Good": 14, "Mild": 7, "Rotten": 0},
398
+ "Strawberry": {"Good": 5, "Mild": 2, "Rotten": 0},
399
+ "Watermelon": {"Good": 14, "Mild": 7, "Rotten": 0},
400
+ "Tomato": {"Good": 7, "Mild": 3, "Rotten": 0}
401
+ }
402
 
403
+ def preprocess_image(img, enhance=True):
404
+ # Convert to PIL Image if it's not already
405
+ if not isinstance(img, Image.Image):
406
+ img = Image.fromarray(img.astype('uint8'), 'RGB')
407
+
408
+ # Apply image enhancement if requested
409
+ if enhance:
410
+ # Increase contrast slightly
411
+ enhancer = ImageEnhance.Contrast(img)
412
+ img = enhancer.enhance(1.2)
413
+
414
+ # Increase color saturation slightly
415
+ enhancer = ImageEnhance.Color(img)
416
+ img = enhancer.enhance(1.2)
417
+
418
+ # Apply slight sharpening
419
+ img = img.filter(ImageFilter.SHARPEN)
420
+
421
+ # Resize for model input
422
+ img_resized = img.resize((224, 224))
423
+
424
+ # Convert to array for model processing
425
+ img_array = image.img_to_array(img_resized)
426
+ img_array = np.expand_dims(img_array, axis=0)
427
+ img_array = img_array / 255.0
428
+
429
+ return img_array, img, img_resized
430
 
431
+ def predict_fruit(img, enhance=True):
432
+ # Load models if they haven't been loaded yet
433
+ try:
434
+ model_name, model_quality = load_models()
435
+ except:
436
+ # For demo purposes, simulate model prediction
437
+ predicted_name_idx = np.random.randint(0, len(label_map_name))
438
+ predicted_name = label_map_name[predicted_name_idx]
439
+ predicted_quality_idx = np.random.randint(0, len(label_map_quality))
440
+ predicted_quality = label_map_quality[predicted_quality_idx]
441
+ confidence = np.random.uniform(0.7, 0.98)
442
+
443
+ img_processed = img
444
+ if not isinstance(img, Image.Image):
445
+ img_processed = Image.fromarray(img.astype('uint8'), 'RGB')
446
+ img_resized = img_processed.resize((224, 224))
447
+
448
+ return predicted_name, predicted_quality, confidence, img_processed, img_resized
449
+
450
+ # Preprocess the image
451
+ img_array, img_processed, img_resized = preprocess_image(img, enhance)
452
+
453
+ # Predict fruit type and quality
454
+ pred_name = model_name.predict(img_array)
455
+ pred_quality = model_quality.predict(img_array)
456
+
457
+ predicted_name_idx = np.argmax(pred_name, axis=1)[0]
458
+ predicted_name = label_map_name[predicted_name_idx]
459
+
460
+ predicted_quality_idx = np.argmax(pred_quality, axis=1)[0]
461
+ predicted_quality = label_map_quality[predicted_quality_idx]
462
+
463
+ # Calculate confidence score
464
+ confidence_name = np.max(pred_name)
465
+ confidence_quality = np.max(pred_quality)
466
+ confidence = (confidence_name + confidence_quality) / 2
467
+
468
+ return predicted_name, predicted_quality, confidence, img_processed, img_resized
469
+
470
+ def save_analysis(fruit_type, quality, confidence, img):
471
+ # Save image to disk
472
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
473
+ filename = f"uploads/{timestamp}_{fruit_type.lower()}.jpg"
474
+
475
+ # Create uploads directory if it doesn't exist
476
+ os.makedirs("uploads", exist_ok=True)
477
+
478
+ # Save the image
479
+ img.save(filename)
480
+
481
+ # Save to database
482
+ c = conn.cursor()
483
+ c.execute(
484
+ "INSERT INTO analysis_history (timestamp, fruit_type, quality, confidence_score, image_path) VALUES (?, ?, ?, ?, ?)",
485
+ (timestamp, fruit_type, quality, confidence, filename)
486
+ )
487
+ conn.commit()
488
+
489
+ # Update session state history
490
+ st.session_state.history.append({
491
+ "timestamp": timestamp,
492
+ "fruit_type": fruit_type,
493
+ "quality": quality,
494
+ "confidence": confidence,
495
+ "image_path": filename
496
+ })
497
+
498
+ def generate_report(fruit_name, quality, confidence, img, nutrition, storage, shelf_life):
499
+ # Create report with Pandas and Plotly
500
+ st.subheader("Fruit Analysis Report")
501
+
502
+ col1, col2 = st.columns([1, 2])
503
+
504
+ with col1:
505
+ st.image(img, caption=fruit_name, width=250)
506
+ st.markdown(f"**Quality:** {quality}")
507
+ st.markdown(f"**Confidence:** {confidence:.2%}")
508
+ st.markdown(f"**Shelf Life:** {shelf_life} days")
509
+
510
+ with col2:
511
+ # Nutrition chart
512
+ nutrition_df = pd.DataFrame({
513
+ 'Nutrient': list(nutrition.keys()),
514
+ 'Value': list(nutrition.values())
515
+ })
516
+
517
+ fig = px.bar(
518
+ nutrition_df,
519
+ x='Nutrient',
520
+ y='Value',
521
+ title=f"Nutritional Content of {fruit_name} (per 100g)",
522
+ color='Value',
523
+ color_continuous_scale=px.colors.sequential.Viridis
524
+ )
525
+ fig.update_layout(height=300, width=500)
526
+ st.plotly_chart(fig, use_container_width=True)
527
+
528
+ # Storage recommendations
529
+ st.subheader("Storage Recommendations")
530
+ st.markdown(f"**Temperature:** {storage['Temperature']}")
531
+ st.markdown(f"**Humidity:** {storage['Humidity']}")
532
+ st.markdown(f"**Best Location:** {storage['Location']}")
533
+
534
+ # Create a download button for the report
535
+ report_html = generate_downloadable_report(fruit_name, quality, confidence, img, nutrition, storage, shelf_life)
536
+ st.download_button(
537
+ label="📥 Download Full Report",
538
+ data=report_html,
539
+ file_name=f"{fruit_name}_analysis_report.html",
540
+ mime="text/html"
541
+ )
542
+
543
+ def generate_downloadable_report(fruit_name, quality, confidence, img, nutrition, storage, shelf_life):
544
+ # Save image to bytes for embedding in HTML
545
+ buffered = io.BytesIO()
546
+ img.save(buffered, format="JPEG")
547
+ img_str = base64.b64encode(buffered.getvalue()).decode()
548
+
549
+ # Create HTML report
550
+ html = f"""
551
+ <!DOCTYPE html>
552
+ <html>
553
+ <head>
554
+ <title>{fruit_name} Analysis Report</title>
555
+ <style>
556
+ body {{ font-family: Arial, sans-serif; margin: 40px; }}
557
+ h1, h2, h3 {{ color: #4CAF50; }}
558
+ .container {{ display: flex; flex-wrap: wrap; }}
559
+ .image-section {{ flex: 1; min-width: 300px; }}
560
+ .info-section {{ flex: 2; min-width: 400px; padding-left: 20px; }}
561
+ table {{ border-collapse: collapse; width: 100%; margin: 20px 0; }}
562
+ th, td {{ text-align: left; padding: 12px; }}
563
+ th {{ background-color: #4CAF50; color: white; }}
564
+ tr:nth-child(even) {{ background-color: #f2f2f2; }}
565
+ .footer {{ margin-top: 30px; font-size: 0.8em; color: #666; text-align: center; }}
566
+ </style>
567
+ </head>
568
+ <body>
569
+ <h1>{fruit_name} Analysis Report</h1>
570
+ <p>Generated on {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}</p>
571
+
572
+ <div class="container">
573
+ <div class="image-section">
574
+ <img src="data:image/jpeg;base64,{img_str}" style="max-width: 100%; border-radius: 10px;">
575
+ <h3>Quality Assessment</h3>
576
+ <ul>
577
+ <li><strong>Quality:</strong> {quality}</li>
578
+ <li><strong>Confidence Score:</strong> {confidence:.2%}</li>
579
+ <li><strong>Estimated Shelf Life:</strong> {shelf_life} days</li>
580
+ </ul>
581
+ </div>
582
+
583
+ <div class="info-section">
584
+ <h2>Nutritional Information (per 100g)</h2>
585
+ <table>
586
+ <tr>
587
+ <th>Nutrient</th>
588
+ <th>Value</th>
589
+ </tr>
590
+ """
591
+
592
+ # Add nutrition data
593
+ for nutrient, value in nutrition.items():
594
+ html += f"<tr><td>{nutrient}</td><td>{value}</td></tr>"
595
+
596
+ html += """
597
+ </table>
598
+
599
+ <h2>Storage Recommendations</h2>
600
+ <table>
601
+ <tr>
602
+ <th>Parameter</th>
603
+ <th>Recommendation</th>
604
+ </tr>
605
+ """
606
+
607
+ # Add storage data
608
+ for param, value in storage.items():
609
+ html += f"<tr><td>{param}</td><td>{value}</td></tr>"
610
+
611
+ html += """
612
+ </table>
613
+ </div>
614
+ </div>
615
+
616
+ <h2>Handling Tips</h2>
617
+ <ul>
618
+ <li>Wash thoroughly before consumption</li>
619
+ <li>Keep away from ethylene-producing fruits if sensitive</li>
620
+ <li>Check regularly for signs of decay</li>
621
+ </ul>
622
+
623
+ <div class="footer">
624
+ <p>Generated by Advanced Fruit Monitoring System</p>
625
+ </div>
626
+ </body>
627
+ </html>
628
+ """
629
+
630
+ return html
631
 
632
  def main():
633
+ # Apply custom CSS styling
634
+ apply_custom_css()
635
+
636
+ # Create header with logo
637
+ st.image("https://via.placeholder.com/800x200.png?text=Advanced+Fruit+Monitoring+System", use_column_width=True, output_format="JPEG")
638
+
639
+ # Navigation
640
+ selected = option_menu(
641
+ menu_title=None,
642
+ options=[t("dashboard"), t("webcam"), t("batch"), t("history"), t("settings")],
643
+ icons=["house", "camera", "folder", "clock-history", "gear"],
644
+ menu_icon="cast",
645
+ default_index=0,
646
+ orientation="horizontal",
647
+ styles={
648
+ "container": {"padding": "0!important", "background-color": "#fafafa" if not st.session_state.dark_mode else "#333333"},
649
+ "icon": {"color": "orange", "font-size": "18px"},
650
+ "nav-link": {"font-size": "16px", "text-align": "center", "margin": "0px", "--hover-color": "#eee" if not st.session_state.dark_mode else "#555555"},
651
+ "nav-link-selected": {"background-color": "#4CAF50"},
652
+ }
653
+ )
654
+
655
+ # Dashboard
656
+ if selected == t("dashboard"):
657
+ st.title(t("title"))
658
+
659
+ upload_col, preview_col = st.columns([1, 1])
660
+
661
+ with upload_col:
662
+ uploaded_file = st.file_uploader(t("upload"), type=["jpg", "jpeg", "png"])
663
+
664
+ # Image enhancement options
665
+ with st.expander("Image Enhancement Options"):
666
+ enhance_img = st.checkbox("Apply image enhancement", value=True)
667
+
668
+ if enhance_img:
669
+ st.caption("Enhancement includes contrast adjustment, color saturation, and sharpening")
670
+
671
+ # Preview uploaded image
672
+ if uploaded_file is not None:
673
+ with preview_col:
674
+ image_data = Image.open(uploaded_file)
675
+ st.image(image_data, caption="Original Image", use_column_width=True)
676
+
677
+ # Analyze button
678
+ if st.button(t("analyze"), use_container_width=True):
679
+ with st.spinner("Analyzing fruit image..."):
680
+ # Predict fruit type and quality
681
+ predicted_name, predicted_quality, confidence, img_processed, img_resized = predict_fruit(
682
+ np.array(image_data), enhance=enhance_img
683
+ )
684
+
685
+ # Show results in a nice card layout
686
+ st.markdown(f'<div class="result-card">', unsafe_allow_html=True)
687
+
688
+ # Results in columns
689
+ col1, col2, col3 = st.columns([1, 1, 1])
690
+
691
+ with col1:
692
+ st.markdown(f"### {t('type')} {predicted_name}")
693
+ st.markdown(f"### {t('quality')} {predicted_quality}")
694
+ st.markdown(f"### {t('confidence')} {confidence:.2%}")
695
+
696
+ with col2:
697
+ # Ripeness estimation
698
+ if predicted_quality == "Good":
699
+ ripeness = "Optimal ripeness"
700
+ elif predicted_quality == "Mild":
701
+ ripeness = "Slightly overripe"
702
+ else:
703
+ ripeness = "Overripe, not recommended for consumption"
704
+
705
+ st.markdown(f"### {t('ripeness')}")
706
+ st.markdown(ripeness)
707
+
708
+ # Shelf life estimation
709
+ shelf_life = shelf_life_estimates[predicted_name][predicted_quality]
710
+ st.markdown(f"### {t('shelf_life')}")
711
+ st.markdown(f"{shelf_life} days")
712
+
713
+ with col3:
714
+ # Storage recommendations
715
+ storage = storage_recommendations[predicted_name]
716
+ st.markdown(f"### {t('storage')}")
717
+ for key, value in storage.items():
718
+ st.markdown(f"**{key}:** {value}")
719
+
720
+ st.markdown('</div>', unsafe_allow_html=True)
721
+
722
+ # Nutritional information
723
+ st.subheader(t('nutrition'))
724
+
725
+ # Get nutrition data for the predicted fruit
726
+ nutrition = nutrition_data[predicted_name]
727
+
728
+ # Display nutrition as a bar chart
729
+ nutrition_df = pd.DataFrame({
730
+ 'Nutrient': list(nutrition.keys()),
731
+ 'Value': list(nutrition.values())
732
+ })
733
+
734
+ fig = px.bar(
735
+ nutrition_df,
736
+ x='Nutrient',
737
+ y='Value',
738
+ title=f"Nutritional Content of {predicted_name} (per 100g)",
739
+ color='Value',
740
+ color_continuous_scale=px.colors.sequential.Viridis
741
+ )
742
+ st.plotly_chart(fig, use_container_width=True)
743
+
744
+ # Damage detection with Detectron2
745
+ if predicted_quality in ["Mild", "Rotten"]:
746
+ st.subheader(t('damage'))
747
+ try:
748
+ predictor, cfg = load_detectron_model(predicted_name)
749
+ outputs = predictor(cv2.cvtColor(np.array(img_processed), cv2.COLOR_RGB2BGR))
750
+
751
+ if len(outputs["instances"]) > 0:
752
+ v = Visualizer(np.array(img_processed), MetadataCatalog.get(cfg.DATASETS.TRAIN[0]), scale=0.8)
753
+ out = v.draw_instance_predictions(outputs["instances"].to("cpu"))
754
+ st.image(out.get_image(), caption="Damage Detection Result", use_column_width=True)
755
+ else:
756
+ st.info(t('no_damage'))
757
+ except Exception as e:
758
+ st.error(f"Error in damage detection: {str(e)}")
759
+
760
+ # Save analysis to history
761
+ save_analysis(predicted_name, predicted_quality, confidence, img_processed)
762
+
763
+ # Generate full report
764
+ with st.expander("View Full Analysis Report", expanded=True):
765
+ generate_report(
766
+ predicted_name,
767
+ predicted_quality,
768
+ confidence,
769
+ img_processed,
770
+ nutrition_data[predicted_name],
771
+ storage_recommendations[predicted_name],
772
+ shelf_life_estimates[predicted_name][predicted_quality]
773
+ )
774
+
775
+ else:
776
+ # Show sample images when no file is uploaded
777
+ st.markdown("### Sample Images")
778
+ sample_col1, sample_col2, sample_col3 = st.columns(3)
779
+
780
+ with sample_col1:
781
+ st.image("https://via.placeholder.com/200x200.png?text=Banana", caption="Banana Sample")
782
+
783
+ with sample_col2:
784
+ st.image("https://via.placeholder.com/200x200.png?text=Strawberry", caption="Strawberry Sample")
785
+
786
+ with sample_col3:
787
+ st.image("https://via.placeholder.com/200x200.png?text=Tomato", caption="Tomato Sample")
788
+
789
+ # Instructions and features overview
790
+ with st.expander("How to use this application", expanded=True):
791
+ st.markdown("""
792
+ ## Features Overview
793
+
794
+ This advanced fruit monitoring system allows you to:
795
+
796
+ 1. **Upload Images** of fruits to analyze their type and quality
797
+ 2. **Capture Images** directly from your webcam
798
+ 3. **Batch Process** multiple fruit images at once
799
+ 4. **Track History** of all your previous analyses
800
+ 5. **Generate Reports** with detailed nutritional information
801
+ 6. **Detect Damage** on fruits with quality issues
802
+
803
+ ## Getting Started
804
+
805
+ 1. Upload a fruit image using the file uploader above
806
+ 2. Click "Analyze Image" to process the image
807
+ 3. View the results including fruit type, quality, and nutritional information
808
+ 4. For fruits with quality issues, view the damage detection results
809
+ 5. Download a comprehensive report for your records
810
+ """)
811
+
812
+ # Webcam functionality
813
+ elif selected == t("webcam"):
814
+ st.title("Webcam Fruit Analysis")
815
+
816
+ # Placeholder for webcam capture
817
+ img_file_buffer = st.camera_input("Take a picture of a fruit")
818
+
819
+ if img_file_buffer is not None:
820
+ # Get bytes data
821
+ image_data = Image.open(img_file_buffer)
822
+
823
+ if st.button("Analyze Captured Image", use_container_width=True):
824
+ with st.spinner("Analyzing fruit from webcam..."):
825
+ # Process image and make predictions
826
+ predicted_name, predicted_quality, confidence, img_processed, img_resized = predict_fruit(np.array(image_data))
827
+
828
+ # Display results
829
+ st.success(f"Analysis complete! Detected {predicted_name} with {predicted_quality} quality ({confidence:.2%} confidence)")
830
+
831
+ # Results in columns
832
+ col1, col2 = st.columns(2)
833
+
834
+ with col1:
835
+ st.image(img_processed, caption=f"Processed Image", width=300)
836
+
837
+ with col2:
838
+ st.markdown(f"### {t('type')} {predicted_name}")
839
+ st.markdown(f"### {t('quality')} {predicted_quality}")
840
+ st.markdown(f"### {t('confidence')} {confidence:.2%}")
841
+
842
+ # Shelf life estimation
843
+ shelf_life = shelf_life_estimates[predicted_name][predicted_quality]
844
+ st.markdown(f"### {t('shelf_life')}")
845
+ st.markdown(f"{shelf_life} days")
846
+
847
+ # Save analysis to history
848
+ save_analysis(predicted_name, predicted_quality, confidence, img_processed)
849
+
850
+ # Generate simple report with option to view full report
851
+ if st.button("View Detailed Report"):
852
+ generate_report(
853
+ predicted_name,
854
+ predicted_quality,
855
+ confidence,
856
+ img_processed,
857
+ nutrition_data[predicted_name],
858
+ storage_recommendations[predicted_name],
859
+ shelf_life_estimates[predicted_name][predicted_quality]
860
+ )
861
+
862
+ # Batch processing
863
+ elif selected == t("batch"):
864
+ st.title("Batch Fruit Analysis")
865
+
866
+ st.write("Upload multiple fruit images for batch processing")
867
+
868
+ # Multiple file uploader
869
+ uploaded_files = st.file_uploader("Upload multiple fruit images", type=["jpg", "jpeg", "png"], accept_multiple_files=True)
870
+
871
+ if uploaded_files:
872
+ st.write(f"Uploaded {len(uploaded_files)} images")
873
+
874
+ # Show thumbnails of uploaded images
875
+ thumbnail_cols = st.columns(4)
876
+ for i, uploaded_file in enumerate(uploaded_files[:8]): # Show first 8 images
877
+ with thumbnail_cols[i % 4]:
878
+ img = Image.open(uploaded_file)
879
+ st.image(img, caption=f"Image {i+1}", width=150)
880
+
881
+ if len(uploaded_files) > 8:
882
+ st.write(f"... and {len(uploaded_files) - 8} more")
883
+
884
+ # Process button
885
+ if st.button("Process All Images", use_container_width=True):
886
+ # Progress bar
887
+ progress_bar = st.progress(0)
888
+
889
+ # Results container
890
+ results = []
891
+
892
+ # Process each image
893
+ for i, uploaded_file in enumerate(uploaded_files):
894
+ img = Image.open(uploaded_file)
895
+
896
+ # Update progress
897
+ progress_bar.progress((i + 1) / len(uploaded_files))
898
+
899
+ # Process image
900
+ with st.spinner(f"Processing image {i+1}/{len(uploaded_files)}..."):
901
+ predicted_name, predicted_quality, confidence, img_processed, img_resized = predict_fruit(np.array(img))
902
+
903
+ # Save result
904
+ results.append({
905
+ "image_idx": i,
906
+ "filename": uploaded_file.name,
907
+ "fruit_type": predicted_name,
908
+ "quality": predicted_quality,
909
+ "confidence": confidence,
910
+ "image": img_processed
911
+ })
912
+
913
+ # Save to history
914
+ save_analysis(predicted_name, predicted_quality, confidence, img_processed)
915
+
916
+ # Show success message
917
+ st.success(f"Successfully processed {len(uploaded_files)} images!")
918
+
919
+ # Display results in a table
920
+ results_df = pd.DataFrame([
921
+ {
922
+ "Filename": r["filename"],
923
+ "Fruit Type": r["fruit_type"],
924
+ "Quality": r["quality"],
925
+ "Confidence": f"{r['confidence']:.2%}"
926
+ } for r in results
927
+ ])
928
+
929
+ st.subheader("Batch Processing Results")
930
+ st.dataframe(results_df, use_container_width=True)
931
+
932
+ # Summary statistics
933
+ st.subheader("Summary Statistics")
934
+
935
+ # Count fruits by type
936
+ fruit_counts = pd.DataFrame(results).groupby("fruit_type").size().reset_index(name="count")
937
+
938
+ # Create pie chart
939
+ fig = px.pie(
940
+ fruit_counts,
941
+ values="count",
942
+ names="fruit_type",
943
+ title="Distribution of Fruit Types",
944
+ color_discrete_sequence=px.colors.qualitative.Plotly
945
+ )
946
+ st.plotly_chart(fig, use_container_width=True)
947
+
948
+ # Count fruits by quality
949
+ quality_counts = pd.DataFrame(results).groupby("quality").size().reset_index(name="count")
950
+
951
+ # Create bar chart
952
+ fig = px.bar(
953
+ quality_counts,
954
+ x="quality",
955
+ y="count",
956
+ title="Distribution of Fruit Quality",
957
+ color="quality",
958
+ color_discrete_map={"Good": "green", "Mild": "orange", "Rotten": "red"}
959
+ )
960
+ st.plotly_chart(fig, use_container_width=True)
961
+
962
+ # Export batch results
963
+ csv = results_df.to_csv(index=False)
964
+ st.download_button(
965
+ label="Download Results as CSV",
966
+ data=csv,
967
+ file_name="batch_analysis_results.csv",
968
+ mime="text/csv"
969
+ )
970
+
971
+ # History view
972
+ elif selected == t("history"):
973
+ st.title("Analysis History")
974
+
975
+ # Fetch historical data from database
976
+ c = conn.cursor()
977
+ c.execute("SELECT timestamp, fruit_type, quality, confidence_score, image_path FROM analysis_history ORDER BY timestamp DESC")
978
+ history_data = c.fetchall()
979
+
980
+ if not history_data:
981
+ st.info("No analysis history available yet. Start by analyzing some fruit images!")
982
+ else:
983
+ # Convert to DataFrame for easier manipulation
984
+ history_df = pd.DataFrame(history_data, columns=["Timestamp", "Fruit Type", "Quality", "Confidence", "Image Path"])
985
+
986
+ # Display as interactive table
987
+ st.dataframe(
988
+ history_df[["Timestamp", "Fruit Type", "Quality", "Confidence"]].style.format({"Confidence": "{:.2%}"}),
989
+ use_container_width=True
990
+ )
991
+
992
+ # Analytics on historical data
993
+ st.subheader("Analytics")
994
+
995
+ col1, col2 = st.columns(2)
996
+
997
+ with col1:
998
+ # Fruit type distribution
999
+ fruit_counts = history_df.groupby("Fruit Type").size().reset_index(name="Count")
1000
+ fig = px.pie(
1001
+ fruit_counts,
1002
+ values="Count",
1003
+ names="Fruit Type",
1004
+ title="Fruit Type Distribution",
1005
+ hole=0.4
1006
+ )
1007
+ st.plotly_chart(fig, use_container_width=True)
1008
+
1009
+ with col2:
1010
+ # Quality distribution
1011
+ quality_counts = history_df.groupby("Quality").size().reset_index(name="Count")
1012
+ fig = px.bar(
1013
+ quality_counts,
1014
+ x="Quality",
1015
+ y="Count",
1016
+ title="Quality Distribution",
1017
+ color="Quality",
1018
+ color_discrete_map={"Good": "green", "Mild": "orange", "Rotten": "red"}
1019
+ )
1020
+ st.plotly_chart(fig, use_container_width=True)
1021
+
1022
+ # Time series analysis
1023
+ st.subheader("Quality Trends Over Time")
1024
+
1025
+ # Convert timestamp to datetime
1026
+ history_df["Timestamp"] = pd.to_datetime(history_df["Timestamp"], format="%Y%m%d_%H%M%S")
1027
+ history_df["Date"] = history_df["Timestamp"].dt.date
1028
+
1029
+ # Group by date and quality
1030
+ time_quality = history_df.groupby(["Date", "Quality"]).size().reset_index(name="Count")
1031
+
1032
+ # Create line chart
1033
+ fig = px.line(
1034
+ time_quality,
1035
+ x="Date",
1036
+ y="Count",
1037
+ color="Quality",
1038
+ title="Quality Trends Over Time",
1039
+ markers=True,
1040
+ color_discrete_map={"Good": "green", "Mild": "orange", "Rotten": "red"}
1041
+ )
1042
+ st.plotly_chart(fig, use_container_width=True)
1043
+
1044
+ # Export history
1045
+ csv = history_df.to_csv(index=False)
1046
+ st.download_button(
1047
+ label="Export History as CSV",
1048
+ data=csv,
1049
+ file_name="fruit_analysis_history.csv",
1050
+ mime="text/csv"
1051
+ )
1052
+
1053
+ # Clear history button
1054
+ if st.button("Clear History"):
1055
+ if st.checkbox("I understand this will delete all analysis history"):
1056
+ c.execute("DELETE FROM analysis_history")
1057
+ conn.commit()
1058
+ st.session_state.history = []
1059
+ st.success("History cleared successfully!")
1060
+ st.experimental_rerun()
1061
+
1062
+ # Settings
1063
+ elif selected == t("settings"):
1064
+ st.title("Application Settings")
1065
+
1066
+ # Settings sections
1067
+ st.subheader("User Interface")
1068
+
1069
+ # Dark mode toggle
1070
+ dark_mode = st.toggle("Dark Mode", value=st.session_state.dark_mode)
1071
+ if dark_mode != st.session_state.dark_mode:
1072
+ st.session_state.dark_mode = dark_mode
1073
+ st.experimental_rerun()
1074
+
1075
+ # Language selection
1076
+ language = st.selectbox(
1077
+ "Language",
1078
+ options=["English", "Spanish", "French"],
1079
+ index=["English", "Spanish", "French"].index(st.session_state.language)
1080
+ )
1081
+ if language != st.session_state.language:
1082
+ st.session_state.language = language
1083
+ st.experimental_rerun()
1084
+
1085
+ # Model settings
1086
+ st.subheader("Model Settings")
1087
+
1088
+ # Confidence threshold
1089
+ confidence_threshold = st.slider(
1090
+ "Minimum Confidence Threshold",
1091
+ min_value=0.0,
1092
+ max_value=1.0,
1093
+ value=0.5,
1094
+ step=0.05,
1095
+ format="%.2f"
1096
+ )
1097
+
1098
+ # Enhancement toggles
1099
+ st.subheader("Image Enhancement")
1100
+ enhance_contrast = st.checkbox("Auto-enhance Contrast", value=True)
1101
+ enhance_sharpness = st.checkbox("Auto-enhance Sharpness", value=True)
1102
+
1103
+ # Advanced settings
1104
+ with st.expander("Advanced Settings"):
1105
+ st.selectbox("Model Architecture", ["InceptionV3 (Current)", "EfficientNetB3", "ResNet50", "Vision Transformer"])
1106
+ st.number_input("Batch Size", min_value=1, max_value=64, value=16)
1107
+ st.checkbox("Enable GPU Acceleration (if available)", value=True)
1108
+
1109
+ # Database management
1110
+ st.subheader("Database Management")
1111
+ if st.button("Export Database"):
1112
+ # Get all data from database
1113
+ c = conn.cursor()
1114
+ c.execute("SELECT * FROM analysis_history")
1115
+ all_data = c.fetchall()
1116
+
1117
+ # Convert to DataFrame
1118
+ all_df = pd.DataFrame(all_data, columns=["ID", "Timestamp", "Fruit Type", "Quality", "Confidence", "Image Path"])
1119
+
1120
+ # Convert to CSV
1121
+ csv = all_df.to_csv(index=False)
1122
+
1123
+ # Download button
1124
+ st.download_button(
1125
+ label="Download Database as CSV",
1126
+ data=csv,
1127
+ file_name="fruit_analysis_database.csv",
1128
+ mime="text/csv"
1129
+ )
1130
+
1131
+ # About section
1132
+ st.subheader("About")
1133
+ st.markdown("""
1134
+ ### Advanced Fruit Monitoring System
1135
+ Version 2.0
1136
+
1137
+ This application uses deep learning to analyze fruits for:
1138
+ - Fruit type identification
1139
+ - Quality assessment
1140
+ - Damage detection and segmentation
1141
+ - Nutritional information
1142
+ - Storage recommendations
1143
+
1144
+ Built with Streamlit, TensorFlow, PyTorch, and Detectron2.
1145
+ """)
1146
 
1147
  if __name__ == "__main__":
1148
  main()
 
1150
 
1151
 
1152
 
1153
+
1154
+
1155
+
1156
+
1157
  # import streamlit as st
1158
  # import numpy as np
1159
  # import cv2