2025-04-10 23:51:53 +09:00
|
|
|
import cv2
|
|
|
|
|
import argparse
|
|
|
|
|
import numpy as np
|
|
|
|
|
|
ref: Add comprehensive test suite and enhance model functionality
- Add new test files for age_gender, factory, landmark, recognition, scrfd, and utils
- Add new scripts for age_gender, landmarks, and video detection
- Update documentation in README.md, MODELS.md, QUICKSTART.md
- Improve model constants and face utilities
- Update detection models (retinaface, scrfd) with enhanced functionality
- Update project configuration in pyproject.toml
2025-11-15 21:09:37 +09:00
|
|
|
from uniface.detection import RetinaFace, SCRFD
|
|
|
|
|
from uniface.recognition import ArcFace, MobileFace, SphereFace
|
|
|
|
|
from uniface.face_utils import compute_similarity
|
2025-04-10 23:51:53 +09:00
|
|
|
|
2025-07-02 18:52:28 +09:00
|
|
|
|
|
|
|
|
def run_inference(detector, recognizer, image_path: str):
|
2025-04-10 23:51:53 +09:00
|
|
|
image = cv2.imread(image_path)
|
|
|
|
|
if image is None:
|
|
|
|
|
print(f"Error: Failed to load image from '{image_path}'")
|
|
|
|
|
return
|
|
|
|
|
|
2025-07-02 18:52:28 +09:00
|
|
|
faces = detector.detect(image)
|
2025-04-10 23:51:53 +09:00
|
|
|
|
2025-07-02 18:52:28 +09:00
|
|
|
if not faces:
|
2025-04-10 23:51:53 +09:00
|
|
|
print("No faces detected.")
|
|
|
|
|
return
|
|
|
|
|
|
2025-07-02 18:52:28 +09:00
|
|
|
print(f"Detected {len(faces)} face(s). Extracting embeddings for the first face...")
|
|
|
|
|
|
|
|
|
|
# Process the first detected face
|
|
|
|
|
first_face = faces[0]
|
|
|
|
|
landmarks = np.array(first_face['landmarks']) # Convert landmarks to numpy array
|
2025-04-10 23:51:53 +09:00
|
|
|
|
2025-07-02 18:52:28 +09:00
|
|
|
# Extract embedding using the landmarks from the face dictionary
|
|
|
|
|
embedding = recognizer.get_embedding(image, landmarks)
|
|
|
|
|
norm_embedding = recognizer.get_normalized_embedding(image, landmarks)
|
|
|
|
|
|
|
|
|
|
# Print some info about the embeddings
|
|
|
|
|
print(f" - Embedding shape: {embedding.shape}")
|
|
|
|
|
print(f" - L2 norm of unnormalized embedding: {np.linalg.norm(embedding):.4f}")
|
|
|
|
|
print(f" - L2 norm of normalized embedding: {np.linalg.norm(norm_embedding):.4f}")
|
2025-04-10 23:51:53 +09:00
|
|
|
|
|
|
|
|
|
ref: Add comprehensive test suite and enhance model functionality
- Add new test files for age_gender, factory, landmark, recognition, scrfd, and utils
- Add new scripts for age_gender, landmarks, and video detection
- Update documentation in README.md, MODELS.md, QUICKSTART.md
- Improve model constants and face utilities
- Update detection models (retinaface, scrfd) with enhanced functionality
- Update project configuration in pyproject.toml
2025-11-15 21:09:37 +09:00
|
|
|
def compare_faces(detector, recognizer, image1_path: str, image2_path: str, threshold: float = 0.35):
|
|
|
|
|
|
|
|
|
|
# Load images
|
|
|
|
|
img1 = cv2.imread(image1_path)
|
|
|
|
|
img2 = cv2.imread(image2_path)
|
|
|
|
|
|
|
|
|
|
if img1 is None or img2 is None:
|
|
|
|
|
print(f"Error: Failed to load images")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# Detect faces
|
|
|
|
|
faces1 = detector.detect(img1)
|
|
|
|
|
faces2 = detector.detect(img2)
|
|
|
|
|
|
|
|
|
|
if not faces1 or not faces2:
|
|
|
|
|
print("Error: No faces detected in one or both images")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# Get landmarks for first face in each image
|
|
|
|
|
landmarks1 = np.array(faces1[0]['landmarks'])
|
|
|
|
|
landmarks2 = np.array(faces2[0]['landmarks'])
|
|
|
|
|
|
|
|
|
|
# Get normalized embeddings
|
|
|
|
|
embedding1 = recognizer.get_normalized_embedding(img1, landmarks1)
|
|
|
|
|
embedding2 = recognizer.get_normalized_embedding(img2, landmarks2)
|
|
|
|
|
|
|
|
|
|
# Compute similarity
|
|
|
|
|
similarity = compute_similarity(embedding1, embedding2, normalized=True)
|
|
|
|
|
is_match = similarity > threshold
|
|
|
|
|
|
|
|
|
|
print(f"Similarity: {similarity:.4f}")
|
|
|
|
|
print(f"Result: {'Same person' if is_match else 'Different person'}")
|
|
|
|
|
print(f"Threshold: {threshold}")
|
|
|
|
|
|
|
|
|
|
|
2025-04-10 23:51:53 +09:00
|
|
|
def main():
|
ref: Add comprehensive test suite and enhance model functionality
- Add new test files for age_gender, factory, landmark, recognition, scrfd, and utils
- Add new scripts for age_gender, landmarks, and video detection
- Update documentation in README.md, MODELS.md, QUICKSTART.md
- Improve model constants and face utilities
- Update detection models (retinaface, scrfd) with enhanced functionality
- Update project configuration in pyproject.toml
2025-11-15 21:09:37 +09:00
|
|
|
parser = argparse.ArgumentParser(description="Face recognition and comparison.")
|
|
|
|
|
parser.add_argument("--image", type=str, help="Path to single image for embedding extraction.")
|
|
|
|
|
parser.add_argument("--image1", type=str, help="Path to first image for comparison.")
|
|
|
|
|
parser.add_argument("--image2", type=str, help="Path to second image for comparison.")
|
|
|
|
|
parser.add_argument("--threshold", type=float, default=0.35, help="Similarity threshold for face matching.")
|
2025-04-10 23:51:53 +09:00
|
|
|
parser.add_argument(
|
2025-07-02 18:52:28 +09:00
|
|
|
"--detector",
|
2025-04-10 23:51:53 +09:00
|
|
|
type=str,
|
2025-07-02 18:52:28 +09:00
|
|
|
default="retinaface",
|
|
|
|
|
choices=['retinaface', 'scrfd'],
|
|
|
|
|
help="Face detection method to use."
|
|
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"--recognizer",
|
|
|
|
|
type=str,
|
|
|
|
|
default="arcface",
|
|
|
|
|
choices=['arcface', 'mobileface', 'sphereface'],
|
|
|
|
|
help="Face recognition method to use."
|
2025-04-10 23:51:53 +09:00
|
|
|
)
|
2025-11-08 01:15:25 +09:00
|
|
|
parser.add_argument("--verbose", action="store_true", help="Enable verbose logging")
|
2025-04-10 23:51:53 +09:00
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
2025-11-08 01:15:25 +09:00
|
|
|
if args.verbose:
|
|
|
|
|
from uniface import enable_logging
|
|
|
|
|
enable_logging()
|
|
|
|
|
|
2025-07-02 18:52:28 +09:00
|
|
|
print(f"Initializing detector: {args.detector}")
|
ref: Add comprehensive test suite and enhance model functionality
- Add new test files for age_gender, factory, landmark, recognition, scrfd, and utils
- Add new scripts for age_gender, landmarks, and video detection
- Update documentation in README.md, MODELS.md, QUICKSTART.md
- Improve model constants and face utilities
- Update detection models (retinaface, scrfd) with enhanced functionality
- Update project configuration in pyproject.toml
2025-11-15 21:09:37 +09:00
|
|
|
if args.detector == 'retinaface':
|
|
|
|
|
detector = RetinaFace()
|
|
|
|
|
else:
|
|
|
|
|
detector = SCRFD()
|
2025-07-02 18:52:28 +09:00
|
|
|
|
|
|
|
|
print(f"Initializing recognizer: {args.recognizer}")
|
ref: Add comprehensive test suite and enhance model functionality
- Add new test files for age_gender, factory, landmark, recognition, scrfd, and utils
- Add new scripts for age_gender, landmarks, and video detection
- Update documentation in README.md, MODELS.md, QUICKSTART.md
- Improve model constants and face utilities
- Update detection models (retinaface, scrfd) with enhanced functionality
- Update project configuration in pyproject.toml
2025-11-15 21:09:37 +09:00
|
|
|
if args.recognizer == 'arcface':
|
|
|
|
|
recognizer = ArcFace()
|
|
|
|
|
elif args.recognizer == 'mobileface':
|
|
|
|
|
recognizer = MobileFace()
|
|
|
|
|
else:
|
|
|
|
|
recognizer = SphereFace()
|
|
|
|
|
|
|
|
|
|
if args.image1 and args.image2:
|
|
|
|
|
# Face comparison mode
|
|
|
|
|
print(f"Comparing faces: {args.image1} vs {args.image2}")
|
|
|
|
|
compare_faces(detector, recognizer, args.image1, args.image2, args.threshold)
|
|
|
|
|
elif args.image:
|
|
|
|
|
# Single image embedding extraction mode
|
|
|
|
|
run_inference(detector, recognizer, args.image)
|
|
|
|
|
else:
|
|
|
|
|
print("Error: Provide either --image for single image processing or --image1 and --image2 for comparison")
|
|
|
|
|
parser.print_help()
|
2025-04-10 23:51:53 +09:00
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
main()
|