Yao211's picture
Update ui.py
a295265 verified
Raw
History Blame Contribute Delete
5.77 kB
import gradio as gr
from api import check_liveness
EXAMPLE_IMAGES = [
["assets/1.jpg"],
["assets/2.jpg"],
["assets/3.jpg"],
["assets/4.jpg"],
["assets/5.jpg"],
["assets/6.jpg"],
]
def _normalize_keys(d: dict) -> dict:
return {k.strip().replace(" ", "_"): v for k, v in d.items()}
def _format_result_html(result: dict) -> str:
r = _normalize_keys(result)
liveness_text = r.get("liveness_result", "").lower()
is_genuine = "genuine" in liveness_text
probability = r.get("probability", 0)
if isinstance(probability, str):
try:
probability = float(probability)
except (ValueError, TypeError):
probability = 0
score = r.get("score", 0)
if isinstance(score, str):
try:
score = float(score)
except (ValueError, TypeError):
score = 0
quality = r.get("quality", 0)
if isinstance(quality, str):
try:
quality = float(quality)
except (ValueError, TypeError):
quality = 0
pct = round(max(0, min(probability, 1)) * 100)
if is_genuine:
badge_text = "✅ GENUINE / LIVE"
badge_color = "#059669"
bg_color = "#ecfdf5"
border_color = "#a7f3d0"
score_color = "#059669"
else:
badge_text = "❌ SPOOF / FAKE"
badge_color = "#dc2626"
bg_color = "#fef2f2"
border_color = "#fecaca"
score_color = "#dc2626"
html = f"""
<div style="padding: 12px 0;">
<div style="background: {bg_color}; border: 2px solid {border_color};
border-radius: 16px; padding: 24px;">
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 20px;">
<span style="font-size: 22px; font-weight: 700; color: #1e293b;">
Liveness Result
</span>
</div>
<div style="display: inline-block; padding: 8px 24px; border-radius: 999px;
background: {badge_color}; color: white; font-weight: 700;
font-size: 18px; letter-spacing: 0.5px; margin-bottom: 20px;">
{badge_text}
</div>
<div style="margin-top: 16px;">
<div style="display: flex; justify-content: space-between; margin-bottom: 6px;">
<span style="font-weight: 600; color: #475569;">Confidence</span>
<span style="font-weight: 700; color: {score_color};">{pct}%</span>
</div>
<div style="background: #e2e8f0; border-radius: 999px; height: 10px; overflow: hidden;">
<div style="width: {pct}%; height: 100%; background: {badge_color};
border-radius: 999px;"></div>
</div>
</div>
<div style="margin-top: 14px; display: flex; gap: 24px;">
<div>
<span style="font-size: 13px; color: #94a3b8;">Quality</span>
<div style="font-weight: 600; color: #334155;">
{round(quality * 100)}%
</div>
</div>
<div>
<span style="font-size: 13px; color: #94a3b8;">Score</span>
<div style="font-weight: 600; color: #334155;">
{score:.4f}
</div>
</div>
<div>
<span style="font-size: 13px; color: #94a3b8;">Status</span>
<div style="font-weight: 600; color: #334155;">
{r.get("state", "")}
</div>
</div>
</div>
</div>
</div>
"""
return html
def process_image(image):
if image is None:
return (
'<div style="padding:20px;text-align:center;color:#94a3b8;">'
"Upload or select an example image</div>",
{"error": "No image provided"},
)
result = check_liveness(image)
if "error" in result:
return (
f'<div style="padding:20px;text-align:center;color:#dc2626;">{result["error"]}</div>',
result,
)
return _format_result_html(result), result
def create_interface():
with gr.Blocks(
title="MiniAiLive Face Liveness Detection",
theme=gr.themes.Soft(
primary_hue="emerald",
neutral_hue="slate",
),
css="""
footer {display: none !important;}
""",
) as demo:
gr.Markdown(
"""
# 🥇 MiniAiLive Face Liveness Detection
**3D Passive Face Liveness Detection · Face Anti-Spoofing** ·
<a href="https://miniai.live/face-liveness-detection/">For more details: please visit our website</a>
Upload a face image or click an example below to check liveness.
"""
)
with gr.Row(equal_height=False):
with gr.Column(scale=1, min_width=400):
image_input = gr.Image(label="Upload Image")
submit_btn = gr.Button(
"Check Liveness", variant="primary", size="lg"
)
gr.Examples(
examples=EXAMPLE_IMAGES,
inputs=image_input,
label="Example Images",
)
with gr.Column(scale=1, min_width=400):
result_html = gr.HTML(label="Result")
raw_json = gr.JSON(label="Raw Response")
submit_btn.click(
fn=process_image,
inputs=image_input,
outputs=[result_html, raw_json],
)
return demo