90 lines
3.0 KiB
Python
90 lines
3.0 KiB
Python
from deepface import DeepFace
|
|
from deepface.commons import functions, distance as dst
|
|
import pandas as pd
|
|
import time
|
|
|
|
def face_find(
|
|
img_path,
|
|
global_face: list,
|
|
model_name="Facenet",
|
|
distance_metric="cosine",
|
|
enforce_detection=True,
|
|
detector_backend="opencv",
|
|
align=True,
|
|
normalization="base",
|
|
silent=False,
|
|
):
|
|
tic = time.time()
|
|
target_size = functions.find_target_size(model_name=model_name)
|
|
# now, we got representations for facial database
|
|
df = pd.DataFrame(global_face, columns=["identity", f"{model_name}_representation"])
|
|
|
|
# img path might have more than once face
|
|
target_objs = functions.extract_faces(
|
|
img=img_path,
|
|
target_size=target_size,
|
|
detector_backend=detector_backend,
|
|
grayscale=False,
|
|
enforce_detection=enforce_detection,
|
|
align=align,
|
|
)
|
|
|
|
resp_obj = []
|
|
|
|
for target_img, target_region, _ in target_objs:
|
|
target_embedding_obj = DeepFace.represent(
|
|
img_path=target_img,
|
|
model_name=model_name,
|
|
enforce_detection=enforce_detection,
|
|
detector_backend="skip",
|
|
align=align,
|
|
normalization=normalization,
|
|
)
|
|
|
|
target_representation = target_embedding_obj[0]["embedding"]
|
|
|
|
result_df = df.copy() # df will be filtered in each img
|
|
result_df["source_x"] = target_region["x"]
|
|
result_df["source_y"] = target_region["y"]
|
|
result_df["source_w"] = target_region["w"]
|
|
result_df["source_h"] = target_region["h"]
|
|
|
|
distances = []
|
|
for index, instance in df.iterrows():
|
|
source_representation = instance[f"{model_name}_representation"]
|
|
|
|
if distance_metric == "cosine":
|
|
distance = dst.findCosineDistance(source_representation, target_representation)
|
|
elif distance_metric == "euclidean":
|
|
distance = dst.findEuclideanDistance(source_representation, target_representation)
|
|
elif distance_metric == "euclidean_l2":
|
|
distance = dst.findEuclideanDistance(
|
|
dst.l2_normalize(source_representation),
|
|
dst.l2_normalize(target_representation),
|
|
)
|
|
else:
|
|
raise ValueError(f"invalid distance metric passes - {distance_metric}")
|
|
|
|
distances.append(distance)
|
|
|
|
# ---------------------------
|
|
|
|
result_df[f"{model_name}_{distance_metric}"] = distances
|
|
|
|
threshold = dst.findThreshold(model_name, distance_metric)
|
|
result_df = result_df.drop(columns=[f"{model_name}_representation"])
|
|
result_df = result_df[result_df[f"{model_name}_{distance_metric}"] <= threshold]
|
|
result_df = result_df.sort_values(
|
|
by=[f"{model_name}_{distance_metric}"], ascending=True
|
|
).reset_index(drop=True)
|
|
|
|
resp_obj.append(result_df)
|
|
|
|
# -----------------------------------
|
|
|
|
toc = time.time()
|
|
|
|
if not silent:
|
|
print("find function lasts ", toc - tic, " seconds")
|
|
|
|
return resp_obj |