diff --git a/bob/bio/face/__init__.py b/bob/bio/face/__init__.py index 4f3858c5fbc180e24a8368de4c55b4e90e73e3c1..9bda18df60dfb0eb66ae95f6292e682150a0e17f 100644 --- a/bob/bio/face/__init__.py +++ b/bob/bio/face/__init__.py @@ -4,6 +4,7 @@ from . import algorithm from . import script from . import database from . import annotator +from . import utils from . import test diff --git a/bob/bio/face/config/baseline/arcface_insightface.py b/bob/bio/face/config/baseline/arcface_insightface.py index dfe1d04334da97d94710ec32c2745059a9816439..3e0181219dbf40d17e32d36d85a909a102b87fd1 100644 --- a/bob/bio/face/config/baseline/arcface_insightface.py +++ b/bob/bio/face/config/baseline/arcface_insightface.py @@ -1,5 +1,5 @@ from bob.bio.face.embeddings.mxnet_models import ArcFaceInsightFace -from bob.bio.face.config.baseline.helpers import lookup_config_from_database +from bob.bio.face.utils import lookup_config_from_database from bob.bio.face.config.baseline.templates import arcface_baseline annotation_type, fixed_positions, memory_demanding = lookup_config_from_database( diff --git a/bob/bio/face/config/baseline/dummy.py b/bob/bio/face/config/baseline/dummy.py index eaa993d3917315b1e1bfb4e83290c07e2d858202..9c407c8ed84a8d4374ce557e5492c2956c1fac54 100644 --- a/bob/bio/face/config/baseline/dummy.py +++ b/bob/bio/face/config/baseline/dummy.py @@ -5,7 +5,7 @@ from bob.bio.base.pipelines.vanilla_biometrics import ( VanillaBiometricsPipeline, ) from bob.pipelines.transformers import SampleLinearize -from bob.bio.face.config.baseline.helpers import lookup_config_from_database +from bob.bio.face.utils import lookup_config_from_database annotation_type, fixed_positions, memory_demanding = lookup_config_from_database() diff --git a/bob/bio/face/config/baseline/facenet_sanderberg.py b/bob/bio/face/config/baseline/facenet_sanderberg.py index 73c3d687239f972e10316eb256598eb2dd15ab8a..510d9287fba4613f072482f0f57026d8fec824ba 100644 --- a/bob/bio/face/config/baseline/facenet_sanderberg.py +++ b/bob/bio/face/config/baseline/facenet_sanderberg.py @@ -1,7 +1,7 @@ from bob.bio.face.embeddings.tf2_inception_resnet import ( FaceNetSanderberg_20170512_110547, ) -from bob.bio.face.config.baseline.helpers import lookup_config_from_database +from bob.bio.face.utils import lookup_config_from_database from bob.bio.face.config.baseline.templates import facenet_baseline annotation_type, fixed_positions, memory_demanding = lookup_config_from_database( diff --git a/bob/bio/face/config/baseline/gabor_graph.py b/bob/bio/face/config/baseline/gabor_graph.py index 2a6925a2628966dbe5fcc98781b5da8ceedd4f19..b21d10ae7ad10e677af7a9d9e9d3d9d18cbb15f8 100644 --- a/bob/bio/face/config/baseline/gabor_graph.py +++ b/bob/bio/face/config/baseline/gabor_graph.py @@ -3,7 +3,7 @@ from bob.bio.base.pipelines.vanilla_biometrics import ( VanillaBiometricsPipeline, BioAlgorithmLegacy, ) -from bob.bio.face.config.baseline.helpers import ( +from bob.bio.face.utils import ( lookup_config_from_database, legacy_default_cropping, make_cropper, diff --git a/bob/bio/face/config/baseline/inception_resnetv1_casiawebface.py b/bob/bio/face/config/baseline/inception_resnetv1_casiawebface.py index b3301dcdba87ed21ac8e8c571f28c97ce18cc6dc..149c074270a1001513dfbeacb0cbf09325784b28 100644 --- a/bob/bio/face/config/baseline/inception_resnetv1_casiawebface.py +++ b/bob/bio/face/config/baseline/inception_resnetv1_casiawebface.py @@ -1,7 +1,7 @@ from bob.bio.face.embeddings.tf2_inception_resnet import ( InceptionResnetv1_Casia_CenterLoss_2018, ) -from bob.bio.face.config.baseline.helpers import lookup_config_from_database +from bob.bio.face.utils import lookup_config_from_database from bob.bio.face.config.baseline.templates import facenet_baseline annotation_type, fixed_positions, memory_demanding = lookup_config_from_database( diff --git a/bob/bio/face/config/baseline/inception_resnetv1_msceleb.py b/bob/bio/face/config/baseline/inception_resnetv1_msceleb.py index 745b7bbdce2cfe9b0d361b0cf3bb239c682ac898..f7ce09f7d1d2bd57eee0490b269c0b5a857c1a8d 100644 --- a/bob/bio/face/config/baseline/inception_resnetv1_msceleb.py +++ b/bob/bio/face/config/baseline/inception_resnetv1_msceleb.py @@ -1,7 +1,7 @@ from bob.bio.face.embeddings.tf2_inception_resnet import ( InceptionResnetv1_MsCeleb_CenterLoss_2018, ) -from bob.bio.face.config.baseline.helpers import lookup_config_from_database +from bob.bio.face.utils import lookup_config_from_database from bob.bio.face.config.baseline.templates import facenet_baseline diff --git a/bob/bio/face/config/baseline/inception_resnetv2_casiawebface.py b/bob/bio/face/config/baseline/inception_resnetv2_casiawebface.py index b1b066acf20519d34b98f6712cea9c4c6da1207f..eadd91541b85511f31e48ad97140ba6bc5dc5d61 100644 --- a/bob/bio/face/config/baseline/inception_resnetv2_casiawebface.py +++ b/bob/bio/face/config/baseline/inception_resnetv2_casiawebface.py @@ -1,7 +1,7 @@ from bob.bio.face.embeddings.tf2_inception_resnet import ( InceptionResnetv2_Casia_CenterLoss_2018, ) -from bob.bio.face.config.baseline.helpers import lookup_config_from_database +from bob.bio.face.utils import lookup_config_from_database from bob.bio.face.config.baseline.templates import facenet_baseline diff --git a/bob/bio/face/config/baseline/inception_resnetv2_msceleb.py b/bob/bio/face/config/baseline/inception_resnetv2_msceleb.py index f3e083b7599884d7a44f60cfbf5835570fe912e0..0be122d36c854becb94ef192ecc79d5134682975 100644 --- a/bob/bio/face/config/baseline/inception_resnetv2_msceleb.py +++ b/bob/bio/face/config/baseline/inception_resnetv2_msceleb.py @@ -1,7 +1,7 @@ from bob.bio.face.embeddings.tf2_inception_resnet import ( InceptionResnetv2_MsCeleb_CenterLoss_2018, ) -from bob.bio.face.config.baseline.helpers import lookup_config_from_database +from bob.bio.face.utils import lookup_config_from_database from bob.bio.face.config.baseline.templates import facenet_baseline annotation_type, fixed_positions, memory_demanding = lookup_config_from_database( diff --git a/bob/bio/face/config/baseline/lda.py b/bob/bio/face/config/baseline/lda.py index e78eb76b79a52650b4c489fc3e3059627107d210..de1935cb45c947e8720f1ae385dc5c42e80bb033 100644 --- a/bob/bio/face/config/baseline/lda.py +++ b/bob/bio/face/config/baseline/lda.py @@ -3,7 +3,7 @@ from bob.bio.base.pipelines.vanilla_biometrics import ( VanillaBiometricsPipeline, BioAlgorithmLegacy, ) -from bob.bio.face.config.baseline.helpers import ( +from bob.bio.face.utils import ( lookup_config_from_database, legacy_default_cropping, make_cropper, diff --git a/bob/bio/face/config/baseline/lgbphs.py b/bob/bio/face/config/baseline/lgbphs.py index 7b484a7f7f929175053b24c6e1e69c672f93be08..b70b638abd2fc9058f1c7d5ee3c38bb8cf7d0ca8 100644 --- a/bob/bio/face/config/baseline/lgbphs.py +++ b/bob/bio/face/config/baseline/lgbphs.py @@ -3,7 +3,7 @@ from bob.bio.base.pipelines.vanilla_biometrics import ( VanillaBiometricsPipeline, BioAlgorithmLegacy, ) -from bob.bio.face.config.baseline.helpers import ( +from bob.bio.face.utils import ( lookup_config_from_database, legacy_default_cropping, make_cropper, diff --git a/bob/bio/face/config/baseline/mobilenetv2_msceleb_arcface_2021.py b/bob/bio/face/config/baseline/mobilenetv2_msceleb_arcface_2021.py index 041484070595f1a32f231fe570b6c62e3df780c1..2355494888b81e8d8f7e8e49dc4ba8a3ba43daea 100644 --- a/bob/bio/face/config/baseline/mobilenetv2_msceleb_arcface_2021.py +++ b/bob/bio/face/config/baseline/mobilenetv2_msceleb_arcface_2021.py @@ -1,5 +1,5 @@ from bob.bio.face.embeddings.mobilenet_v2 import MobileNetv2_MsCeleb_ArcFace_2021 -from bob.bio.face.config.baseline.helpers import lookup_config_from_database +from bob.bio.face.utils import lookup_config_from_database from bob.bio.face.config.baseline.templates import arcface_baseline diff --git a/bob/bio/face/config/baseline/resnet50_msceleb_arcface_2021.py b/bob/bio/face/config/baseline/resnet50_msceleb_arcface_2021.py index b67e65e5df8dd76b1af067597407d4190d45a5bb..0560a97a62f42d33f5d8c54c3177760db61ab9fc 100644 --- a/bob/bio/face/config/baseline/resnet50_msceleb_arcface_2021.py +++ b/bob/bio/face/config/baseline/resnet50_msceleb_arcface_2021.py @@ -1,5 +1,5 @@ from bob.bio.face.embeddings.resnet50 import Resnet50_MsCeleb_ArcFace_2021 -from bob.bio.face.config.baseline.helpers import lookup_config_from_database +from bob.bio.face.utils import lookup_config_from_database from bob.bio.face.config.baseline.templates import arcface_baseline diff --git a/bob/bio/face/config/baseline/resnet50_vgg2_arcface_2021.py b/bob/bio/face/config/baseline/resnet50_vgg2_arcface_2021.py index 1237cfefa9c6f55eaf538e9b294da6b99fb6e91a..64d6ec4c84fbb43c1ef3061c070c6a568e7d74d6 100644 --- a/bob/bio/face/config/baseline/resnet50_vgg2_arcface_2021.py +++ b/bob/bio/face/config/baseline/resnet50_vgg2_arcface_2021.py @@ -1,5 +1,5 @@ from bob.bio.face.embeddings.resnet50 import Resnet50_VGG2_ArcFace_2021 -from bob.bio.face.config.baseline.helpers import lookup_config_from_database +from bob.bio.face.utils import lookup_config_from_database from bob.bio.face.config.baseline.templates import arcface_baseline diff --git a/bob/bio/face/config/baseline/templates.py b/bob/bio/face/config/baseline/templates.py index ed8b10e3b8f9a6946d726c160586a2e9d6636e9f..415ecd2831432dfb96b94ff4eae814409cdc2088 100644 --- a/bob/bio/face/config/baseline/templates.py +++ b/bob/bio/face/config/baseline/templates.py @@ -1,4 +1,4 @@ -from bob.bio.face.config.baseline.helpers import ( +from bob.bio.face.utils import ( dnn_default_cropping, embedding_transformer, ) diff --git a/bob/bio/face/config/baseline/tf2_inception_resnet.py b/bob/bio/face/config/baseline/tf2_inception_resnet.py index 54b408bb62765bad8227c8e4934409595d59eefa..38d78c53de52cac64e1e668f98c72635789adf99 100644 --- a/bob/bio/face/config/baseline/tf2_inception_resnet.py +++ b/bob/bio/face/config/baseline/tf2_inception_resnet.py @@ -1,6 +1,6 @@ from bob.extension import rc from bob.bio.face.embeddings.tf2_inception_resnet import InceptionResnetv2 -from bob.bio.face.config.baseline.helpers import lookup_config_from_database +from bob.bio.face.utils import lookup_config_from_database from bob.bio.face.config.baseline.templates import facenet_baseline annotation_type, fixed_positions, memory_demanding = lookup_config_from_database( diff --git a/bob/bio/face/helpers.py b/bob/bio/face/helpers.py deleted file mode 100644 index 9a3a2c97e2001934da770132587c8777f1330caa..0000000000000000000000000000000000000000 --- a/bob/bio/face/helpers.py +++ /dev/null @@ -1,72 +0,0 @@ -from bob.bio.face.preprocessor import FaceCrop, MultiFaceCrop, Scale -import bob.bio.face.config.baseline.helpers as helpers - -def face_crop_solver( - cropped_image_size, - cropped_positions=None, - color_channel="rgb", - fixed_positions=None, - annotator=None, - dtype="uint8", -): - """ - Decide which face cropper to use. - """ - # If there's not cropped positions, just resize - if cropped_positions is None: - return Scale(cropped_image_size) - else: - # Detects the face and crops it without eye detection - if isinstance(cropped_positions, list): - return MultiFaceCrop( - cropped_image_size=cropped_image_size, - cropped_positions_list=cropped_positions, - fixed_positions_list=fixed_positions, - color_channel=color_channel, - dtype=dtype, - annotator=annotator, - ) - else: - return FaceCrop( - cropped_image_size=cropped_image_size, - cropped_positions=cropped_positions, - color_channel=color_channel, - fixed_positions=fixed_positions, - dtype=dtype, - annotator=annotator, - ) - - -def get_default_cropped_positions(mode, cropped_image_size, annotation_type): - """ - Computes the default cropped positions for the FaceCropper, - proportionally to the target image size - - - Parameters - ---------- - mode: str - Which default cropping to use. Available modes are : `legacy` (legacy baselines), `facenet`, `arcface`, - and `pad`. - - cropped_image_size : tuple - A tuple (HEIGHT, WIDTH) describing the target size of the cropped image. - - annotation_type: str - Type of annotations. Possible values are: `bounding-box`, `eyes-center` and None, or a combination of those as a list - - Returns - ------- - - cropped_positions: - The dictionary of cropped positions that will be feeded to the FaceCropper, or a list of such dictionaries if - ``annotation_type`` is a list - """ - if mode == "legacy": - return helpers.legacy_default_cropping(cropped_image_size, annotation_type) - elif mode in ["dnn", "facenet", "arcface"]: - return helpers.dnn_default_cropping(cropped_image_size, annotation_type) - elif mode == "pad": - return helpers.pad_default_cropping(cropped_image_size, annotation_type) - else: - raise ValueError("Unknown default cropping mode `{}`".format(mode)) diff --git a/bob/bio/face/config/baseline/helpers.py b/bob/bio/face/utils.py similarity index 78% rename from bob/bio/face/config/baseline/helpers.py rename to bob/bio/face/utils.py index 5a8cc9440dd45875b5bc5e275365a493ee7af075..988314f0e2e477111f762872c896368c8d5a09ce 100644 --- a/bob/bio/face/config/baseline/helpers.py +++ b/bob/bio/face/utils.py @@ -1,9 +1,11 @@ -from sklearn.pipeline import make_pipeline -from bob.pipelines import wrap -from bob.bio.face import helpers -import numpy as np import logging +from .preprocessor import FaceCrop +from .preprocessor import MultiFaceCrop +from .preprocessor import Scale +from bob.pipelines import wrap +from sklearn.pipeline import make_pipeline + logger = logging.getLogger(__name__) @@ -237,7 +239,7 @@ def make_cropper( transform_extra_arguments for wrapping the cropper with a SampleWrapper. """ - face_cropper = helpers.face_crop_solver( + face_cropper = face_crop_solver( cropped_image_size=cropped_image_size, cropped_positions=cropped_positions, fixed_positions=fixed_positions, @@ -289,3 +291,74 @@ def embedding_transformer( ) return transformer + + +def face_crop_solver( + cropped_image_size, + cropped_positions=None, + color_channel="rgb", + fixed_positions=None, + annotator=None, + dtype="uint8", +): + """ + Decide which face cropper to use. + """ + # If there's not cropped positions, just resize + if cropped_positions is None: + return Scale(cropped_image_size) + else: + # Detects the face and crops it without eye detection + if isinstance(cropped_positions, list): + return MultiFaceCrop( + cropped_image_size=cropped_image_size, + cropped_positions_list=cropped_positions, + fixed_positions_list=fixed_positions, + color_channel=color_channel, + dtype=dtype, + annotator=annotator, + ) + else: + return FaceCrop( + cropped_image_size=cropped_image_size, + cropped_positions=cropped_positions, + color_channel=color_channel, + fixed_positions=fixed_positions, + dtype=dtype, + annotator=annotator, + ) + + +def get_default_cropped_positions(mode, cropped_image_size, annotation_type): + """ + Computes the default cropped positions for the FaceCropper, + proportionally to the target image size + + + Parameters + ---------- + mode: str + Which default cropping to use. Available modes are : `legacy` (legacy baselines), `facenet`, `arcface`, + and `pad`. + + cropped_image_size : tuple + A tuple (HEIGHT, WIDTH) describing the target size of the cropped image. + + annotation_type: str + Type of annotations. Possible values are: `bounding-box`, `eyes-center` and None, or a combination of those as a list + + Returns + ------- + + cropped_positions: + The dictionary of cropped positions that will be feeded to the FaceCropper, or a list of such dictionaries if + ``annotation_type`` is a list + """ + if mode == "legacy": + return legacy_default_cropping(cropped_image_size, annotation_type) + elif mode in ["dnn", "facenet", "arcface"]: + return dnn_default_cropping(cropped_image_size, annotation_type) + elif mode == "pad": + return pad_default_cropping(cropped_image_size, annotation_type) + else: + raise ValueError("Unknown default cropping mode `{}`".format(mode)) diff --git a/doc/faq.rst b/doc/faq.rst index cf281bd6074c813f76a2333aecf41479458013f4..e52795bfa90aada769beeb1b7bdc6408a69191da 100644 --- a/doc/faq.rst +++ b/doc/faq.rst @@ -22,7 +22,7 @@ Some face embedding extractors work well on loosely cropped faces, while others We provide a few reasonable defaults that are used in our implemented baselines. They are accessible through a function as follows : :: - from bob.bio.face.helpers import get_default_cropped_positions + from bob.bio.face.utils import get_default_cropped_positions mode = 'legacy' cropped_image_size=(160, 160) annotation_type='eyes-center' @@ -31,7 +31,7 @@ We provide a few reasonable defaults that are used in our implemented baselines. There are currently three available modes : -* :code:`legacy` Tight crop, used in non neural-net baselines such as :code:`gabor-graph`, :code:`lgbphs` or :code:`lda`. +* :code:`legacy` Tight crop, used in non neural-net baselines such as :code:`gabor-graph`, :code:`lgbphs` or :code:`lda`. It is typically use with a 5:4 aspect ratio for the :code:`cropped_image_size` * :code:`dnn` Loose crop, used for neural-net baselines such as the ArcFace or FaceNet models. * :code:`pad` Tight crop used in some PAD baselines @@ -40,4 +40,3 @@ We present hereafter a visual example of those crops for the `eyes-center` annot .. plot:: plot/default_crops.py :include-source: True - \ No newline at end of file diff --git a/doc/plot/default_crops.py b/doc/plot/default_crops.py index 2507cd4fa71f6c5abe128b0d385a535914a5728a..c1b9ac6bd8c668199c56d7c63acdbcf9dada24c7 100644 --- a/doc/plot/default_crops.py +++ b/doc/plot/default_crops.py @@ -1,5 +1,5 @@ import bob.io.image -from bob.bio.face.helpers import get_default_cropped_positions +from bob.bio.face.utils import get_default_cropped_positions from bob.bio.face.preprocessor import FaceCrop import matplotlib.pyplot as plt