import streamlit as st import numpy as np import cv2 import warnings import os # Suppress warnings warnings.filterwarnings("ignore", category=FutureWarning) warnings.filterwarnings("ignore", category=UserWarning) # Try importing TensorFlow try: from tensorflow.keras.models import load_model from tensorflow.keras.preprocessing import image except ImportError: st.error("Failed to import TensorFlow. Please make sure it's installed correctly.") # Try importing PyTorch and Detectron2 try: import torch import detectron2 except ImportError: with st.spinner("Installing PyTorch and Detectron2..."): os.system("pip install torch torchvision") os.system("pip install 'git+https://github.com/facebookresearch/detectron2.git'") import torch import detectron2 import streamlit as st import numpy as np import cv2 import torch import os from PIL import Image from tensorflow.keras.models import load_model from tensorflow.keras.preprocessing import image from detectron2.engine import DefaultPredictor from detectron2.config import get_cfg from detectron2.utils.visualizer import Visualizer from detectron2.data import MetadataCatalog # Suppress warnings import warnings import tensorflow as tf warnings.filterwarnings("ignore") tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR) @st.cache_resource def load_models(): model_name = load_model('name_model_inception.h5') model_quality = load_model('type_model_inception.h5') return model_name, model_quality model_name, model_quality = load_models() # Detectron2 setup @st.cache_resource def load_detectron_model(fruit_name): cfg = get_cfg() config_path = os.path.join(f"{fruit_name.lower()}_config.yaml") cfg.merge_from_file(config_path) model_path = os.path.join(f"{fruit_name}_model.pth") cfg.MODEL.WEIGHTS = model_path cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5 cfg.MODEL.DEVICE = 'cpu' predictor = DefaultPredictor(cfg) return predictor, cfg # Labels label_map_name = { 0: "Banana", 1: "Cucumber", 2: "Grape", 3: "Kaki", 4: "Papaya", 5: "Peach", 6: "Pear", 7: "Peeper", 8: "Strawberry", 9: "Watermelon", 10: "tomato" } label_map_quality = {0: "Good", 1: "Mild", 2: "Rotten"} def predict_fruit(img): # Preprocess image img = Image.fromarray(img.astype('uint8'), 'RGB') img = img.resize((224, 224)) x = image.img_to_array(img) x = np.expand_dims(x, axis=0) x = x / 255.0 # Predict pred_name = model_name.predict(x) pred_quality = model_quality.predict(x) predicted_name = label_map_name[np.argmax(pred_name, axis=1)[0]] predicted_quality = label_map_quality[np.argmax(pred_quality, axis=1)[0]] return predicted_name, predicted_quality, img def main(): st.title("Automated Fruits Monitoring System") st.write("Upload an image of a fruit to detect its type, quality, and potential damage.") uploaded_file = st.file_uploader("Choose a fruit image...", type=["jpg", "jpeg", "png"]) if uploaded_file is not None: image = Image.open(uploaded_file) st.image(image, caption="Uploaded Image", use_column_width=True) if st.button("Analyze"): predicted_name, predicted_quality, img = predict_fruit(np.array(image)) st.write(f"Fruits Type Detection: {predicted_name}") st.write(f"Fruits Quality Classification: {predicted_quality}") if predicted_name.lower() in ["kaki", "tomato", "strawberry", "peeper", "pear", "peach", "papaya", "watermelon", "grape", "banana", "cucumber"] and predicted_quality in ["Mild", "Rotten"]: st.write("Segmentation of Defective Region:") try: predictor, cfg = load_detectron_model(predicted_name) outputs = predictor(cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)) v = Visualizer(np.array(img), MetadataCatalog.get(cfg.DATASETS.TRAIN[0]), scale=0.8) out = v.draw_instance_predictions(outputs["instances"].to("cpu")) st.image(out.get_image(), caption="Damage Detection Result", use_column_width=True) except Exception as e: st.error(f"Error in damage detection: {str(e)}") else: st.write("No damage detection performed for this fruit or quality level.") if __name__ == "__main__": main() # import streamlit as st # import numpy as np # import cv2 # import torch # import os # import pandas as pd # import plotly.express as px # import plotly.graph_objects as go # import time # import sqlite3 # from datetime import datetime # from PIL import Image, ImageEnhance, ImageFilter # import io # import base64 # from streamlit_option_menu import option_menu # from tensorflow.keras.models import load_model # from tensorflow.keras.preprocessing import image # from detectron2.engine import DefaultPredictor # from detectron2.config import get_cfg # from detectron2.utils.visualizer import Visualizer # from detectron2.data import MetadataCatalog # from detectron2 import model_zoo # # Suppress warnings # import warnings # import tensorflow as tf # warnings.filterwarnings("ignore") # tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR) # # Initialize session state # if 'history' not in st.session_state: # st.session_state.history = [] # if 'dark_mode' not in st.session_state: # st.session_state.dark_mode = False # if 'language' not in st.session_state: # st.session_state.language = 'English' # # Database setup # def init_db(): # conn = sqlite3.connect('fruit_analysis.db', check_same_thread=False) # c = conn.cursor() # c.execute(''' # CREATE TABLE IF NOT EXISTS analysis_history # (id INTEGER PRIMARY KEY AUTOINCREMENT, # timestamp TEXT, # fruit_type TEXT, # quality TEXT, # confidence_score REAL, # image_path TEXT) # ''') # conn.commit() # return conn # conn = init_db() # # Translations # translations = { # 'English': { # 'title': 'Advanced Fruit Quality Monitoring System', # 'upload': 'Upload a fruit image...', # 'analyze': 'Analyze Image', # 'type': 'Fruit Type:', # 'quality': 'Fruit Quality:', # 'confidence': 'Confidence Score:', # 'ripeness': 'Estimated Ripeness:', # 'nutrition': 'Estimated Nutritional Content:', # 'damage': 'Segmentation of Defective Region:', # 'storage': 'Recommended Storage Conditions:', # 'shelf_life': 'Estimated Shelf Life:', # 'history': 'Analysis History', # 'webcam': 'Use Webcam', # 'settings': 'Settings', # 'dashboard': 'Dashboard', # 'language': 'Language', # 'dark_mode': 'Dark Mode', # 'batch': 'Batch Analysis', # 'export': 'Export Report', # 'no_damage': 'No damage detected.' # }, # 'Spanish': { # 'title': 'Sistema Avanzado de Monitoreo de Calidad de Frutas', # 'upload': 'Subir una imagen de fruta...', # 'analyze': 'Analizar Imagen', # 'type': 'Tipo de Fruta:', # 'quality': 'Calidad de la Fruta:', # 'confidence': 'Puntuación de Confianza:', # 'ripeness': 'Madurez Estimada:', # 'nutrition': 'Contenido Nutricional Estimado:', # 'damage': 'Segmentación de Región Defectuosa:', # 'storage': 'Condiciones de Almacenamiento Recomendadas:', # 'shelf_life': 'Vida Útil Estimada:', # 'history': 'Historial de Análisis', # 'webcam': 'Usar Cámara Web', # 'settings': 'Configuración', # 'dashboard': 'Panel', # 'language': 'Idioma', # 'dark_mode': 'Modo Oscuro', # 'batch': 'Análisis por Lotes', # 'export': 'Exportar Informe', # 'no_damage': 'No se detectó daño.' # }, # 'French': { # 'title': 'Système Avancé de Surveillance de la Qualité des Fruits', # 'upload': 'Télécharger une image de fruit...', # 'analyze': 'Analyser l\'Image', # 'type': 'Type de Fruit:', # 'quality': 'Qualité du Fruit:', # 'confidence': 'Score de Confiance:', # 'ripeness': 'Maturité Estimée:', # 'nutrition': 'Contenu Nutritionnel Estimé:', # 'damage': 'Segmentation de la Région Défectueuse:', # 'storage': 'Conditions de Stockage Recommandées:', # 'shelf_life': 'Durée de Conservation Estimée:', # 'history': 'Historique d\'Analyse', # 'webcam': 'Utiliser la Webcam', # 'settings': 'Paramètres', # 'dashboard': 'Tableau de Bord', # 'language': 'Langue', # 'dark_mode': 'Mode Sombre', # 'batch': 'Analyse par Lots', # 'export': 'Exporter le Rapport', # 'no_damage': 'Aucun dommage détecté.' # } # } # # Get translated text # def t(key): # return translations[st.session_state.language][key] # # Apply custom CSS for better styling # def apply_custom_css(): # if st.session_state.dark_mode: # bg_color = "#1E1E1E" # text_color = "#FFFFFF" # accent_color = "#4CAF50" # else: # bg_color = "#F0F8FF" # text_color = "#333333" # accent_color = "#4CAF50" # st.markdown(f""" # # """, unsafe_allow_html=True) # @st.cache_resource # def load_models(): # # For the actual implementation, you would load your models here # # For this example, we'll simulate model loading # with st.spinner("Loading classification models..."): # time.sleep(1) # Simulate loading time # model_name = load_model('name_model_inception.h5') # model_quality = load_model('type_model_inception.h5') # return model_name, model_quality # @st.cache_resource # def load_detectron_model(fruit_name): # with st.spinner(f"Loading damage detection model for {fruit_name}..."): # # For an advanced implementation, we'll use Detectron2's model zoo # cfg = get_cfg() # # Use a pre-trained model from model zoo instead of local files # cfg.merge_from_file(model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml")) # cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5 # cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml") # cfg.MODEL.DEVICE = 'cpu' # # In a real implementation, you'd fine-tune this model for fruit damage detection # predictor = DefaultPredictor(cfg) # return predictor, cfg # # Labels # label_map_name = { # 0: "Banana", 1: "Cucumber", 2: "Grape", 3: "Kaki", 4: "Papaya", # 5: "Peach", 6: "Pear", 7: "Peeper", 8: "Strawberry", 9: "Watermelon", # 10: "Tomato" # } # label_map_quality = {0: "Good", 1: "Mild", 2: "Rotten"} # # Nutrition data (example values per 100g) # nutrition_data = { # "Banana": {"Calories": 89, "Carbs": 23, "Protein": 1.1, "Fat": 0.3, "Fiber": 2.6, "Vitamin C": 8.7}, # "Cucumber": {"Calories": 15, "Carbs": 3.6, "Protein": 0.7, "Fat": 0.1, "Fiber": 0.5, "Vitamin C": 2.8}, # "Grape": {"Calories": 69, "Carbs": 18, "Protein": 0.6, "Fat": 0.2, "Fiber": 0.9, "Vitamin C": 3.2}, # "Kaki": {"Calories": 70, "Carbs": 18, "Protein": 0.6, "Fat": 0.3, "Fiber": 3.6, "Vitamin C": 7.5}, # "Papaya": {"Calories": 43, "Carbs": 11, "Protein": 0.5, "Fat": 0.4, "Fiber": 1.7, "Vitamin C": 62}, # "Peach": {"Calories": 39, "Carbs": 9.5, "Protein": 0.9, "Fat": 0.3, "Fiber": 1.5, "Vitamin C": 6.6}, # "Pear": {"Calories": 57, "Carbs": 15, "Protein": 0.4, "Fat": 0.1, "Fiber": 3.1, "Vitamin C": 4.3}, # "Peeper": {"Calories": 20, "Carbs": 4.6, "Protein": 0.9, "Fat": 0.2, "Fiber": 1.7, "Vitamin C": 80}, # "Strawberry": {"Calories": 32, "Carbs": 7.7, "Protein": 0.7, "Fat": 0.3, "Fiber": 2.0, "Vitamin C": 59}, # "Watermelon": {"Calories": 30, "Carbs": 7.6, "Protein": 0.6, "Fat": 0.2, "Fiber": 0.4, "Vitamin C": 8.1}, # "Tomato": {"Calories": 18, "Carbs": 3.9, "Protein": 0.9, "Fat": 0.2, "Fiber": 1.2, "Vitamin C": 13.7} # } # # Storage recommendations # storage_recommendations = { # "Banana": {"Temperature": "13-15°C", "Humidity": "85-95%", "Location": "Counter, away from other fruits"}, # "Cucumber": {"Temperature": "10-12°C", "Humidity": "95%", "Location": "Refrigerator crisper drawer"}, # "Grape": {"Temperature": "0-2°C", "Humidity": "90-95%", "Location": "Refrigerator in perforated bag"}, # "Kaki": {"Temperature": "0-2°C", "Humidity": "90%", "Location": "Refrigerator when ripe"}, # "Papaya": {"Temperature": "7-13°C", "Humidity": "85-90%", "Location": "Counter until ripe, then refrigerate"}, # "Peach": {"Temperature": "0-2°C", "Humidity": "90-95%", "Location": "Counter until ripe, then refrigerate"}, # "Pear": {"Temperature": "0-2°C", "Humidity": "90-95%", "Location": "Counter until ripe, then refrigerate"}, # "Peeper": {"Temperature": "7-10°C", "Humidity": "90-95%", "Location": "Refrigerator crisper drawer"}, # "Strawberry": {"Temperature": "0-2°C", "Humidity": "90-95%", "Location": "Refrigerator, unwashed"}, # "Watermelon": {"Temperature": "10-15°C", "Humidity": "90%", "Location": "Counter until cut, then refrigerate"}, # "Tomato": {"Temperature": "13-21°C", "Humidity": "90-95%", "Location": "Counter away from direct sunlight"} # } # # Shelf life estimates (in days) by quality # shelf_life_estimates = { # "Banana": {"Good": 7, "Mild": 3, "Rotten": 0}, # "Cucumber": {"Good": 10, "Mild": 5, "Rotten": 0}, # "Grape": {"Good": 14, "Mild": 7, "Rotten": 0}, # "Kaki": {"Good": 30, "Mild": 14, "Rotten": 0}, # "Papaya": {"Good": 7, "Mild": 3, "Rotten": 0}, # "Peach": {"Good": 5, "Mild": 2, "Rotten": 0}, # "Pear": {"Good": 14, "Mild": 7, "Rotten": 0}, # "Peeper": {"Good": 14, "Mild": 7, "Rotten": 0}, # "Strawberry": {"Good": 5, "Mild": 2, "Rotten": 0}, # "Watermelon": {"Good": 14, "Mild": 7, "Rotten": 0}, # "Tomato": {"Good": 7, "Mild": 3, "Rotten": 0} # } # def preprocess_image(img, enhance=True): # # Convert to PIL Image if it's not already # if not isinstance(img, Image.Image): # img = Image.fromarray(img.astype('uint8'), 'RGB') # # Apply image enhancement if requested # if enhance: # # Increase contrast slightly # enhancer = ImageEnhance.Contrast(img) # img = enhancer.enhance(1.2) # # Increase color saturation slightly # enhancer = ImageEnhance.Color(img) # img = enhancer.enhance(1.2) # # Apply slight sharpening # img = img.filter(ImageFilter.SHARPEN) # # Resize for model input # img_resized = img.resize((224, 224)) # # Convert to array for model processing # img_array = image.img_to_array(img_resized) # img_array = np.expand_dims(img_array, axis=0) # img_array = img_array / 255.0 # return img_array, img, img_resized # def predict_fruit(img, enhance=True): # # Load models if they haven't been loaded yet # try: # model_name, model_quality = load_models() # except: # # For demo purposes, simulate model prediction # predicted_name_idx = np.random.randint(0, len(label_map_name)) # predicted_name = label_map_name[predicted_name_idx] # predicted_quality_idx = np.random.randint(0, len(label_map_quality)) # predicted_quality = label_map_quality[predicted_quality_idx] # confidence = np.random.uniform(0.7, 0.98) # img_processed = img # if not isinstance(img, Image.Image): # img_processed = Image.fromarray(img.astype('uint8'), 'RGB') # img_resized = img_processed.resize((224, 224)) # return predicted_name, predicted_quality, confidence, img_processed, img_resized # # Preprocess the image # img_array, img_processed, img_resized = preprocess_image(img, enhance) # # Predict fruit type and quality # pred_name = model_name.predict(img_array) # pred_quality = model_quality.predict(img_array) # predicted_name_idx = np.argmax(pred_name, axis=1)[0] # predicted_name = label_map_name[predicted_name_idx] # predicted_quality_idx = np.argmax(pred_quality, axis=1)[0] # predicted_quality = label_map_quality[predicted_quality_idx] # # Calculate confidence score # confidence_name = np.max(pred_name) # confidence_quality = np.max(pred_quality) # confidence = (confidence_name + confidence_quality) / 2 # return predicted_name, predicted_quality, confidence, img_processed, img_resized # def save_analysis(fruit_type, quality, confidence, img): # # Save image to disk # timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") # filename = f"uploads/{timestamp}_{fruit_type.lower()}.jpg" # # Create uploads directory if it doesn't exist # os.makedirs("uploads", exist_ok=True) # # Save the image # img.save(filename) # # Save to database # c = conn.cursor() # c.execute( # "INSERT INTO analysis_history (timestamp, fruit_type, quality, confidence_score, image_path) VALUES (?, ?, ?, ?, ?)", # (timestamp, fruit_type, quality, confidence, filename) # ) # conn.commit() # # Update session state history # st.session_state.history.append({ # "timestamp": timestamp, # "fruit_type": fruit_type, # "quality": quality, # "confidence": confidence, # "image_path": filename # }) # def generate_report(fruit_name, quality, confidence, img, nutrition, storage, shelf_life): # # Create report with Pandas and Plotly # st.subheader("Fruit Analysis Report") # col1, col2 = st.columns([1, 2]) # with col1: # st.image(img, caption=fruit_name, width=250) # st.markdown(f"**Quality:** {quality}") # st.markdown(f"**Confidence:** {confidence:.2%}") # st.markdown(f"**Shelf Life:** {shelf_life} days") # with col2: # # Nutrition chart # nutrition_df = pd.DataFrame({ # 'Nutrient': list(nutrition.keys()), # 'Value': list(nutrition.values()) # }) # fig = px.bar( # nutrition_df, # x='Nutrient', # y='Value', # title=f"Nutritional Content of {fruit_name} (per 100g)", # color='Value', # color_continuous_scale=px.colors.sequential.Viridis # ) # fig.update_layout(height=300, width=500) # st.plotly_chart(fig, use_container_width=True) # # Storage recommendations # st.subheader("Storage Recommendations") # st.markdown(f"**Temperature:** {storage['Temperature']}") # st.markdown(f"**Humidity:** {storage['Humidity']}") # st.markdown(f"**Best Location:** {storage['Location']}") # # Create a download button for the report # report_html = generate_downloadable_report(fruit_name, quality, confidence, img, nutrition, storage, shelf_life) # st.download_button( # label="📥 Download Full Report", # data=report_html, # file_name=f"{fruit_name}_analysis_report.html", # mime="text/html" # ) # def generate_downloadable_report(fruit_name, quality, confidence, img, nutrition, storage, shelf_life): # # Save image to bytes for embedding in HTML # buffered = io.BytesIO() # img.save(buffered, format="JPEG") # img_str = base64.b64encode(buffered.getvalue()).decode() # # Create HTML report # html = f""" # # # # {fruit_name} Analysis Report # # # #

