| import os | |
| import gradio as gr | |
| import requests | |
| import base64 | |
| from io import BytesIO | |
| from PIL import Image | |
| import hashlib | |
| def image_to_base64(image): | |
| buffered = BytesIO() | |
| image.save(buffered, format="JPEG", quality=90) | |
| return base64.b64encode(buffered.getvalue()).decode('utf-8') | |
| def base64_to_image(base64_str): | |
| return base64.b64decode(base64_str + '=' * (-len(base64_str) % 4)) | |
| def check_db(img_array, suffix, token_server_url): | |
| hashes = [] | |
| out_array = [] | |
| for item in img_array: | |
| try: | |
| image_data = base64_to_image(item["image"]) | |
| hash_object = hashlib.sha256(image_data) | |
| image_hash = hash_object.hexdigest() | |
| hashes.append(image_hash) | |
| out_array.append((Image.open(BytesIO(image_data)), item["url"] + suffix)) | |
| except base64.binascii.Error as e: | |
| raise ValueError(f"Invalid base64 string: {str(e)}") | |
| except Exception as e: | |
| raise ValueError(f"Error processing image: {str(e)}") | |
| try: | |
| r = requests.post(url=token_server_url + '/lookup-hashes', json={"hashes": hashes}) | |
| out_array = [value for i, value in enumerate(out_array) if i not in r.json().get('res')] | |
| except: | |
| raise gr.Error("Token Server Error!") | |
| return out_array | |
| def search_face(file, token): | |
| free_url = os.environ.get("SERVER_URL_FREE") | |
| premium_url = os.environ.get("SERVER_URL_PREMIUM") | |
| token_server_url = os.environ.get("TOKEN_URL") | |
| url = free_url | |
| if token: | |
| try: | |
| r = requests.post(url=token_server_url + '/verify-token', json={"token": token}) | |
| if r.json().get('status') == 'success': | |
| url = premium_url | |
| else: | |
| raise gr.Error("Invalid token! For free search, use empty string for token") | |
| except: | |
| raise gr.Error("Invalid token!") | |
| try: | |
| image = Image.open(file) | |
| image_base64 = image_to_base64(image) | |
| r = requests.post(url=url, headers={"X-RapidAPI-Key": os.environ.get("API_KEY")}, json={"image": image_base64}) | |
| except: | |
| raise gr.Error("Please select image file!") | |
| status_code = r.status_code | |
| if status_code == 301: | |
| gr.Info("Too many faces in the photo.") | |
| elif status_code == 302: | |
| gr.Info("Face is not clear enough.") | |
| elif status_code == 303: | |
| gr.Info("No matches found.") | |
| elif status_code == 304: | |
| gr.Info("No face in the photo.") | |
| elif status_code == 305: | |
| gr.Info("Search blocked for privacy issue.") | |
| elif status_code == 401: | |
| gr.Info("Invalid image format.") | |
| elif status_code == 402: | |
| gr.Info("Wrong request.") | |
| elif status_code == 403: | |
| gr.Info("Please try again later.") | |
| elif status_code == 404: | |
| gr.Info("Timeout, try again.") | |
| if status_code > 300: | |
| return [] | |
| try: | |
| res = r.json().get('img_array') | |
| suffix = "*********" | |
| if url == premium_url: | |
| suffix = "" | |
| out_array = check_db(res, suffix, token_server_url) | |
| if url == premium_url: | |
| try: | |
| r = requests.post(url=token_server_url + '/activate-token', json={"token": token}) | |
| except: | |
| raise gr.Error("Invalid token!") | |
| return out_array | |
| except: | |
| raise gr.Error("Try again.") | |
| def search_face_free(file): | |
| return search_face(file, '') | |
| custom_css = """ | |
| caption.caption { | |
| user-select: text; | |
| cursor: text; | |
| } | |
| """ | |
| with gr.Blocks(css=custom_css) as demo: | |
| gr.Markdown( | |
| """ | |
| # Search Your Face Online For Free | |
| ## For more detailed information, please check on our website.<br/> | |
| ## [FaceOnLive: On-premises ID Verification, Biometric Authentication Solution Provider](https://faceonlive.com) | |
| <br> | |
| """ | |
| ) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| image = gr.Image(type='filepath', height=480) | |
| token = gr.Textbox(placeholder="(Optional) Premium Token via the link below.", label="Premium Token") | |
| gr.HTML("<a href='https://faceonlive.pocketsflow.com/checkout?productId=676c15b1971244a587ca07cb' target='_blank'>Get Premium Token: Perform Deep Search & Full URLs</a>") | |
| gr.HTML("<a href='https://faceonlive.pocketsflow.com/checkout?productId=676d7e7597f8b3b699f84820' target='_blank'>Send DMCA & GDPR Takedown Notices On Your Behalf, Opt-Out From Search</a>") | |
| search_face_button = gr.Button("Search Face") | |
| with gr.Column(scale=2): | |
| output = gr.Gallery(label="Found Images", columns=[4], object_fit="contain", height="auto") | |
| gr.Examples(['examples/1.jpg', 'examples/2.jpg'], inputs=image, cache_examples=True, cache_mode='lazy', fn=search_face_free, outputs=[output]) | |
| search_face_button.click(search_face, inputs=[image, token], outputs=[output], api_name=False) | |
| gr.HTML('<a href="https://visitorbadge.io/status?path=https%3A%2F%2Fhuggingface.co%2Fspaces%2FFaceOnLive%2FFace-Search-Online"><img src="https://api.visitorbadge.io/api/combined?path=https%3A%2F%2Fhuggingface.co%2Fspaces%2FFaceOnLive%2FFace-Search-Online&labelColor=%23ff8a65&countColor=%2337d67a&style=flat&labelStyle=upper" /></a>') | |
| demo.queue(api_open=False, default_concurrency_limit=4).launch(server_name="0.0.0.0", server_port=7860, show_api=False) |