diff --git a/src/face_classifying.py b/src/face_classifying.py new file mode 100644 index 0000000..cfb3545 --- /dev/null +++ b/src/face_classifying.py @@ -0,0 +1,28 @@ +from face_recognition import * + +def classify_faces(faces, threshold:float = 0.65): + + # classify each faces + res = {} + for face in faces: + + score = 0 + max_score = 0 + nearest_person = None + + for person, faces in res.items(): + for face2 in faces: + score += is_same_face(face.img, face2.img) + + score /= len(faces) + + if score > max_score: + nearest_person = person + max_score = score + + if max_score > threshold: + res[nearest_person].append(face) + else: + res[f"persone_{len(res)}"] = [face] + + return res \ No newline at end of file diff --git a/src/face_recognition.py b/src/face_recognition.py index e8e9df3..389502d 100644 --- a/src/face_recognition.py +++ b/src/face_recognition.py @@ -7,7 +7,7 @@ def extract_faces(faces_data:list, img:list, filename:str): recognizer = Recognizer.get() res = [] - for i in range(1, len(faces_data[1])): + for i in range(len(faces_data[1])): face_data = faces_data[1][i] croped_img = recognizer.alignCrop(img, face_data) @@ -33,4 +33,21 @@ def is_same_face( cosine_score = recognizer.match(faces1_features, faces2_features, cv2.FaceRecognizerSF_FR_COSINE) l2_score = recognizer.match(faces1_features, faces2_features, cv2.FaceRecognizerSF_FR_NORM_L2) - return cosine_score >= cosine_similarity_threshold and l2_score <= l2_similarity_threshold \ No newline at end of file + return cosine_score >= cosine_similarity_threshold and l2_score <= l2_similarity_threshold + +def similarity_score( + face1_img:list, + face2_img:list, + cosine_similarity_threshold:float = 0.363, + l2_similarity_threshold:float = 1.128 +) -> bool: + + recognizer = Recognizer.get() + + faces1_features = recognizer.feature(face1_img) + faces2_features = recognizer.feature(face2_img) + + cosine_score = recognizer.match(faces1_features, faces2_features, cv2.FaceRecognizerSF_FR_COSINE) + l2_score = recognizer.match(faces1_features, faces2_features, cv2.FaceRecognizerSF_FR_NORM_L2) + + return (int(cosine_score >= cosine_similarity_threshold) + int(l2_score <= l2_similarity_threshold)) / 2 \ No newline at end of file diff --git a/src/main.py b/src/main.py index 8963a37..dd9c2ce 100644 --- a/src/main.py +++ b/src/main.py @@ -4,10 +4,13 @@ import os from utils import * from face_detection import * from face_recognition import * +from face_classifying import * # list all files in data/raw files = list_all_files("./data/raw", ["jpg", "webp"]) +print(files) + # process each files faces = [] for file_path in files: @@ -23,12 +26,23 @@ for file_path in files: # detect faces file faces_data = detect_face_in_image(img, scale=1) - print("faces_data: ", faces_data[1]) # extract faces from file - faces += extract_faces(faces_data, img, filename) + extracted_faces = extract_faces(faces_data, img, filename) -# classify each faces -for face in faces: - face.save("./data/extracted") + faces += extracted_faces + +classified_faces = classify_faces(faces) + +# saving result by folders +for person, faces in classified_faces.items(): + dir_ = f"./data/results/{person}/" + if not os.path.exists(dir_): + os.makedirs(dir_) + + for face in faces: + face.save(dir_) + + +print("classified_faces: ", classified_faces) cv2.destroyAllWindows() \ No newline at end of file