| 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 |
|
|