Spaces:
Runtime error
Runtime error
| 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) | |
| 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 | |
| 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""" | |
| # <style> | |
| # .main .block-container {{ | |
| # padding-top: 2rem; | |
| # padding-bottom: 2rem; | |
| # background-color: {bg_color}; | |
| # color: {text_color}; | |
| # }} | |
| # .stButton>button {{ | |
| # background-color: {accent_color}; | |
| # color: white; | |
| # font-weight: bold; | |
| # border-radius: 10px; | |
| # padding: 0.5rem 1rem; | |
| # transition: all 0.3s; | |
| # }} | |
| # .stButton>button:hover {{ | |
| # transform: scale(1.05); | |
| # box-shadow: 0 4px 8px rgba(0,0,0,0.2); | |
| # }} | |
| # .result-card {{ | |
| # background-color: {'#333333' if st.session_state.dark_mode else 'white'}; | |
| # border-radius: 10px; | |
| # padding: 20px; | |
| # box-shadow: 0 4px 8px rgba(0,0,0,0.1); | |
| # margin-bottom: 20px; | |
| # }} | |
| # .header-image {{ | |
| # max-width: 100%; | |
| # border-radius: 10px; | |
| # }} | |
| # h1, h2, h3 {{ | |
| # color: {accent_color}; | |
| # }} | |
| # .stTabs [data-baseweb="tab-list"] {{ | |
| # gap: 24px; | |
| # }} | |
| # .stTabs [data-baseweb="tab"] {{ | |
| # background-color: {'#333333' if st.session_state.dark_mode else 'white'}; | |
| # border-radius: 4px 4px 0px 0px; | |
| # padding: 10px 20px; | |
| # color: {text_color}; | |
| # }} | |
| # .stTabs [aria-selected="true"] {{ | |
| # background-color: {accent_color}; | |
| # color: white; | |
| # }} | |
| # </style> | |
| # """, 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""" | |
| # <!DOCTYPE html> | |
| # <html> | |
| # <head> | |
| # <title>{fruit_name} Analysis Report</title> | |
| # <style> | |
| # body {{ font-family: Arial, sans-serif; margin: 40px; }} | |
| # h1, h2, h3 {{ color: #4CAF50; }} | |
| # .container {{ display: flex; flex-wrap: wrap; }} | |
| # .image-section {{ flex: 1; min-width: 300px; }} | |
| # .info-section {{ flex: 2; min-width: 400px; padding-left: 20px; }} | |
| # table {{ border-collapse: collapse; width: 100%; margin: 20px 0; }} | |
| # th, td {{ text-align: left; padding: 12px; }} | |
| # th {{ background-color: #4CAF50; color: white; }} | |
| # tr:nth-child(even) {{ background-color: #f2f2f2; }} | |
| # .footer {{ margin-top: 30px; font-size: 0.8em; color: #666; text-align: center; }} | |
| # </style> | |
| # </head> | |
| # <body> | |
| # <h1>{fruit_name} Analysis Report</h1> | |
| # <p>Generated on {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}</p> | |
| # <div class="container"> | |
| # <div class="image-section"> | |
| # <img src="data:image/jpeg;base64,{img_str}" style="max-width: 100%; border-radius: 10px;"> | |
| # <h3>Quality Assessment</h3> | |
| # <ul> | |
| # <li><strong>Quality:</strong> {quality}</li> | |
| # <li><strong>Confidence Score:</strong> {confidence:.2%}</li> | |
| # <li><strong>Estimated Shelf Life:</strong> {shelf_life} days</li> | |
| # </ul> | |
| # </div> | |
| # <div class="info-section"> | |
| # <h2>Nutritional Information (per 100g)</h2> | |
| # <table> | |
| # <tr> | |
| # <th>Nutrient</th> | |
| # <th>Value</th> | |
| # </tr> | |
| # """ | |
| # # Add nutrition data | |
| # for nutrient, value in nutrition.items(): | |
| # html += f"<tr><td>{nutrient}</td><td>{value}</td></tr>" | |
| # html += """ | |
| # </table> | |
| # <h2>Storage Recommendations</h2> | |
| # <table> | |
| # <tr> | |
| # <th>Parameter</th> | |
| # <th>Recommendation</th> | |
| # </tr> | |
| # """ | |
| # # Add storage data | |
| # for param, value in storage.items(): | |
| # html += f"<tr><td>{param}</td><td>{value}</td></tr>" | |
| # html += """ | |
| # </table> | |
| # </div> | |
| # </div> | |
| # <h2>Handling Tips</h2> | |
| # <ul> | |
| # <li>Wash thoroughly before consumption</li> | |
| # <li>Keep away from ethylene-producing fruits if sensitive</li> | |
| # <li>Check regularly for signs of decay</li> | |
| # </ul> | |
| # <div class="footer"> | |
| # <p>Generated by Advanced Fruit Monitoring System</p> | |
| # </div> | |
| # </body> | |
| # </html> | |
| # """ | |
| # 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'<div class="result-card">', 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('</div>', 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() |