# app.py import streamlit as st from PIL import Image import io from face_swap import swap_faces # --- Page config --- st.set_page_config(page_title="🎭 Face Swap Demo", layout="centered") # --- Hero section --- st.markdown( """
🎭 Face Swap Demo
Upload two images and see the magic of AI face-swapping
""", unsafe_allow_html=True, ) # --- Upload section in cards --- col1, col2 = st.columns(2) with col1: st.markdown("### 🧑 Source Face") src_file = st.file_uploader( "Upload Source Image", type=["jpg", "jpeg", "png"], key="src" ) with col2: st.markdown("### 🎯 Target Image") tgt_file = st.file_uploader( "Upload Target Image", type=["jpg", "jpeg", "png"], key="tgt" ) # --- Options --- with st.sidebar: st.header("⚙️ Options") resize_max = st.number_input( "Resize images to max dimension (px)", value=800, min_value=200, max_value=2000 ) download_name = st.text_input("Download filename", value="face_swap_result.png") def load_image(file): img = Image.open(file).convert("RGB") # resize if large w, h = img.size max_dim = max(w, h) if max_dim > resize_max: scale = resize_max / max_dim img = img.resize((int(w * scale), int(h * scale)), Image.LANCZOS) return img # --- Run button --- if st.button("🚀 Run Face Swap", use_container_width=True): if not src_file or not tgt_file: st.error("⚠️ Please upload both source and target images.") else: src_img = load_image(src_file) tgt_img = load_image(tgt_file) st.markdown("### 🔍 Preview Images") st.image([src_img, tgt_img], caption=["Source", "Target"], width=300) with st.spinner("Running face-swap... please wait ⏳"): try: result_pil = swap_faces(src_img, tgt_img) st.success("✨ Done! Check the result below") # Show side-by-side comparison col_a, col_b = st.columns(2) with col_a: st.markdown("**Before**") st.image(tgt_img, use_column_width=True) with col_b: st.markdown("**After (Swapped)**") st.image(result_pil, use_column_width=True) # Download button buf = io.BytesIO() result_pil.save(buf, format="PNG") st.download_button( "⬇️ Download result", buf.getvalue(), file_name=download_name, mime="image/png", use_container_width=True, ) except Exception as e: st.error(f"❌ Face-swap failed: {e}") st.exception(e) # --- Footer --- st.markdown( """
Built with ❤️ using Streamlit and InsightFace
""", unsafe_allow_html=True, )