import os import requests import gradio as gr HTML_HEADER = """

Demo of Face Liveness Detection

To learn more, visit our website: https://dataspike.io/

Visitor Count
""" HTML_IQA_FAILED = """

Liveness Checks Not Performed

The liveness checks could not be conducted because the quality of the submitted image is not acceptable. Please ensure that your selfie meets the following criteria for optimal quality:

Please re-upload a clearer selfie to proceed with the liveness verification.

""" HTML_HEAD_POSITION_FAILED = """

Liveness Checks Not Performed

The liveness checks could not be conducted because the position of the head in the submitted image does not meet the required criteria. Please ensure that your selfie adheres to the following guidelines for optimal head positioning:

Please re-upload a selfie that meets these criteria to proceed with the liveness verification.

""" HTML_SUCCESSFUL_PRECHECKS = """

Explanation of Results

Below is an explanation of the checks we run on the uploaded selfie to determine its quality, head position, and whether the selfie is genuine or not.

""" HTML_FACE_COMPARISON_HEADER = """

Demo of Face Comparison

To learn more, visit our website: https://dataspike.io/

""" HTML_FACE_COMPARISON_EXPLANATION = """

🔍 Face Comparison Results Explanation

The system compares two photos and provides one of four results:

""" def check_liveness(file_path): if file_path: url = "https://api.dataspike.io/api/v4/upload/liveness-demo" headers = {"ds-api-token": os.getenv("API_KEY")} files = {"file": open(file_path, "rb")} response = requests.post(url, headers=headers, files=files) liveness_result = response.json() if ( "ran_checks" not in liveness_result.keys() or len(liveness_result["ran_checks"]) == 0 ): msg = "" elif liveness_result["ran_checks"] == ["ImageQuality"]: msg = HTML_IQA_FAILED elif liveness_result["ran_checks"] == ["ImageQuality", "HeadPosition"]: msg = HTML_HEAD_POSITION_FAILED else: msg = HTML_SUCCESSFUL_PRECHECKS return liveness_result, msg, True else: liveness_result = { "overallStatus": "Failure", "errors": [ "The image is not found. Please, submit an image first and then click the button 'Check Liveness!'" ], } return liveness_result, "", False def map_fc_result(api_status: str): mapping = { "FaceComparisonVerified": {"label": "Same Person", "color": "#2ECC71"}, "FaceComparisonUnknown": {"label": "Failure", "color": "#95A5A6"}, "FaceComparisonFailedDifferentFaces": { "label": "Different Person", "color": "#E74C3C", }, "FaceComparisonFailedSamePhotos": {"label": "Same Photo", "color": "#F1C40F"}, } status = api_status["status"] if "status" in api_status.keys() else "" return mapping.get(status, {"label": "Unknown", "color": "gray"}) def compare_faces(image1_path, image2_path): if image1_path and image2_path: url = "https://api.dataspike.io/api/v4/upload/face-comparison-demo" headers = {"ds-api-token": os.getenv("API_KEY")} files = {"left": open(image1_path, "rb"), "right": open(image2_path, "rb")} response = requests.post(url, headers=headers, files=files) comparison_result = response.json() result = map_fc_result(comparison_result) return gr.Label(value=result["label"], color=result["color"]), True # return comparison_result, True else: comparison_result = { "overallStatus": "Failure", "errors": ["Please submit both images before comparing"], } return comparison_result, "", False tabs_css = """ /* Style all Gradio tab buttons */ button[role="tab"] { font-size: 14px !important; font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; padding: 12px 24px !important; margin: 0 6px !important; background-color: #0B0F19 !important; color: #F3F4F6 !important; border-radius: 8px !important; border: 1px solid #1a1a1a !important; box-shadow: none !important; transition: all 0.2s ease !important; } /* Style selected tab button */ button[role="tab"].selected { background-color: #635bff !important; color: white !important; box-shadow: 0 0 6px rgba(99, 91, 255, 0.5) !important; } /* Inactive tab style */ button[role="tab"]:not(.selected) { font-size: 14px !important; font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; padding: 12px 24px !important; margin: 0 6px !important; background-color: #9D2C53 !important; color: #F3F4F6 !important; border-radius: 8px !important; border: 1px solid #1a1a1a !important; box-shadow: none !important; transition: all 0.2s ease !important; } /* Optional: hover effect */ button[role="tab"]:hover { background-color: #1a1a2b !important; color: white !important; } """ with gr.Blocks(theme=gr.themes.Soft(), css=tabs_css) as Demo: with gr.Tabs(): with gr.Tab("Liveness Detection"): header_box = gr.HTML(HTML_HEADER) with gr.Row(): with gr.Column(scale=1): input_img_path = gr.Image( label="Input Image", type="filepath", height=300 ) gr.Examples( [ "images/real_client054_android_SD_scene01.jpg", "images/attack_client006_android_SD_ipad_video_scene01.jpg", "images/attack_client055_android_SD_iphone_video_scene01.jpg", "images/attack_client026_android_SD_printed_photo_scene01.jpg", "images/attack_deepfake_1.jpg", "images/attack_deepfake_3.jpg", "images/attack_mask.jpg", "images/tiktok_3d_mask.jpeg", ], inputs=input_img_path, ) check_button = gr.Button("Check Liveness!", variant="primary") with gr.Column(): liveness_result = gr.JSON(label="Liveness Result") explanation_box = gr.HTML("", visible=False) state = gr.State(False) check_button.click( check_liveness, inputs=input_img_path, outputs=[liveness_result, explanation_box, state], ) state.change( lambda show: gr.update(visible=show), inputs=state, outputs=explanation_box, ) with gr.Tab("Face Comparison"): gr.HTML(HTML_FACE_COMPARISON_HEADER) with gr.Row(): with gr.Column(): image1_input = gr.Image( label="First Image", type="filepath", height=300 ) gr.Examples( [ "images/brad_pitt_1.jpeg", "images/brad_pitt_2.jpeg", "images/angelina-jolie-1.jpeg", "images/angelina-jolie-2.jpeg", ], inputs=image1_input, ) with gr.Column(): image2_input = gr.Image( label="Second Image", type="filepath", height=300 ) gr.Examples( [ "images/brad_pitt_1.jpeg", "images/brad_pitt_2.jpeg", "images/angelina-jolie-1.jpeg", "images/angelina-jolie-2.jpeg", ], inputs=image2_input, ) compare_button = gr.Button("Compare Faces!", variant="primary") comparison_result = gr.Label(label="Comparison Result") gr.HTML(HTML_FACE_COMPARISON_EXPLANATION) comparison_state = gr.State(False) compare_button.click( compare_faces, inputs=[image1_input, image2_input], outputs=[comparison_result, comparison_state], ) if __name__ == "__main__": Demo.launch()