import streamlit as st import os import sys import time import tempfile import pandas as pd from PIL import Image import numpy as np # Add workspace to path sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) from src.embedding import FaceEmbedder from scripts.inference import run_inference # Page configuration st.set_page_config( page_title="FaceID - Milestone 4 Dashboard", page_icon="🛡️", layout="wide", initial_sidebar_state="expanded" ) # Custom CSS for "Premium" look st.markdown(""" """, unsafe_allow_html=True) # Singleton Model Loader @st.cache_resource def get_embedder(): return FaceEmbedder(model_name="Facenet") def save_uploaded_file(uploaded_file): try: with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as tmp_file: tmp_file.write(uploaded_file.getvalue()) return tmp_file.name except Exception as e: st.error(f"Error saving file: {e}") return None def load_markdown(path): if os.path.exists(path): with open(path, 'r', encoding='utf-8') as f: return f.read() return "File not found." def main(): st.markdown("

FaceID Final Release

", unsafe_allow_html=True) st.markdown("

Milestone 4: Hardware-Aware Inference & Professional Documentation

", unsafe_allow_html=True) # Tabs for different sections tab1, tab2, tab3, tab4 = st.tabs(["🚀 Real-time Inference", "📊 Performance Insights", "🛡️ System Card", "📈 Final Metrics"]) # --- TAB 1: INFERENCE --- with tab1: # Sample selection st.markdown("### 🧬 Quick Select Samples") samples = { "Custom Upload": (None, None), "Same Person (Albrecht Mentz)": ( "data/lfw/test/Albrecht_Mentz/Albrecht_Mentz_0000.jpg", "data/lfw/test/Albrecht_Mentz/Albrecht_Mentz_0001.jpg" ), "Same Person (Alejandro Toledo)": ( "data/lfw/test/Alejandro_Toledo/Alejandro_Toledo_0000.jpg", "data/lfw/test/Alejandro_Toledo/Alejandro_Toledo_0001.jpg" ), "Different People (Albrecht vs Alejandro)": ( "data/lfw/test/Albrecht_Mentz/Albrecht_Mentz_0000.jpg", "data/lfw/test/Alejandro_Toledo/Alejandro_Toledo_0000.jpg" ) } sample_choice = st.selectbox("Pick a pre-loaded pair or use your own:", list(samples.keys())) col1, col2 = st.columns([1, 1]) s_img1, s_img2 = samples[sample_choice] with col1: st.markdown("
", unsafe_allow_html=True) st.subheader("Subject A") if s_img1: st.image(s_img1, width='stretch') file1 = s_img1 else: file1_up = st.file_uploader("Upload image 1", type=['jpg', 'jpeg', 'png'], key="app_img1") if file1_up: st.image(file1_up, width='stretch') file1 = save_uploaded_file(file1_up) else: file1 = None st.markdown("
", unsafe_allow_html=True) with col2: st.markdown("
", unsafe_allow_html=True) st.subheader("Subject B") if s_img2: st.image(s_img2, width='stretch') file2 = s_img2 else: file2_up = st.file_uploader("Upload image 2", type=['jpg', 'jpeg', 'png'], key="app_img2") if file2_up: st.image(file2_up, width='stretch') file2 = save_uploaded_file(file2_up) else: file2 = None st.markdown("
", unsafe_allow_html=True) threshold = st.slider("Verification Threshold", 0.0, 1.0, 0.35, 0.01) if st.button("Run Verification", use_container_width=True, type="primary"): if file1 and file2: with st.spinner("Analyzing..."): embedder = get_embedder() try: res = run_inference(file1, file2, threshold, embedder=embedder) cls = "same" if res['decision'] == "SAME" else "diff" st.markdown(f"
{res['decision']} (Confidence: {res['confidence']*100:.1f}%)
", unsafe_allow_html=True) m1, m2, m3 = st.columns(3) m1.metric("Similarity Score", f"{res['similarity_score']:.4f}") m2.metric("Total Latency", f"{res['latency_total_ms']:.1f}ms") m3.metric("Extraction Time", f"{res['latency_emb_ms']:.1f}ms") except Exception as e: st.error(f"Inference error: {e}") finally: # Only cleanup if it was a temp file from upload if isinstance(file1, str) and "tmp" in file1 and os.path.exists(file1): os.remove(file1) if isinstance(file2, str) and "tmp" in file2 and os.path.exists(file2): os.remove(file2) else: st.warning("Please upload images or select a sample.") # --- TAB 2: PERFORMANCE --- with tab2: st.subheader("Hardware-Aware Profiling Results") st.info("Measurements taken on local hardware to characterize CPU latency and throughput.") # Latency breakdown l_col1, l_col2 = st.columns(2) with l_col1: st.markdown("#### Latency Breakdown") latency_data = pd.DataFrame({ "Stage": ["Preprocessing", "Embedding", "Similarity"], "Mean (ms)": [170.54, 237.70, 0.17] }) st.bar_chart(latency_data.set_index("Stage")) with l_col2: st.markdown("#### Throughput by Batch Size") throughput_data = pd.DataFrame({ "Batch Size": [1, 4, 8, 16], "FPS": [4.24, 4.31, 3.97, 4.10] }) st.line_chart(throughput_data.set_index("Batch Size")) st.markdown("---") st.markdown("#### Profiling Summary") summary_txt = load_markdown("reports/profiling_summary.txt") # Use st.code for high contrast and readability st.code(summary_txt, language="markdown") # --- TAB 3: SYSTEM CARD --- with tab3: st.subheader("System Documentation") system_card = load_markdown("reports/System_Card.md") st.markdown(system_card) # --- TAB 4: FINAL METRICS --- with tab4: st.subheader("Final Evaluation Summary (Milestone 4)") e_col1, e_col2, e_col3 = st.columns(3) e_col1.metric("Accuracy", "84.6%") e_col2.metric("F1-Score", "0.8254") e_col3.metric("Pairs Evaluated", "500") st.markdown("#### ROC Curve Artifact") if os.path.exists("reports/roc_curve.png"): st.image("reports/roc_curve.png", caption="ROC Curve for Final Release Model") else: st.write("ROC curve image not found.") if __name__ == "__main__": main()