# built-in dependencies import io import cv2 import pytest import numpy as np import pytest # project dependencies from deepface import DeepFace from deepface.commons.logger import Logger logger = Logger() def test_standard_represent(): img_path = "dataset/img1.jpg" embedding_objs = DeepFace.represent(img_path) # type should be list of dict assert isinstance(embedding_objs, list) for embedding_obj in embedding_objs: assert isinstance(embedding_obj, dict) embedding = embedding_obj["embedding"] logger.debug(f"Function returned {len(embedding)} dimensional vector") assert len(embedding) == 4096 logger.info("✅ test standard represent function done") def test_standard_represent_with_io_object(): img_path = "dataset/img1.jpg" default_embedding_objs = DeepFace.represent(img_path) io_embedding_objs = DeepFace.represent(open(img_path, "rb")) assert default_embedding_objs == io_embedding_objs # Confirm non-seekable io objects are handled properly io_obj = io.BytesIO(open(img_path, "rb").read()) io_obj.seek = None no_seek_io_embedding_objs = DeepFace.represent(io_obj) assert default_embedding_objs == no_seek_io_embedding_objs # Confirm non-image io objects raise exceptions with pytest.raises(ValueError, match="Failed to decode image"): DeepFace.represent(io.BytesIO(open(r"../requirements.txt", "rb").read())) logger.info("✅ test standard represent with io object function done") def test_represent_for_skipped_detector_backend_with_image_path(): face_img = "dataset/img5.jpg" img_objs = DeepFace.represent(img_path=face_img, detector_backend="skip") assert len(img_objs) >= 1 img_obj = img_objs[0] assert "embedding" in img_obj.keys() assert "facial_area" in img_obj.keys() assert isinstance(img_obj["facial_area"], dict) assert "x" in img_obj["facial_area"].keys() assert "y" in img_obj["facial_area"].keys() assert "w" in img_obj["facial_area"].keys() assert "h" in img_obj["facial_area"].keys() assert "face_confidence" in img_obj.keys() logger.info("✅ test represent function for skipped detector and image path input backend done") def test_represent_for_preloaded_image(): face_img = "dataset/img5.jpg" img = cv2.imread(face_img) img_objs = DeepFace.represent(img_path=img) # type should be list of dict assert isinstance(img_objs, list) assert len(img_objs) >= 1 for img_obj in img_objs: assert isinstance(img_obj, dict) assert "embedding" in img_obj.keys() assert "facial_area" in img_obj.keys() assert isinstance(img_obj["facial_area"], dict) assert "x" in img_obj["facial_area"].keys() assert "y" in img_obj["facial_area"].keys() assert "w" in img_obj["facial_area"].keys() assert "h" in img_obj["facial_area"].keys() assert "face_confidence" in img_obj.keys() logger.info("✅ test represent function for skipped detector and preloaded image done") def test_represent_for_skipped_detector_backend_with_preloaded_image(): face_img = "dataset/img5.jpg" img = cv2.imread(face_img) img_objs = DeepFace.represent(img_path=img, detector_backend="skip") assert len(img_objs) >= 1 img_obj = img_objs[0] assert "embedding" in img_obj.keys() assert "facial_area" in img_obj.keys() assert isinstance(img_obj["facial_area"], dict) assert "x" in img_obj["facial_area"].keys() assert "y" in img_obj["facial_area"].keys() assert "w" in img_obj["facial_area"].keys() assert "h" in img_obj["facial_area"].keys() assert "face_confidence" in img_obj.keys() logger.info("✅ test represent function for skipped detector and preloaded image done") def test_max_faces(): # confirm that input image has more than one face results = DeepFace.represent(img_path="dataset/couple.jpg") assert len(results) > 1 # test it with max faces arg max_faces = 1 results = DeepFace.represent(img_path="dataset/couple.jpg", max_faces=max_faces) assert len(results) == max_faces def test_represent_detector_backend(): # Results using a detection backend. results_1 = DeepFace.represent(img_path="dataset/img1.jpg") assert len(results_1) == 1 # Results performing face extraction first. faces = DeepFace.extract_faces(img_path="dataset/img1.jpg", color_face='bgr') assert len(faces) == 1 # Images sent into represent need to be in BGR format. img = faces[0]['face'] results_2 = DeepFace.represent(img_path=img, detector_backend="skip") assert len(results_2) == 1 # The embeddings should be the exact same for both cases. embedding_1 = results_1[0]['embedding'] embedding_2 = results_2[0]['embedding'] assert embedding_1 == embedding_2 logger.info("✅ test represent function for consistent output.") @pytest.mark.parametrize( "model_name", [ "VGG-Face", "Facenet", "SFace", ], ) def test_batched_represent_for_list_input(model_name): img_paths = [ "dataset/img1.jpg", "dataset/img2.jpg", "dataset/img3.jpg", "dataset/img4.jpg", "dataset/img5.jpg", "dataset/couple.jpg", ] expected_faces = [1, 1, 1, 1, 1, 2] batched_embedding_objs = DeepFace.represent(img_path=img_paths, model_name=model_name) # type should be list of list of dict for batch input assert isinstance(batched_embedding_objs, list) assert len(batched_embedding_objs) == len( img_paths ), f"Expected {len(img_paths)} embeddings, got {len(batched_embedding_objs)}" # the last one has two faces for idx, embedding_objs in enumerate(batched_embedding_objs): # type should be list of list of dict for batch input # batched_embedding_objs was list already, embedding_objs should be list of dict assert isinstance(embedding_objs, list) for embedding_obj in embedding_objs: assert isinstance(embedding_obj, dict) assert expected_faces[idx] == len( embedding_objs ), f"{img_paths[idx]} has {expected_faces[idx]} faces, but got {len(embedding_objs)} embeddings!" for idx, img_path in enumerate(img_paths): single_embedding_objs = DeepFace.represent(img_path=img_path, model_name=model_name) # type should be list of dict for single input assert isinstance(single_embedding_objs, list) for embedding_obj in single_embedding_objs: assert isinstance(embedding_obj, dict) assert len(single_embedding_objs) == len(batched_embedding_objs[idx]) for alpha, beta in zip(single_embedding_objs, batched_embedding_objs[idx]): assert np.allclose( alpha["embedding"], beta["embedding"], rtol=1e-2, atol=1e-2 ), "Embeddings do not match within tolerance" logger.info(f"✅ test batch represent function with string input for model {model_name} done") @pytest.mark.parametrize( "model_name", [ "VGG-Face", "Facenet", "SFace", ], ) def test_batched_represent_for_numpy_input(model_name): img_paths = [ "dataset/img1.jpg", "dataset/img2.jpg", "dataset/img3.jpg", "dataset/img4.jpg", "dataset/img5.jpg", "dataset/couple.jpg", ] expected_faces = [1, 1, 1, 1, 1, 2] imgs = [] for img_path in img_paths: img = cv2.imread(img_path) img = cv2.resize(img, (1000, 1000)) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # print(img.shape) imgs.append(img) imgs = np.array(imgs) assert imgs.ndim == 4 and imgs.shape[0] == len(img_paths) batched_embedding_objs = DeepFace.represent(img_path=imgs, model_name=model_name) # type should be list of list of dict for batch input assert isinstance(batched_embedding_objs, list) for idx, batched_embedding_obj in enumerate(batched_embedding_objs): assert isinstance(batched_embedding_obj, list) # it also has to have the expected number of faces assert len(batched_embedding_obj) == expected_faces[idx] for embedding_obj in batched_embedding_obj: assert isinstance(embedding_obj, dict) # we should have the same number of embeddings as the number of images assert len(batched_embedding_objs) == len(img_paths) logger.info(f"✅ test batch represent function with numpy input for model {model_name} done")