Spaces:
Running
Running
File size: 3,464 Bytes
9e1ec94 fae5be7 9e1ec94 2b7c418 9e1ec94 40a4317 9e1ec94 f430918 9e1ec94 fae5be7 9e1ec94 fae5be7 9e1ec94 fae5be7 9e1ec94 22320ed 9e1ec94 2bc188c |
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 |
import os
import json
import math
os.environ["DEEPFACE_HOME"] = "."
import pyzipper
import numpy as np
import gradio as gr
from annoy import AnnoyIndex
from deepface.commons import functions
from deepface.basemodels import Facenet512
# load the face model
model = Facenet512.loadModel()
input_shape_x, input_shape_y = functions.find_input_shape(model)
index = AnnoyIndex(512, "euclidean")
index.load(f"face.db")
ANNOY_INDEX = json.load(open(f"face.json"))
with pyzipper.AESZipFile('persons.zip') as zf:
password = os.getenv("VISAGE_KEY","").encode('ascii')
zf.setpassword(password)
PERFORMER_DB = json.loads(zf.read('performers.json'))
def predict(image, threshold=20.0, results=3):
image_array = np.array(image)
img = functions.preprocess_face(
img=image_array,
target_size=(input_shape_x, input_shape_y),
enforce_detection=True,
detector_backend="retinaface",
align=True,
)
img = functions.normalize_input(img, normalization="Facenet2018")
face = model.predict(img)[0].tolist()
ids, distances = index.get_nns_by_vector(
face, 50, search_k=10000, include_distances=True
)
persons = {}
for p, distance in zip(ids, distances):
id = ANNOY_INDEX[p]
if id in persons:
persons[id]["hits"] += 1
persons[id]["distance"] -= 0.5
persons[id]["confidence"] = normalize_confidence_from_distance(persons[id]["distance"], threshold)
continue
persons[id] = {
"id": id,
"distance": round(distance, 2),
"confidence": normalize_confidence_from_distance(distance, threshold),
"hits": 1,
}
if id in PERFORMER_DB:
persons[id].update(PERFORMER_DB.get(id))
persons = sorted(persons.values(), key=lambda x: x["distance"])
persons = [p for p in persons if p["distance"] < threshold]
return persons[:results]
def normalize_confidence_from_distance(distance, threshold=20.0):
"""Normalize confidence to 0-100 scale"""
confidence = face_distance_to_conf(distance, threshold)
return int(((confidence - 0.0) / (1.0 - 0.0)) * (100.0 - 0.0) + 0.0)
def face_distance_to_conf(face_distance, face_match_threshold=20.0):
"""Using a face distance, calculate a similarity confidence value"""
if face_distance > face_match_threshold:
# The face is far away, so give it a low confidence
range = (1.0 - face_match_threshold)
linear_val = (1.0 - face_distance) / (range * 2.0)
return linear_val
else:
# The face is close, so give it a high confidence
range = face_match_threshold
linear_val = 1.0 - (face_distance / (range * 2.0))
# But adjust this value by a curve so that we don't get a linear
# transition from close to far. We want it to be more confident
# the closer it is.
return linear_val + ((1.0 - linear_val) * math.pow((linear_val - 0.5) * 2, 0.2))
gr.Interface(
fn=predict,
inputs=[
gr.components.Image(),
gr.components.Slider(label="threshold",minimum=0.0, maximum=30.0, value=20.0),
gr.components.Slider(label="results", minimum=0, maximum=50, value=3, step=1),
],
outputs=gr.outputs.JSON(label=""),
title="Who is in the photo?",
description="Upload an image of a person and we'll tell you who it is.",
).launch(enable_queue=True, server_name="0.0.0.0")
|