Yao211's picture
Update ui.py
57e5671 verified
Raw
History Blame Contribute Delete
5.73 kB
import gradio as gr
from api import check_liveness
EXAMPLE_IMAGES = [[f"assets/{i}.jpg"] for i in range(1, 4)]
THRESHOLD = 0.5
def _normalize(d: dict) -> dict:
return {k.strip().replace(" ", "_"): v for k, v in d.items()}
def _format_result_html(results: list) -> str:
if not results or (isinstance(results, dict) and "error" in results):
return ""
if isinstance(results, dict):
results = [results]
max_prob = 0
max_attack = ""
rows = ""
for item in results:
r = _normalize(item)
attack = r.get("attack_method", "Unknown")
prob = r.get("liveness_probability", 0)
score = r.get("liveness_score", 0)
quality = r.get("quality_score", 0)
state = r.get("state", "")
if isinstance(prob, str):
try:
prob = float(prob)
except (ValueError, TypeError):
prob = 0
if prob > max_prob:
max_prob = prob
max_attack = attack
pct = round(max(0, min(prob, 1)) * 100)
bar_color = "#059669" if prob < THRESHOLD else "#dc2626"
rows += f"""
<tr>
<td style="padding:8px 12px;font-weight:600;color:#334155;border-bottom:1px solid #f1f5f9;">
{attack}
</td>
<td style="padding:8px 12px;border-bottom:1px solid #f1f5f9;">
<div style="display:flex;align-items:center;gap:8px;">
<div style="flex:1;background:#e2e8f0;border-radius:999px;height:8px;overflow:hidden;">
<div style="width:{pct}%;height:100%;background:{bar_color};border-radius:999px;"></div>
</div>
<span style="font-weight:700;color:{bar_color};min-width:40px;text-align:right;">{pct}%</span>
</div>
</td>
<td style="padding:8px 12px;color:#64748b;border-bottom:1px solid #f1f5f9;text-align:center;">
{state}
</td>
</tr>"""
is_genuine = max_prob < THRESHOLD
if is_genuine:
badge_text = "✅ GENUINE / LIVE"
badge_color = "#059669"
bg_color = "#ecfdf5"
border_color = "#a7f3d0"
else:
badge_text = f"❌ SPOOF / FAKE — {max_attack}"
badge_color = "#dc2626"
bg_color = "#fef2f2"
border_color = "#fecaca"
return f"""
<div style="padding:12px 0;">
<div style="background:{bg_color};border:2px solid {border_color};
border-radius:16px;padding:24px;">
<div style="font-size:22px;font-weight:700;color:#1e293b;margin-bottom:16px;">
Liveness Result
</div>
<div style="display:inline-block;padding:8px 24px;border-radius:999px;
background:{badge_color};color:white;font-weight:700;
font-size:18px;margin-bottom:16px;">
{badge_text}
</div>
<div style="margin-top:16px;background:white;border:1px solid #e2e8f0;border-radius:12px;overflow:hidden;">
<table style="width:100%;border-collapse:collapse;">
<thead>
<tr style="background:#f8fafc;">
<th style="padding:8px 12px;text-align:left;font-weight:600;color:#64748b;">Attack Method</th>
<th style="padding:8px 12px;text-align:left;font-weight:600;color:#64748b;">Probability</th>
<th style="padding:8px 12px;text-align:center;font-weight:600;color:#64748b;">Status</th>
</tr>
</thead>
<tbody>
{rows}
</tbody>
</table>
</div>
</div>
</div>
"""
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 isinstance(result, dict) and "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 ID Document Liveness Detection",
theme=gr.themes.Soft(primary_hue="emerald", neutral_hue="slate"),
css="footer {display: none !important;}",
) as demo:
gr.Markdown(
"""
# 🥇 MiniAiLive ID Document Liveness Detection
**Advanced ID Document Liveness Detection · On-Premise SDK**
<a href="https://miniai.live/document-liveness-detection/">Please Visit Website</a>
Upload a document image to check if it is genuine or spoofed.
"""
)
with gr.Row(equal_height=False):
with gr.Column(scale=1, min_width=400):
image_input = gr.Image(label="Upload Document 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