streamlit_app / app.py
MuhammmadRizwanRizwan's picture
Update app.py
64ba694 verified
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"""
# <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()