| import cv2 |
| import numpy as np |
| import torch |
| from PIL import Image |
| from facenet_pytorch import MTCNN, InceptionResnetV1 |
| import gradio as gr |
| import zipfile |
| import os |
| import shutil |
| import traceback |
|
|
| |
| try: |
| mtcnn = MTCNN(image_size=160, margin=0, min_face_size=20) |
| resnet = InceptionResnetV1(pretrained='vggface2').eval() |
| except Exception as e: |
| print(f"Error loading models: {e}") |
|
|
| |
| def preprocess_image(image): |
| try: |
| image = Image.fromarray(image) |
| image_cropped = mtcnn(image) |
| if image_cropped is not None: |
| image_embedding = resnet(image_cropped.unsqueeze(0)) |
| return image_embedding |
| else: |
| print("No face detected in image during preprocessing.") |
| except Exception as e: |
| print(f"Error preprocessing image: {e}") |
| return None |
|
|
| |
| def load_embeddings_from_folder(folder_path): |
| embeddings = [] |
| try: |
| for filename in os.listdir(folder_path): |
| img_path = os.path.join(folder_path, filename) |
| image = cv2.imread(img_path) |
| if image is None: |
| print(f"Image {filename} could not be read or is not in a supported format.") |
| continue |
| embedding = preprocess_image(image) |
| if embedding is not None: |
| embeddings.append((filename, embedding)) |
| else: |
| print(f"Embedding for {filename} could not be generated.") |
| except Exception as e: |
| print(f"Error loading embeddings from folder {folder_path}: {e}") |
| return embeddings |
|
|
| |
| def compare_embeddings(embedding1, embedding2, threshold=0.3): |
| try: |
| similarity = torch.nn.functional.cosine_similarity(embedding1, embedding2) |
| return similarity.item() > threshold |
| except Exception as e: |
| print(f"Error comparing embeddings: {e}") |
| return False |
|
|
| |
| def identify_non_matching_faces(folder_a_zip, folder_b_zip): |
| try: |
| |
| folder_a_path = "temp_folder_a" |
| folder_b_path = "temp_folder_b" |
| non_matching_folder = "non_matching_images" |
| os.makedirs(folder_a_path, exist_ok=True) |
| os.makedirs(folder_b_path, exist_ok=True) |
| os.makedirs(non_matching_folder, exist_ok=True) |
|
|
| |
| with zipfile.ZipFile(folder_a_zip, 'r') as zip_ref: |
| zip_ref.extractall(folder_a_path) |
| with zipfile.ZipFile(folder_b_zip, 'r') as zip_ref: |
| zip_ref.extractall(folder_b_path) |
|
|
| |
| embeddings_a = load_embeddings_from_folder(folder_a_path) |
| embeddings_b = load_embeddings_from_folder(folder_b_path) |
|
|
| if not embeddings_a: |
| print("No valid embeddings found in Folder A.") |
| if not embeddings_b: |
| print("No valid embeddings found in Folder B.") |
|
|
| |
| non_matching_images = [] |
|
|
| for name_a, embedding_a in embeddings_a: |
| match_found = False |
| for name_b, embedding_b in embeddings_b: |
| similarity = torch.nn.functional.cosine_similarity(embedding_a, embedding_b).item() |
| print(f"Comparing {name_a} with {name_b} | Similarity: {similarity}") |
|
|
| if similarity > 0.3: |
| match_found = True |
| break |
| if not match_found: |
| print(f"Non-matching image found: {name_a}") |
| non_matching_images.append(name_a) |
| shutil.copy(os.path.join(folder_a_path, name_a), os.path.join(non_matching_folder, name_a)) |
|
|
| if non_matching_images: |
| |
| zip_filename = "non_matching_images.zip" |
| with zipfile.ZipFile(zip_filename, 'w') as zipf: |
| for root, _, files in os.walk(non_matching_folder): |
| for file in files: |
| zipf.write(os.path.join(root, file), arcname=file) |
| print("Non-matching images found and zipped.") |
| return zip_filename |
| else: |
| print("No non-matching images found.") |
| shutil.rmtree(non_matching_folder) |
| return None |
|
|
| except Exception as e: |
| |
| error_message = f"An error occurred: {str(e)}\n{traceback.format_exc()}" |
| print(error_message) |
| return error_message |
|
|
| |
| def gradio_interface(folder_a_zip, folder_b_zip): |
| result = identify_non_matching_faces(folder_a_zip.name, folder_b_zip.name) |
| if isinstance(result, str) and result.endswith('.zip'): |
| return result |
| elif result is None: |
| return "No non-matching images found." |
| else: |
| return result |
|
|
| with gr.Blocks() as demo: |
| gr.Markdown("# Face Comparison between Two Zipped Image Folders") |
|
|
| with gr.Row(): |
| folder_a_input = gr.File(label="Upload Zipped Folder A", type="filepath") |
| folder_b_input = gr.File(label="Upload Zipped Folder B", type="filepath") |
| compare_faces_button = gr.Button("Find Non-Matching Faces") |
| download_link = gr.File(label="Download Non-Matching Images Zip") |
|
|
| compare_faces_button.click(gradio_interface, inputs=[folder_a_input, folder_b_input], outputs=[download_link]) |
|
|
| |
| demo.launch() |
|
|