This guide demonstrates how to use facenet-pytorch
to implement a tool for detecting face similarity. Built on the FaceNet
model, which generates high-quality face embeddings, the tool compares a target image with multiple pictures to identify the most similar face. Here the process to get started.
**
Key Tools and Libraries**
- PyTorch: For deep learning operations.
- FaceNet-PyTorch: Provides pre-trained models for face detection and embedding.
- Pillow (PIL): For image manipulation.
- Matplotlib: For visualizing results.
We'll use two main models:
- MTCNN: For detecting faces.
- InceptionResnetV1: For extracting face embeddings.
Initialization
import torch from facenet_pytorch import MTCNN, InceptionResnetV1 from PIL import Image import requests from io import BytesIO import matplotlib.pyplot as plt # Initialize the MTCNN module for face detection and the InceptionResnetV1 module for face embedding. mtcnn = MTCNN(image_size=160, keep_all=True) resnet = InceptionResnetV1(pretrained='vggface2').eval()
Function Definitions
1. Load Image and Extract Embedding:
This function loads an image from a URL, detects the face, and computes the embedding.
def get_embedding_and_face(image_path): """Load an image, detect the face, and return the embedding and face.""" try: response = requests.get(image_path) response.raise_for_status() content_type = response.headers.get('Content-Type') if 'image' not in content_type: raise ValueError(f"URL does not point to an image: {content_type}") image = Image.open(BytesIO(response.content)).convert("RGB") except Exception as e: print(f"Error loading image from {image_path}: {e}") return None, None faces, probs = mtcnn(image, return_prob=True) if faces is None or len(faces) == 0: return None, None embedding = resnet(faces[0].unsqueeze(0)) return embedding, faces[0]
2. Convert Tensor to Image:
This function prepares a tensor for visualization.
def tensor_to_image(tensor): """Convert a normalized tensor to a valid image array.""" image = tensor.permute(1, 2, 0).detach().numpy() image = (image - image.min()) / (image.max() - image.min()) image = (image * 255).astype('uint8') return image
3. Find the Most Similar Face:
This function compares the embeddings of the target image with the candidates.
def find_most_similar(target_image_path, candidate_image_paths): """Find the most similar image to the target image from a list of candidate images.""" target_emb, target_face = get_embedding_and_face(target_image_path) if target_emb is None: raise ValueError("No face detected in the target image.") highest_similarity = float('-inf') most_similar_face = None most_similar_image_path = None candidate_faces = [] similarities = [] for candidate_image_path in candidate_image_paths: candidate_emb, candidate_face = get_embedding_and_face(candidate_image_path) if candidate_emb is None: similarities.append(None) candidate_faces.append(None) continue similarity = torch.nn.functional.cosine_similarity(target_emb, candidate_emb).item() similarities.append(similarity) candidate_faces.append(candidate_face) if similarity > highest_similarity: highest_similarity = similarity most_similar_face = candidate_face most_similar_image_path = candidate_image_path # Visualization plt.figure(figsize=(12, 8)) # Display target image plt.subplot(2, len(candidate_image_paths) + 1, 1) plt.imshow(tensor_to_image(target_face)) plt.title("Target Image") plt.axis("off") # Display most similar image if most_similar_face is not None: plt.subplot(2, len(candidate_image_paths) + 1, 2) plt.imshow(tensor_to_image(most_similar_face)) plt.title("Most Similar") plt.axis("off") # Display all candidate images with similarity scores for idx, (candidate_face, similarity) in enumerate(zip(candidate_faces, similarities)): plt.subplot(2, len(candidate_image_paths) + 1, idx + len(candidate_image_paths) + 2) if candidate_face is not None: plt.imshow(tensor_to_image(candidate_face)) plt.title(f"Score: {similarity * 100:.2f}%") else: plt.title("No Face") plt.axis("off") plt.tight_layout() plt.show() if most_similar_image_path is None: raise ValueError("No faces detected in the candidate images.") return most_similar_image_path, highest_similarity
Usage
URLs of the images to compare:
image_url_target = 'https://d1mnxluw9mpf9w.cloudfront.net/media/7588/4x3/1200.jpg' candidate_image_urls = [ 'https://beyondthesinglestory.wordpress.com/wp-content/uploads/2021/04/elon_musk_royal_society_crop1.jpg', 'https://cdn.britannica.com/56/199056-050-CCC44482/Jeff-Bezos-2017.jpg', 'https://cdn.britannica.com/45/188745-050-7B822E21/Richard-Branson-2003.jpg' ] most_similar_image, similarity_score = find_most_similar(image_url_target, candidate_image_urls) print(f"The most similar image is: {most_similar_image}") print(f"Similarity score: {similarity_score * 100:.2f}%")
Result
Conclusion
This example demonstrates the power of facenet-pytorch
for facial recognition tasks. By combining face detection and embedding, we can create tools for various applications, such as identity verification, or content filtering.
Top comments (0)