{fruit_name} Analysis Report

#

Generated on {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}

#
#
# #

Quality Assessment

# #
#
#

Nutritional Information (per 100g)

# # # # # # """ # # Add nutrition data # for nutrient, value in nutrition.items(): # html += f"" # html += """ #
NutrientValue
{nutrient}{value}
#

Storage Recommendations

# # # # # # """ # # Add storage data # for param, value in storage.items(): # html += f"" # html += """ #
ParameterRecommendation
{param}{value}
#
#
#

Handling Tips

# # # # # """ # return html # def main(): # # Apply custom CSS styling # apply_custom_css() # # Create header with logo # st.image("https://via.placeholder.com/800x200.png?text=Advanced+Fruit+Monitoring+System", use_column_width=True, output_format="JPEG") # # Navigation # selected = option_menu( # menu_title=None, # options=[t("dashboard"), t("webcam"), t("batch"), t("history"), t("settings")], # icons=["house", "camera", "folder", "clock-history", "gear"], # menu_icon="cast", # default_index=0, # orientation="horizontal", # styles={ # "container": {"padding": "0!important", "background-color": "#fafafa" if not st.session_state.dark_mode else "#333333"}, # "icon": {"color": "orange", "font-size": "18px"}, # "nav-link": {"font-size": "16px", "text-align": "center", "margin": "0px", "--hover-color": "#eee" if not st.session_state.dark_mode else "#555555"}, # "nav-link-selected": {"background-color": "#4CAF50"}, # } # ) # # Dashboard # if selected == t("dashboard"): # st.title(t("title")) # upload_col, preview_col = st.columns([1, 1]) # with upload_col: # uploaded_file = st.file_uploader(t("upload"), type=["jpg", "jpeg", "png"]) # # Image enhancement options # with st.expander("Image Enhancement Options"): # enhance_img = st.checkbox("Apply image enhancement", value=True) # if enhance_img: # st.caption("Enhancement includes contrast adjustment, color saturation, and sharpening") # # Preview uploaded image # if uploaded_file is not None: # with preview_col: # image_data = Image.open(uploaded_file) # st.image(image_data, caption="Original Image", use_column_width=True) # # Analyze button # if st.button(t("analyze"), use_container_width=True): # with st.spinner("Analyzing fruit image..."): # # Predict fruit type and quality # predicted_name, predicted_quality, confidence, img_processed, img_resized = predict_fruit( # np.array(image_data), enhance=enhance_img # ) # # Show results in a nice card layout # st.markdown(f'
', unsafe_allow_html=True) # # Results in columns # col1, col2, col3 = st.columns([1, 1, 1]) # with col1: # st.markdown(f"### {t('type')} {predicted_name}") # st.markdown(f"### {t('quality')} {predicted_quality}") # st.markdown(f"### {t('confidence')} {confidence:.2%}") # with col2: # # Ripeness estimation # if predicted_quality == "Good": # ripeness = "Optimal ripeness" # elif predicted_quality == "Mild": # ripeness = "Slightly overripe" # else: # ripeness = "Overripe, not recommended for consumption" # st.markdown(f"### {t('ripeness')}") # st.markdown(ripeness) # # Shelf life estimation # shelf_life = shelf_life_estimates[predicted_name][predicted_quality] # st.markdown(f"### {t('shelf_life')}") # st.markdown(f"{shelf_life} days") # with col3: # # Storage recommendations # storage = storage_recommendations[predicted_name] # st.markdown(f"### {t('storage')}") # for key, value in storage.items(): # st.markdown(f"**{key}:** {value}") # st.markdown('
', unsafe_allow_html=True) # # Nutritional information # st.subheader(t('nutrition')) # # Get nutrition data for the predicted fruit # nutrition = nutrition_data[predicted_name] # # Display nutrition as a bar chart # nutrition_df = pd.DataFrame({ # 'Nutrient': list(nutrition.keys()), # 'Value': list(nutrition.values()) # }) # fig = px.bar( # nutrition_df, # x='Nutrient', # y='Value', # title=f"Nutritional Content of {predicted_name} (per 100g)", # color='Value', # color_continuous_scale=px.colors.sequential.Viridis # ) # st.plotly_chart(fig, use_container_width=True) # # Damage detection with Detectron2 # if predicted_quality in ["Mild", "Rotten"]: # st.subheader(t('damage')) # try: # predictor, cfg = load_detectron_model(predicted_name) # outputs = predictor(cv2.cvtColor(np.array(img_processed), cv2.COLOR_RGB2BGR)) # if len(outputs["instances"]) > 0: # v = Visualizer(np.array(img_processed), MetadataCatalog.get(cfg.DATASETS.TRAIN[0]), scale=0.8) # out = v.draw_instance_predictions(outputs["instances"].to("cpu")) # st.image(out.get_image(), caption="Damage Detection Result", use_column_width=True) # else: # st.info(t('no_damage')) # except Exception as e: # st.error(f"Error in damage detection: {str(e)}") # # Save analysis to history # save_analysis(predicted_name, predicted_quality, confidence, img_processed) # # Generate full report # with st.expander("View Full Analysis Report", expanded=True): # generate_report( # predicted_name, # predicted_quality, # confidence, # img_processed, # nutrition_data[predicted_name], # storage_recommendations[predicted_name], # shelf_life_estimates[predicted_name][predicted_quality] # ) # else: # # Show sample images when no file is uploaded # st.markdown("### Sample Images") # sample_col1, sample_col2, sample_col3 = st.columns(3) # with sample_col1: # st.image("https://via.placeholder.com/200x200.png?text=Banana", caption="Banana Sample") # with sample_col2: # st.image("https://via.placeholder.com/200x200.png?text=Strawberry", caption="Strawberry Sample") # with sample_col3: # st.image("https://via.placeholder.com/200x200.png?text=Tomato", caption="Tomato Sample") # # Instructions and features overview # with st.expander("How to use this application", expanded=True): # st.markdown(""" # ## Features Overview # This advanced fruit monitoring system allows you to: # 1. **Upload Images** of fruits to analyze their type and quality # 2. **Capture Images** directly from your webcam # 3. **Batch Process** multiple fruit images at once # 4. **Track History** of all your previous analyses # 5. **Generate Reports** with detailed nutritional information # 6. **Detect Damage** on fruits with quality issues # ## Getting Started # 1. Upload a fruit image using the file uploader above # 2. Click "Analyze Image" to process the image # 3. View the results including fruit type, quality, and nutritional information # 4. For fruits with quality issues, view the damage detection results # 5. Download a comprehensive report for your records # """) # # Webcam functionality # elif selected == t("webcam"): # st.title("Webcam Fruit Analysis") # # Placeholder for webcam capture # img_file_buffer = st.camera_input("Take a picture of a fruit") # if img_file_buffer is not None: # # Get bytes data # image_data = Image.open(img_file_buffer) # if st.button("Analyze Captured Image", use_container_width=True): # with st.spinner("Analyzing fruit from webcam..."): # # Process image and make predictions # predicted_name, predicted_quality, confidence, img_processed, img_resized = predict_fruit(np.array(image_data)) # # Display results # st.success(f"Analysis complete! Detected {predicted_name} with {predicted_quality} quality ({confidence:.2%} confidence)") # # Results in columns # col1, col2 = st.columns(2) # with col1: # st.image(img_processed, caption=f"Processed Image", width=300) # with col2: # st.markdown(f"### {t('type')} {predicted_name}") # st.markdown(f"### {t('quality')} {predicted_quality}") # st.markdown(f"### {t('confidence')} {confidence:.2%}") # # Shelf life estimation # shelf_life = shelf_life_estimates[predicted_name][predicted_quality] # st.markdown(f"### {t('shelf_life')}") # st.markdown(f"{shelf_life} days") # # Save analysis to history # save_analysis(predicted_name, predicted_quality, confidence, img_processed) # # Generate simple report with option to view full report # if st.button("View Detailed Report"): # generate_report( # predicted_name, # predicted_quality, # confidence, # img_processed, # nutrition_data[predicted_name], # storage_recommendations[predicted_name], # shelf_life_estimates[predicted_name][predicted_quality] # ) # # Batch processing # elif selected == t("batch"): # st.title("Batch Fruit Analysis") # st.write("Upload multiple fruit images for batch processing") # # Multiple file uploader # uploaded_files = st.file_uploader("Upload multiple fruit images", type=["jpg", "jpeg", "png"], accept_multiple_files=True) # if uploaded_files: # st.write(f"Uploaded {len(uploaded_files)} images") # # Show thumbnails of uploaded images # thumbnail_cols = st.columns(4) # for i, uploaded_file in enumerate(uploaded_files[:8]): # Show first 8 images # with thumbnail_cols[i % 4]: # img = Image.open(uploaded_file) # st.image(img, caption=f"Image {i+1}", width=150) # if len(uploaded_files) > 8: # st.write(f"... and {len(uploaded_files) - 8} more") # # Process button # if st.button("Process All Images", use_container_width=True): # # Progress bar # progress_bar = st.progress(0) # # Results container # results = [] # # Process each image # for i, uploaded_file in enumerate(uploaded_files): # img = Image.open(uploaded_file) # # Update progress # progress_bar.progress((i + 1) / len(uploaded_files)) # # Process image # with st.spinner(f"Processing image {i+1}/{len(uploaded_files)}..."): # predicted_name, predicted_quality, confidence, img_processed, img_resized = predict_fruit(np.array(img)) # # Save result # results.append({ # "image_idx": i, # "filename": uploaded_file.name, # "fruit_type": predicted_name, # "quality": predicted_quality, # "confidence": confidence, # "image": img_processed # }) # # Save to history # save_analysis(predicted_name, predicted_quality, confidence, img_processed) # # Show success message # st.success(f"Successfully processed {len(uploaded_files)} images!") # # Display results in a table # results_df = pd.DataFrame([ # { # "Filename": r["filename"], # "Fruit Type": r["fruit_type"], # "Quality": r["quality"], # "Confidence": f"{r['confidence']:.2%}" # } for r in results # ]) # st.subheader("Batch Processing Results") # st.dataframe(results_df, use_container_width=True) # # Summary statistics # st.subheader("Summary Statistics") # # Count fruits by type # fruit_counts = pd.DataFrame(results).groupby("fruit_type").size().reset_index(name="count") # # Create pie chart # fig = px.pie( # fruit_counts, # values="count", # names="fruit_type", # title="Distribution of Fruit Types", # color_discrete_sequence=px.colors.qualitative.Plotly # ) # st.plotly_chart(fig, use_container_width=True) # # Count fruits by quality # quality_counts = pd.DataFrame(results).groupby("quality").size().reset_index(name="count") # # Create bar chart # fig = px.bar( # quality_counts, # x="quality", # y="count", # title="Distribution of Fruit Quality", # color="quality", # color_discrete_map={"Good": "green", "Mild": "orange", "Rotten": "red"} # ) # st.plotly_chart(fig, use_container_width=True) # # Export batch results # csv = results_df.to_csv(index=False) # st.download_button( # label="Download Results as CSV", # data=csv, # file_name="batch_analysis_results.csv", # mime="text/csv" # ) # # History view # elif selected == t("history"): # st.title("Analysis History") # # Fetch historical data from database # c = conn.cursor() # c.execute("SELECT timestamp, fruit_type, quality, confidence_score, image_path FROM analysis_history ORDER BY timestamp DESC") # history_data = c.fetchall() # if not history_data: # st.info("No analysis history available yet. Start by analyzing some fruit images!") # else: # # Convert to DataFrame for easier manipulation # history_df = pd.DataFrame(history_data, columns=["Timestamp", "Fruit Type", "Quality", "Confidence", "Image Path"]) # # Display as interactive table # st.dataframe( # history_df[["Timestamp", "Fruit Type", "Quality", "Confidence"]].style.format({"Confidence": "{:.2%}"}), # use_container_width=True # ) # # Analytics on historical data # st.subheader("Analytics") # col1, col2 = st.columns(2) # with col1: # # Fruit type distribution # fruit_counts = history_df.groupby("Fruit Type").size().reset_index(name="Count") # fig = px.pie( # fruit_counts, # values="Count", # names="Fruit Type", # title="Fruit Type Distribution", # hole=0.4 # ) # st.plotly_chart(fig, use_container_width=True) # with col2: # # Quality distribution # quality_counts = history_df.groupby("Quality").size().reset_index(name="Count") # fig = px.bar( # quality_counts, # x="Quality", # y="Count", # title="Quality Distribution", # color="Quality", # color_discrete_map={"Good": "green", "Mild": "orange", "Rotten": "red"} # ) # st.plotly_chart(fig, use_container_width=True) # # Time series analysis # st.subheader("Quality Trends Over Time") # # Convert timestamp to datetime # history_df["Timestamp"] = pd.to_datetime(history_df["Timestamp"], format="%Y%m%d_%H%M%S") # history_df["Date"] = history_df["Timestamp"].dt.date # # Group by date and quality # time_quality = history_df.groupby(["Date", "Quality"]).size().reset_index(name="Count") # # Create line chart # fig = px.line( # time_quality, # x="Date", # y="Count", # color="Quality", # title="Quality Trends Over Time", # markers=True, # color_discrete_map={"Good": "green", "Mild": "orange", "Rotten": "red"} # ) # st.plotly_chart(fig, use_container_width=True) # # Export history # csv = history_df.to_csv(index=False) # st.download_button( # label="Export History as CSV", # data=csv, # file_name="fruit_analysis_history.csv", # mime="text/csv" # ) # # Clear history button # if st.button("Clear History"): # if st.checkbox("I understand this will delete all analysis history"): # c.execute("DELETE FROM analysis_history") # conn.commit() # st.session_state.history = [] # st.success("History cleared successfully!") # st.experimental_rerun() # # Settings # elif selected == t("settings"): # st.title("Application Settings") # # Settings sections # st.subheader("User Interface") # # Dark mode toggle # dark_mode = st.toggle("Dark Mode", value=st.session_state.dark_mode) # if dark_mode != st.session_state.dark_mode: # st.session_state.dark_mode = dark_mode # st.experimental_rerun() # # Language selection # language = st.selectbox( # "Language", # options=["English", "Spanish", "French"], # index=["English", "Spanish", "French"].index(st.session_state.language) # ) # if language != st.session_state.language: # st.session_state.language = language # st.experimental_rerun() # # Model settings # st.subheader("Model Settings") # # Confidence threshold # confidence_threshold = st.slider( # "Minimum Confidence Threshold", # min_value=0.0, # max_value=1.0, # value=0.5, # step=0.05, # format="%.2f" # ) # # Enhancement toggles # st.subheader("Image Enhancement") # enhance_contrast = st.checkbox("Auto-enhance Contrast", value=True) # enhance_sharpness = st.checkbox("Auto-enhance Sharpness", value=True) # # Advanced settings # with st.expander("Advanced Settings"): # st.selectbox("Model Architecture", ["InceptionV3 (Current)", "EfficientNetB3", "ResNet50", "Vision Transformer"]) # st.number_input("Batch Size", min_value=1, max_value=64, value=16) # st.checkbox("Enable GPU Acceleration (if available)", value=True) # # Database management # st.subheader("Database Management") # if st.button("Export Database"): # # Get all data from database # c = conn.cursor() # c.execute("SELECT * FROM analysis_history") # all_data = c.fetchall() # # Convert to DataFrame # all_df = pd.DataFrame(all_data, columns=["ID", "Timestamp", "Fruit Type", "Quality", "Confidence", "Image Path"]) # # Convert to CSV # csv = all_df.to_csv(index=False) # # Download button # st.download_button( # label="Download Database as CSV", # data=csv, # file_name="fruit_analysis_database.csv", # mime="text/csv" # ) # # About section # st.subheader("About") # st.markdown(""" # ### Advanced Fruit Monitoring System # Version 2.0 # This application uses deep learning to analyze fruits for: # - Fruit type identification # - Quality assessment # - Damage detection and segmentation # - Nutritional information # - Storage recommendations # Built with Streamlit, TensorFlow, PyTorch, and Detectron2. # """) # if __name__ == "__main__": # main() # # import streamlit as st # # import numpy as np # # import cv2 # # import warnings # # import os # # from pathlib import Path # # from PIL import Image # # import tensorflow as tf # # from tensorflow.keras.models import load_model # # from tensorflow.keras.preprocessing import image # # from detectron2.engine import DefaultPredictor # # from detectron2.config import get_cfg # # from detectron2.utils.visualizer import Visualizer # # from detectron2.data import MetadataCatalog # # # Suppress warnings # # warnings.filterwarnings("ignore") # # tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR) # # # Configuration # # MODEL_CONFIG = { # # 'name_model': 'name_model_inception.h5', # # 'quality_model': 'type_model_inception.h5', # # 'input_size': (224, 224), # # 'score_threshold': 0.5 # # } # # LABEL_MAPS = { # # 'name': { # # 0: "Banana", 1: "Cucumber", 2: "Grape", 3: "Kaki", 4: "Papaya", # # 5: "Peach", 6: "Pear", 7: "Peeper", 8: "Strawberry", 9: "Watermelon", # # 10: "tomato" # # }, # # 'quality': {0: "Good", 1: "Mild", 2: "Rotten"} # # } # # @st.cache_resource # # def load_classification_models(): # # """Load and cache the classification models.""" # # try: # # model_name = load_model(MODEL_CONFIG['name_model']) # # model_quality = load_model(MODEL_CONFIG['quality_model']) # # return model_name, model_quality # # except Exception as e: # # st.error(f"Error loading classification models: {str(e)}") # # return None, None # # @st.cache_resource # # def load_detectron_model(fruit_name: str): # # """Load and cache the Detectron2 model for damage detection.""" # # try: # # cfg = get_cfg() # # config_path = Path(f"{fruit_name.lower()}_config.yaml") # # model_path = Path(f"{fruit_name}_model.pth") # # if not config_path.exists() or not model_path.exists(): # # raise FileNotFoundError(f"Model files not found for {fruit_name}") # # cfg.merge_from_file(str(config_path)) # # cfg.MODEL.WEIGHTS = str(model_path) # # cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = MODEL_CONFIG['score_threshold'] # # cfg.MODEL.DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu' # # return DefaultPredictor(cfg), cfg # # except Exception as e: # # st.error(f"Error loading Detectron2 model: {str(e)}") # # return None, None # # def preprocess_image(img: np.ndarray) -> tuple: # # """Preprocess the input image for model prediction.""" # # try: # # # Convert to PIL Image if necessary # # if isinstance(img, np.ndarray): # # img = Image.fromarray(img.astype('uint8'), 'RGB') # # # Resize and prepare for model input # # img_resized = img.resize(MODEL_CONFIG['input_size']) # # img_array = image.img_to_array(img_resized) # # img_expanded = np.expand_dims(img_array, axis=0) # # img_normalized = img_expanded / 255.0 # # return img_normalized, img_resized # # except Exception as e: # # st.error(f"Error preprocessing image: {str(e)}") # # return None, None # # def predict_fruit(img: np.ndarray) -> tuple: # # """Predict fruit type and quality.""" # # model_name, model_quality = load_classification_models() # # if model_name is None or model_quality is None: # # return None, None, None # # img_normalized, img_resized = preprocess_image(img) # # if img_normalized is None: # # return None, None, None # # try: # # # Make predictions # # pred_name = model_name.predict(img_normalized) # # pred_quality = model_quality.predict(img_normalized) # # # Get predicted labels # # predicted_name = LABEL_MAPS['name'][np.argmax(pred_name, axis=1)[0]] # # predicted_quality = LABEL_MAPS['quality'][np.argmax(pred_quality, axis=1)[0]] # # return predicted_name, predicted_quality, img_resized # # except Exception as e: # # st.error(f"Error making predictions: {str(e)}") # # return None, None, None # # def detect_damage(img: Image, fruit_name: str) -> np.ndarray: # # """Detect and visualize damage in the fruit image.""" # # predictor, cfg = load_detectron_model(fruit_name) # # if predictor is None or cfg is None: # # return None # # try: # # outputs = predictor(cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)) # # v = Visualizer(np.array(img), MetadataCatalog.get(cfg.DATASETS.TRAIN[0]), scale=0.8) # # out = v.draw_instance_predictions(outputs["instances"].to("cpu")) # # return out.get_image() # # except Exception as e: # # st.error(f"Error in damage detection: {str(e)}") # # return None # # def main(): # # st.set_page_config(page_title="Fruit Quality Analysis", layout="wide") # # st.title("Automated Fruits Monitoring System") # # st.write("Upload an image of a fruit to detect its type, quality, and potential damage.") # # uploaded_file = st.file_uploader("Choose a fruit image...", type=["jpg", "jpeg", "png"]) # # if uploaded_file is not None: # # # Create two columns for layout # # col1, col2 = st.columns(2) # # # Display uploaded image # # image = Image.open(uploaded_file) # # col1.image(image, caption="Uploaded Image", use_column_width=True) # # if col1.button("Analyze"): # # with st.spinner("Analyzing image..."): # # predicted_name, predicted_quality, img_resized = predict_fruit(np.array(image)) # # if predicted_name and predicted_quality: # # # Display results # # col2.markdown("### Analysis Results") # # col2.markdown(f"**Fruit Type:** {predicted_name}") # # col2.markdown(f"**Quality:** {predicted_quality}") # # # Check if damage detection is needed # # if (predicted_name.lower() in LABEL_MAPS['name'].values() and # # predicted_quality in ["Mild", "Rotten"]): # # col2.markdown("### Damage Detection") # # damage_image = detect_damage(img_resized, predicted_name) # # if damage_image is not None: # # col2.image(damage_image, caption="Detected Damage Regions", # # use_column_width=True) # # # Add download button for the damage detection result # # col2.download_button( # # label="Download Analysis Result", # # data=cv2.imencode('.png', damage_image)[1].tobytes(), # # file_name=f"{predicted_name}_damage_analysis.png", # # mime="image/png" # # ) # # if __name__ == "__main__": # # main()