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() |