Skip to content

Face Search

Find and identify people in images and video streams.

UniFace supports two search approaches:

Approach Use case Tool
Reference search "Is this specific person in the video?" tools/search.py
Vector search "Who is this?" against a database of known faces tools/faiss_search.py

Reference Search (single image)

Compare every detected face against a single reference photo:

import cv2
import numpy as np
from uniface.detection import RetinaFace
from uniface.recognition import ArcFace
from uniface.face_utils import compute_similarity

detector = RetinaFace()
recognizer = ArcFace()

ref_image = cv2.imread("reference.jpg")
ref_faces = detector.detect(ref_image)
ref_embedding = recognizer.get_normalized_embedding(ref_image, ref_faces[0].landmarks)

query_image = cv2.imread("group_photo.jpg")
faces = detector.detect(query_image)

for face in faces:
    embedding = recognizer.get_normalized_embedding(query_image, face.landmarks)
    sim = compute_similarity(ref_embedding, embedding)

    label = f"Match ({sim:.2f})" if sim > 0.4 else f"Unknown ({sim:.2f})"
    print(label)

CLI tool:

python tools/search.py --reference ref.jpg --source video.mp4
python tools/search.py --reference ref.jpg --source 0  # webcam

Vector Search (FAISS index)

For identifying faces against a database of many known people, use the FAISS vector store.

Install extra

bash pip install faiss-cpu

Build an index

Organise face images in person sub-folders:

dataset/
├── alice/
│   ├── 001.jpg
│   └── 002.jpg
├── bob/
│   └── 001.jpg
└── charlie/
    ├── 001.jpg
    └── 002.jpg
import cv2
from pathlib import Path
from uniface.detection import RetinaFace
from uniface.recognition import ArcFace
from uniface.indexing import FAISS

detector = RetinaFace()
recognizer = ArcFace()
store = FAISS(db_path="./my_index")

for person_dir in sorted(Path("dataset").iterdir()):
    if not person_dir.is_dir():
        continue
    for img_path in person_dir.glob("*.jpg"):
        image = cv2.imread(str(img_path))
        faces = detector.detect(image)
        if faces:
            emb = recognizer.get_normalized_embedding(image, faces[0].landmarks)
            store.add(emb, {"person_id": person_dir.name, "source": str(img_path)})

store.save()
print(f"Index saved: {store}")

CLI tool:

python tools/faiss_search.py build --faces-dir dataset/ --db-path ./my_index

Search against the index

import cv2
from uniface.detection import RetinaFace
from uniface.recognition import ArcFace
from uniface.indexing import FAISS

detector = RetinaFace()
recognizer = ArcFace()

store = FAISS(db_path="./my_index")
store.load()

image = cv2.imread("query.jpg")
faces = detector.detect(image)

for face in faces:
    embedding = recognizer.get_normalized_embedding(image, face.landmarks)
    result, similarity = store.search(embedding, threshold=0.4)

    if result:
        print(f"Matched: {result['person_id']} ({similarity:.2f})")
    else:
        print(f"Unknown ({similarity:.2f})")

CLI tool:

python tools/faiss_search.py run --db-path ./my_index --source video.mp4
python tools/faiss_search.py run --db-path ./my_index --source 0  # webcam

Manage the index

from uniface.indexing import FAISS

store = FAISS(db_path="./my_index")
store.load()

print(f"Total vectors: {len(store)}")

removed = store.remove("person_id", "bob")
print(f"Removed {removed} entries")

store.save()

See Also