Spaces:
Runtime error
Runtime error
File size: 5,789 Bytes
8434bec 92629f4 8434bec c71100c 8434bec 92629f4 8434bec 92629f4 8434bec 92629f4 8434bec 92629f4 bd5a570 8434bec bd5a570 b3c844a 8434bec bd5a570 8434bec b3c844a bd5a570 8434bec bd5a570 c71100c bd5a570 b3c844a bd5a570 b3c844a bd5a570 8434bec 92629f4 bd5a570 92629f4 bd5a570 92629f4 bd5a570 8434bec ace09f3 af0a77b 8434bec ace09f3 8434bec af0a77b 5892042 8434bec 2a48472 c71100c 8434bec a11b506 b085e05 8434bec 92629f4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
import json
import zipfile
import numpy as np
import cv2
import os
import gradio as gr
from deepface import DeepFace
from ultralytics import YOLO
import urllib.request
import asyncio
with open('config.json', 'r') as f:
config = json.load(f)
FACE_DIST_TRESH = config['FACE_DIST_TRESH']
FACE_DET_TRESH = config['FACE_DET_TRESH']
YOLO_WEIGHTS_URL = config['YOLO_WEIGHTS_URL']
yolo_weights_filename = os.path.basename(YOLO_WEIGHTS_URL)
if not os.path.exists(yolo_weights_filename):
urllib.request.urlretrieve(YOLO_WEIGHTS_URL, yolo_weights_filename)
model = YOLO(yolo_weights_filename)
async def find_distance(base_face, check_face):
result = await asyncio.to_thread(DeepFace.verify, base_face, check_face, enforce_detection=False)
return result['distance']
def find_faces(image):
outputs = model(image)
faces = []
for box in outputs[0].boxes:
if float(box.conf) >= FACE_DET_TRESH:
x, y, w, h = [int(coord) for coord in box.xywh[0]]
x_center, y_center = x + w / 2, y + h / 2
x1 = int(x_center - w)
y1 = int(y_center - h)
crop_img = image[y1:y1+h, x1:x1+w]
faces.append(crop_img)
return faces
async def load_images_from_zip(zip_path):
images = []
loop = asyncio.get_running_loop()
with zipfile.ZipFile(zip_path, 'r') as zip_file:
for file_name in zip_file.namelist():
with zip_file.open(file_name) as file:
img_bytes = await loop.run_in_executor(None, file.read)
img = cv2.imdecode(np.frombuffer(img_bytes, np.uint8), cv2.IMREAD_COLOR)
if img is not None:
images.append(img)
return images
def create_image(images):
table_width = 800
row_height = 100
margin = 10
text_margin = 20
id_col_width = 100
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 0.5
color = (255, 255, 255)
thickness = 2
table_height = text_margin + margin + (row_height + margin) * len(images)
table = np.zeros((table_height, table_width, 3), np.uint8)
id_x = 10
img_x = id_col_width + 10
y = text_margin
cv2.putText(table, 'Image ID', (id_x, y), font, font_scale, color, thickness)
cv2.putText(table, 'Face', (img_x, y), font, font_scale, color, thickness)
y += margin
for i, img in enumerate(images):
height, width = img.shape[:2]
new_width = int(width * row_height / height)
if img_x + new_width > table_width:
new_width = table_width - img_x
img_resized = cv2.resize(img, (new_width, row_height))
cv2.putText(table, str(i), (id_x, y + margin), font, font_scale, color, thickness)
table[y:y+row_height, img_x:img_x+new_width] = img_resized
y += row_height + margin
for col in range(table.shape[1]-1, -1, -1):
if not np.any(table[:, col]):
continue
else:
break
table_cropped = table[:, :col+1+id_x]
return table_cropped
async def process_photo_async(photo, input_avatars_faces):
not_found_faces = []
avatars_faces_count = len(input_avatars_faces)
input_faces = find_faces(photo)
for input_face in input_faces:
for i in range(avatars_faces_count):
distance = await find_distance(input_avatars_faces[i], input_face)
if distance <= FACE_DIST_TRESH:
break
elif i + 1 == avatars_faces_count:
not_found_faces.append(input_face)
return not_found_faces
async def check_async(photos, input_avatars_faces, progress):
tasks = []
not_found_faces = []
for photo in photos:
task = asyncio.create_task(process_photo_async(photo, input_avatars_faces))
tasks.append(task)
for i, task in enumerate(tasks):
result = await task
not_found_faces += result
progress((i+1)/len(tasks))
return not_found_faces
def check(avatars_zip, photos_zip, progress=gr.Progress()):
avatars = asyncio.run(load_images_from_zip(avatars_zip.name))
avatars = [cv2.cvtColor(avatar, cv2.COLOR_RGB2BGR) for avatar in avatars]
photos = asyncio.run(load_images_from_zip(photos_zip.name))
photos = [cv2.cvtColor(photo, cv2.COLOR_RGB2BGR) for photo in photos]
input_avatars_faces = [find_faces(avatar) for avatar in avatars]
input_avatars_faces = [face for faces in input_avatars_faces for face in faces]
not_found_faces = asyncio.run(check_async(photos, input_avatars_faces, progress))
return create_image(not_found_faces)
title = '<h1 style="text-align:center">SquadDetective</h1>'
logo = '<center><img src="https://i.ibb.co/C0BH40g/logo.png" width="300" height="300" alt="SquadDetective logo"></center>'
with gr.Blocks(theme='soft', title='SquadDetective') as blocks:
gr.HTML(title)
gr.HTML(logo)
gr.Markdown('**SquadDetective** is a service that helps sports teams to identify unclaimed players by comparing their faces to photos taken during matches. By using state-of-the-art facial recognition technology, this service can quickly and accurately match the faces of players in photos to a database of registered players, allowing teams to quickly identify any unclaimed players and take appropriate action. With **SquadDetective**, sports teams can ensure that all players are properly registered and eligible to play, helping to avoid potential penalties and other issues.')
with gr.Row():
avatars = gr.inputs.File(label='Avatar photos (zip)')
photos = gr.inputs.File(label='Photos to be processed (zip)')
inputs = [avatars, photos]
process_button = gr.Button('Process')
outputs=gr.outputs.Image(type='numpy', label='Report')
process_button.click(fn=check, inputs=inputs, outputs=outputs)
blocks.queue(concurrency_count=1).launch() |