From 4fbd33a419a5738b493247e4feccf3cfc1735f99 Mon Sep 17 00:00:00 2001 From: dakotah-jones <104460663+dakotah-jones@users.noreply.github.com> Date: Wed, 15 Jan 2025 13:15:00 -0500 Subject: [PATCH 1/6] Update representation.py Add explicit "color_face" argument. --- deepface/modules/representation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/deepface/modules/representation.py b/deepface/modules/representation.py index d880645..c7af0ed 100644 --- a/deepface/modules/representation.py +++ b/deepface/modules/representation.py @@ -83,6 +83,7 @@ def represent( expand_percentage=expand_percentage, anti_spoofing=anti_spoofing, max_faces=max_faces, + color_face="bgr", ) else: # skip # Try load. If load error, will raise exception internal From 830decb4831fbb3803959281ba623e285ed41c19 Mon Sep 17 00:00:00 2001 From: dakotah-jones Date: Wed, 15 Jan 2025 16:40:10 -0500 Subject: [PATCH 2/6] Revert change to default case. --- deepface/modules/representation.py | 1 - 1 file changed, 1 deletion(-) diff --git a/deepface/modules/representation.py b/deepface/modules/representation.py index c7af0ed..d880645 100644 --- a/deepface/modules/representation.py +++ b/deepface/modules/representation.py @@ -83,7 +83,6 @@ def represent( expand_percentage=expand_percentage, anti_spoofing=anti_spoofing, max_faces=max_faces, - color_face="bgr", ) else: # skip # Try load. If load error, will raise exception internal From 1ea31bc0726de1ce0e171eff906ddf3a6bda390c Mon Sep 17 00:00:00 2001 From: dakotah-jones Date: Wed, 15 Jan 2025 16:41:40 -0500 Subject: [PATCH 3/6] Update skip case. --- deepface/modules/representation.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/deepface/modules/representation.py b/deepface/modules/representation.py index d880645..d5783eb 100644 --- a/deepface/modules/representation.py +++ b/deepface/modules/representation.py @@ -87,7 +87,10 @@ def represent( else: # skip # Try load. If load error, will raise exception internal img, _ = image_utils.load_image(img_path) - + + # bgr to rgb + img = img[:, :, ::-1] + if len(img.shape) != 3: raise ValueError(f"Input img must be 3 dimensional but it is {img.shape}") From bc92d5a15a2902f782a2e25f37b304ce6a071bfa Mon Sep 17 00:00:00 2001 From: dakotah-jones Date: Wed, 15 Jan 2025 16:43:18 -0500 Subject: [PATCH 4/6] Revert change to comment. (#1402) --- deepface/modules/representation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deepface/modules/representation.py b/deepface/modules/representation.py index d5783eb..3848039 100644 --- a/deepface/modules/representation.py +++ b/deepface/modules/representation.py @@ -119,7 +119,7 @@ def represent( raise ValueError("Spoof detected in the given image.") img = img_obj["face"] - # bgr to rgb + # rgb to bgr img = img[:, :, ::-1] region = img_obj["facial_area"] From 5d4146b248b90f60b1ccd966d3805e04d981d980 Mon Sep 17 00:00:00 2001 From: dakotah-jones Date: Tue, 28 Jan 2025 10:41:16 -0500 Subject: [PATCH 5/6] Add test. Add comments. Update color format for `__find_bulk_embeddings`. --- deepface/modules/recognition.py | 1 + deepface/modules/representation.py | 9 +++++---- tests/test_represent.py | 20 ++++++++++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/deepface/modules/recognition.py b/deepface/modules/recognition.py index 90e8c29..4002b47 100644 --- a/deepface/modules/recognition.py +++ b/deepface/modules/recognition.py @@ -398,6 +398,7 @@ def __find_bulk_embeddings( enforce_detection=enforce_detection, align=align, expand_percentage=expand_percentage, + color_face='bgr' # `represent` expects images in bgr format. ) except ValueError as err: diff --git a/deepface/modules/representation.py b/deepface/modules/representation.py index 3848039..d0c4fc3 100644 --- a/deepface/modules/representation.py +++ b/deepface/modules/representation.py @@ -74,6 +74,7 @@ def represent( # we have run pre-process in verification. so, this can be skipped if it is coming from verify. target_size = model.input_shape if detector_backend != "skip": + # Images are returned in RGB format. img_objs = detection.extract_faces( img_path=img_path, detector_backend=detector_backend, @@ -87,13 +88,13 @@ def represent( else: # skip # Try load. If load error, will raise exception internal img, _ = image_utils.load_image(img_path) - - # bgr to rgb - img = img[:, :, ::-1] - + if len(img.shape) != 3: raise ValueError(f"Input img must be 3 dimensional but it is {img.shape}") + # Convert to RGB format to keep compatability with `extract_faces`. + img = img[:, :, ::-1] + # make dummy region and confidence to keep compatibility with `extract_faces` img_objs = [ { diff --git a/tests/test_represent.py b/tests/test_represent.py index b33def7..8ad3724 100644 --- a/tests/test_represent.py +++ b/tests/test_represent.py @@ -81,3 +81,23 @@ def test_max_faces(): 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 From a05c2ea813a07b4da0447c9f46be670217a781b0 Mon Sep 17 00:00:00 2001 From: dakotah-jones Date: Tue, 28 Jan 2025 11:01:20 -0500 Subject: [PATCH 6/6] Add logging to test case. --- tests/test_represent.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/test_represent.py b/tests/test_represent.py index 8ad3724..e3c52b8 100644 --- a/tests/test_represent.py +++ b/tests/test_represent.py @@ -84,6 +84,12 @@ def test_max_faces(): def test_represent_detector_backend(): + """ + There shouldn't be a difference between: + - Using a detector backend provided by `represent` + - Manually calling a detector backend, then calling `represent`. + """ + # Results using a detection backend. results_1 = DeepFace.represent(img_path="dataset/img1.jpg") assert len(results_1) == 1 @@ -101,3 +107,4 @@ def test_represent_detector_backend(): 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.")