# SPDX-FileCopyrightText: 2025 Idiap Research Institute # SPDX-FileContributor: Anjith George # SPDX-License-Identifier: BSD-3-Clause """EdgeFace demo""" from __future__ import annotations from pathlib import Path import cv2 import gradio as gr import numpy as np import torch import torch.nn.functional as F from torchvision import transforms from utils import align_crop # ─────────────────────────────── # Data & models # ─────────────────────────────── DATA_DIR = Path("data") EXTS = (".jpg", ".jpeg", ".png", ".bmp", ".webp") PRELOADED = sorted(p for p in DATA_DIR.iterdir() if p.suffix.lower() in EXTS) EDGE_MODELS = [ "edgeface_base", "edgeface_s_gamma_05", "edgeface_xs_gamma_06", "edgeface_xxs", ] # ─────────────────────────────── # Styling (orange palette) # ─────────────────────────────── PRIMARY = "#F97316" PRIMARY_DARK = "#C2410C" ACCENT_LIGHT = "#FFEAD2" BG_LIGHT = "#FFFBF7" TEXT_DARK = "#0F172A" CSS = f""" @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap'); /* ─── palette ───────────────────────────────────────────── */ body {{ font-family:'Inter',sans-serif; background:{BG_LIGHT}; color:{TEXT_DARK}; }} a {{ color:{PRIMARY}; text-decoration:none; font-weight:600; }} a:hover {{color:{PRIMARY_DARK}}} /* ─── headline ──────────────────────────────────────────── */ #titlebar {{ text-align:center; margin-top:2.4rem; margin-bottom:.9rem; }} #edgeface-title {{ font-size:2.6rem; font-weight:800; margin:0; line-height:1.25; color: #0F172A; }} #edgeface-title .brand {{ background:linear-gradient(90deg,{PRIMARY} 0%,{PRIMARY_DARK} 90%); -webkit-background-clip:text; color:transparent; }} /* ─── card look ─────────────────────────────────────────── */ .gr-block, .gr-box, .gr-row, #cite-wrapper {{ border:1px solid #F8C89B; border-radius:10px; background:#fff; box-shadow:0 3px 6px rgba(0,0,0,.05); }} .gr-gallery-item {{background:#fff}} /* ─── controls / inputs ─────────────────────────────────── */ .gr-button-primary, #copy-btn {{ background:linear-gradient(90deg,{PRIMARY} 0%,{PRIMARY_DARK} 100%); border:none; color:#fff; border-radius:6px; font-weight:600; transition:transform .12s ease,box-shadow .12s ease; }} .gr-button-primary:hover, #copy-btn:hover {{ transform:translateY(-2px); box-shadow:0 4px 12px rgba(249,115,22,.35); }} .gr-dropdown input {{border:1px solid {PRIMARY}99}} .preview img, .preview canvas {{object-fit:contain!important}} /* ─── hero section ─────────────────────────────────────── */ #hero-wrapper {{text-align:center}} #hero-badge {{ display:inline-block; padding:.85rem 1.2rem; border-radius:8px; background:{ACCENT_LIGHT}; border:1px solid {PRIMARY}55; font-size:.95rem; font-weight:600; margin-bottom:.5rem; }} #hero-links {{ font-size:.95rem; font-weight:600; margin-bottom:1.6rem; }} #hero-links img {{ height:22px; vertical-align:middle; margin-left:.55rem; }} /* ─── score area ───────────────────────────────────────── */ #score-area {{ text-align:center; /* ← centres the badge */ }} .match-badge {{ display:inline-block; padding:.35rem .9rem; border-radius:9999px; font-weight:600; font-size:1.25rem; /* ← slightly larger */ }} /* ─── citation card ────────────────────────────────────── */ #cite-wrapper {{ position:relative; padding:.9rem 1rem; margin-top:2rem; }} #cite-wrapper code {{ font-family: SFMono-Regular, Consolas, monospace; font-size: .84rem; white-space: pre-wrap; color: #0F172A; }} #copy-btn {{ position:absolute; top:.55rem; right:.6rem; padding:.18rem .7rem; font-size:.72rem; line-height:1; }} """ # ─────────────────────────────── # Torch / transforms # ─────────────────────────────── _tx = transforms.Compose([ transforms.ToTensor(), transforms.Normalize([0.5, 0.5, 0.5],[0.5, 0.5, 0.5]), ]) def get_edge_model(name:str)->torch.nn.Module: if name not in get_edge_model.cache: mdl=torch.hub.load("otroshi/edgeface",name,source="github",pretrained=True).eval() mdl.to("cuda" if torch.cuda.is_available() else "cpu") get_edge_model.cache[name]=mdl return get_edge_model.cache[name] get_edge_model.cache={} # ─────────────────────────────── # Helpers # ─────────────────────────────── def _as_rgb(path:Path)->np.ndarray: return cv2.cvtColor(cv2.imread(str(path)),cv2.COLOR_BGR2RGB) def badge(text:str,colour:str)->str: return f'
@article{edgeface,
title = {{EdgeFace: Efficient Face Recognition Model for Edge Devices}},
author = {{George, A. and Ecabert, C. and Otroshi, H. and Kotwal, K. and Marcel, S.}},
journal= {{IEEE Trans. Biometrics, Behavior, & Identity Science}},
year = {{2024}}
}