import streamlit as st from PIL import Image, UnidentifiedImageError import numpy as np import tensorflow as tf from tensorflow.keras.applications.resnet50 import preprocess_input as preprocess_input_resnet50 import os # --- Page Config --- st.set_page_config( page_title="Ai-Generated vs. Real Detector", page_icon="./logo.png", layout="wide" ) # --- Path Setup --- MODEL_PATH = os.path.join(os.path.dirname(__file__), 'my_ai_detector_resnet50.keras') SAMPLE_DIR = os.path.join(os.path.dirname(__file__), 'samples') FILES_DIR = os.path.join(os.path.dirname(__file__), 'files') IMAGE_SIZE = (224, 224) # --- Custom CSS --- st.markdown(""" """, unsafe_allow_html=True) # --- Model Loading --- @st.cache_resource def load_my_model(model_path): try: model = tf.keras.models.load_model(model_path) return model except Exception as e: st.error(f"Error loading model: {e}") return None # --- Preprocessing --- def preprocess_image_for_resnet50(image_pil, target_size): if image_pil.mode != "RGB": image_pil = image_pil.convert("RGB") image_pil_resized = image_pil.resize(target_size) image_array = np.array(image_pil_resized) image_array_expanded = np.expand_dims(image_array, axis=0) processed_image = preprocess_input_resnet50(image_array_expanded.astype('float32')) return processed_image model = load_my_model(MODEL_PATH) # --- Sidebar: Project Summary & Files --- with st.sidebar: st.header("Project Background") st.markdown(""" **The Generative AI Challenge** We developed this model thinking of the possible future consequences that we will be facing with Gen-AI. As synthetic media becomes indistinguishable from reality, the need for automated verification tools is critical. """) st.markdown("---") # 1. SAMPLE SELECTOR st.markdown( "

Test the Model:

", unsafe_allow_html=True ) st.markdown("Try a sample image below:") sample_choice = st.selectbox( " ", # Empty label, relying on the markdown above for the title ["None", "Sample Real (Organic)", "Sample AI (Synthetic)"], label_visibility="collapsed" # Hide the default label area completely ) st.markdown("---") # 2. DOWNLOAD BUTTONS st.markdown("### 📥 Resources") # Download Buttons Logic report_path = os.path.join(FILES_DIR, 'report.pdf') poster_path = os.path.join(FILES_DIR, 'poster.pdf') if os.path.exists(report_path): with open(report_path, "rb") as f: st.download_button( label="📄 Read Full Report", data=f, file_name="AI_Detection_Report.pdf", mime="application/pdf" ) if os.path.exists(poster_path): with open(poster_path, "rb") as f: st.download_button( label="🖼️ View Project Poster", data=f, file_name="AI_Detection_Poster.pdf", mime="application/pdf" ) # --- Main Layout --- top_col1, top_col2 = st.columns([0.85, 0.15]) with top_col1: st.title("AI-Generated vs. Real Image Classification") with top_col2: # Theme Toggle Logic current_theme = st.get_option("theme.base") toggle_btn = st.button("🌓 Theme") if toggle_btn: if current_theme == "dark": st._config.set_option("theme.base", "light") else: st._config.set_option("theme.base", "dark") st.rerun() # Creators Section st.markdown( """

Developed by Ignacio Alarcon & Bernardo Gandara

""", unsafe_allow_html=True ) st.markdown( """ Upload an image to inspect digital artifacts and determine authenticity. **We encourage you to test the model's accuracy against synthetic content, such as images autogenerated by this site: [thispersondoesnotexist.com](https://thispersondoesnotexist.com/)** """ ) # --- Image Loading --- uploaded_file = st.file_uploader("Choose an image file:", type=["jpg", "jpeg", "png"]) active_image = None # --- CRASH PROTECTION LOGIC --- if uploaded_file: try: active_image = Image.open(uploaded_file) except Exception as e: st.error("⚠️ Format not supported. Please upload a valid image file (JPG, PNG).") # We leave active_image as None, so the code below won't run. elif sample_choice != "None": if sample_choice == "Sample Real (Organic)": file_path = os.path.join(SAMPLE_DIR, "real.jpg") else: file_path = os.path.join(SAMPLE_DIR, "fake.jpg") if os.path.exists(file_path): active_image = Image.open(file_path) # --- Analysis Logic --- if active_image: col1, col2 = st.columns([0.5, 0.5], gap="large") with col1: st.image(active_image, caption="Input Image") with col2: st.subheader("Analysis Results") with st.status("Scanning image artifacts...", expanded=True) as status: st.write("Preprocessing image (ResNet50 standard)...") processed_image = preprocess_image_for_resnet50(active_image, IMAGE_SIZE) st.write("Running inference...") prediction_probs = model.predict(processed_image) status.update(label="Analysis Complete!", state="complete", expanded=False) prob_real = float(prediction_probs[0][0]) if prob_real > 0.5: pred_class = "REAL" sub_text = "Organic Photography" confidence_val = f"{prob_real:.2%}" st.markdown(f"""
Prediction Result
✅ {pred_class}
Confidence: {confidence_val}

{sub_text}

""", unsafe_allow_html=True) else: pred_class = "FAKE" sub_text = "AI-Generated / Synthetic" confidence_val = f"{(1 - prob_real):.2%}" st.markdown(f"""
Prediction Result
⚠️ {pred_class}
Confidence: {confidence_val}

{sub_text}

""", unsafe_allow_html=True) elif not active_image and not uploaded_file: # Only show this instruction if nothing is uploaded and no error occurred st.info("👈 Upload an image or select a sample from the sidebar to start.") #to run nacho : streamlit run /Users/ignacioalarconvarela/Developer/AI-Image-Detector/Deployment/main2.py