Commit 579aba47 authored by Xinyi ZHANG's avatar Xinyi ZHANG Committed by Tiago de Freitas Pereira
Browse files

2

parent 7c03658e
import bob.ip.facedetect
def bounding_box_to_annotations(bbx):
"""Converts :any:`bob.ip.facedetect.BoundingBox` to dictionary annotations.
......
......@@ -26,10 +26,7 @@ class BobIpTinyface(Base):
Annotations with (topleft, bottomright) keys (or None).
"""
annotations = self.tinyface.detect(image)
if annotations is not None:
r = annotations[0]
return {"topleft": (r[0], r[1]), "bottomright": (r[2], r[3])}
return annotations[0]
else:
return None
from bob.bio.face.annotator import BobIpTinyface
annotator = BobIpTinyface()
annotator = BobIpTinyface()
\ No newline at end of file
import bob.bio.base
from bob.bio.face.preprocessor import FaceCrop
from bob.bio.face.extractor import mxnet_model
from bob.bio.face.extractor import MxNetModel
from bob.bio.base.algorithm import Distance
from bob.bio.base.pipelines.vanilla_biometrics.legacy import BioAlgorithmLegacy
import scipy.spatial
......@@ -39,7 +39,7 @@ transform_extra_arguments = (
)
extractor_transformer = mxnet_model()
extractor_transformer = MxNetModel()
algorithm = Distance(
distance_function=scipy.spatial.distance.cosine, is_distance_function=True
......
......@@ -35,6 +35,15 @@ preprocessor_transformer = FaceCrop(
fixed_positions=fixed_positions,
)
cropped_positions = {"leye": (100, 140), "reye": (100, 95)}
# Preprocessor
preprocessor_transformer = FaceCrop(
cropped_image_size=(224, 224),
cropped_positions={"leye": (100, 140), "reye": (100, 95)},
color_channel="rgb",
fixed_positions=fixed_positions,
)
transform_extra_arguments = (
None
if (cropped_positions is None or fixed_positions is not None)
......
import bob.bio.base
from bob.bio.face.preprocessor import FaceCrop
from bob.bio.face.extractor import pytorch_loaded_model
from bob.bio.face.extractor import PyTorchLoadedModel
from bob.bio.base.algorithm import Distance
from bob.bio.base.pipelines.vanilla_biometrics.legacy import BioAlgorithmLegacy
import scipy.spatial
......@@ -25,9 +25,11 @@ else:
cropped_positions = {"leye": (49, 72), "reye": (49, 38)}
cropped_positions = {"leye": (110, 144), "reye": (110, 96)}
preprocessor_transformer = FaceCrop(
cropped_image_size=(224, 224),
cropped_positions={"leye": (49, 72), "reye": (49, 38)},
cropped_positions={"leye": (110, 144), "reye": (110, 96)},
color_channel="rgb",
fixed_positions=fixed_positions,
)
......@@ -38,8 +40,14 @@ transform_extra_arguments = (
else (("annotations", "annotations"),)
)
transform_extra_arguments = (
None
if (cropped_positions is None or fixed_positions is not None)
else (("annotations", "annotations"),)
)
extractor_transformer = pytorch_loaded_model()
extractor_transformer = PyTorchLoadedModel()
algorithm = Distance(
distance_function=scipy.spatial.distance.cosine, is_distance_function=True
......
import bob.bio.base
from bob.bio.face.preprocessor import FaceCrop
from bob.bio.face.extractor import pytorch_library_model
from bob.bio.face.extractor import PyTorchLibraryModel
from facenet_pytorch import InceptionResnetV1
from bob.bio.base.algorithm import Distance
from bob.bio.base.pipelines.vanilla_biometrics.legacy import BioAlgorithmLegacy
......@@ -26,9 +26,11 @@ else:
cropped_positions = {"leye": (49, 72), "reye": (49, 38)}
cropped_positions = {"leye": (110, 144), "reye": (110, 96)}
preprocessor_transformer = FaceCrop(
cropped_image_size=(224, 224),
cropped_positions={"leye": (49, 72), "reye": (49, 38)},
cropped_positions={"leye": (110, 144), "reye": (110, 96)},
color_channel="rgb",
fixed_positions=fixed_positions,
)
......@@ -40,8 +42,15 @@ transform_extra_arguments = (
)
transform_extra_arguments = (
None
if (cropped_positions is None or fixed_positions is not None)
else (("annotations", "annotations"),)
)
model = InceptionResnetV1(pretrained="vggface2").eval()
extractor_transformer = pytorch_library_model(model=model)
extractor_transformer = PyTorchLibraryModel(model=model)
algorithm = Distance(
......
import bob.bio.base
from bob.bio.face.preprocessor import FaceCrop
from bob.bio.face.extractor import tf_model
from bob.bio.face.extractor import TensorFlowModel
from bob.bio.base.algorithm import Distance
from bob.bio.base.pipelines.vanilla_biometrics.legacy import BioAlgorithmLegacy
import scipy.spatial
......@@ -24,11 +24,11 @@ else:
# Preprocessor
cropped_positions = {"leye": (49, 72), "reye": (49, 38)}
cropped_positions = {"leye": (80, 100), "reye": (80, 60)}
preprocessor_transformer = FaceCrop(
cropped_image_size=(160, 160),
cropped_positions={"leye": (49, 72), "reye": (49, 38)},
cropped_positions={"leye": (80, 100), "reye": (80, 60)},
color_channel="rgb",
fixed_positions=fixed_positions,
)
......@@ -41,7 +41,7 @@ transform_extra_arguments = (
# Extractor
extractor_transformer = tf_model()
extractor_transformer = TensorFlowModel()
# Algorithm
algorithm = Distance(
......
......@@ -12,11 +12,9 @@ import mxnet as mx
from mxnet import gluon
import warnings
from bob.extension import rc
mxnet_resnet_directory = rc["bob.extractor_model.mxnet"]
mxnet_weight_directory = rc["bob.extractor_weights.mxnet"]
class MxNetModel(TransformerMixin, BaseEstimator):
"""Extracts features using deep face recognition models under MxNet Interfaces.
......@@ -59,10 +57,8 @@ class MxNetModel(TransformerMixin, BaseEstimator):
with warnings.catch_warnings():
warnings.simplefilter("ignore")
deserialized_net = gluon.nn.SymbolBlock.imports(
mxnet_resnet_directory, ["data"], mxnet_weight_directory, ctx=ctx
)
deserialized_net = gluon.nn.SymbolBlock.imports(mxnet_resnet_directory, ['data'], mxnet_weight_directory, ctx=ctx)
self.model = deserialized_net
def transform(self, X):
......@@ -80,7 +76,7 @@ class MxNetModel(TransformerMixin, BaseEstimator):
feature : 2D, 3D, or 4D :py:class:`numpy.ndarray` (floats)
The list of features extracted from the image.
"""
if self.model is None:
self._load_model()
......@@ -89,6 +85,7 @@ class MxNetModel(TransformerMixin, BaseEstimator):
return self.model(X,).asnumpy()
def __getstate__(self):
# Handling unpicklable objects
......@@ -97,4 +94,4 @@ class MxNetModel(TransformerMixin, BaseEstimator):
return d
def _more_tags(self):
return {"stateless": True, "requires_fit": False}
return {"stateless": True, "requires_fit": False}
\ No newline at end of file
......@@ -12,10 +12,12 @@ import mxnet as mx
from mxnet import gluon
import warnings
from bob.extension import rc
mxnet_resnet_directory = rc["bob.extractor_model.mxnet"]
mxnet_weight_directory = rc["bob.extractor_weights.mxnet"]
class mxnet_model(TransformerMixin, BaseEstimator):
class MxNetModel(TransformerMixin, BaseEstimator):
"""Extracts features using deep face recognition models under MxNet Interfaces.
......@@ -57,8 +59,10 @@ class mxnet_model(TransformerMixin, BaseEstimator):
with warnings.catch_warnings():
warnings.simplefilter("ignore")
deserialized_net = gluon.nn.SymbolBlock.imports(mxnet_resnet_directory, ['data'], mxnet_weight_directory, ctx=ctx)
deserialized_net = gluon.nn.SymbolBlock.imports(
mxnet_resnet_directory, ["data"], mxnet_weight_directory, ctx=ctx
)
self.model = deserialized_net
def transform(self, X):
......@@ -76,7 +80,7 @@ class mxnet_model(TransformerMixin, BaseEstimator):
feature : 2D, 3D, or 4D :py:class:`numpy.ndarray` (floats)
The list of features extracted from the image.
"""
if self.model is None:
self._load_model()
......@@ -85,7 +89,6 @@ class mxnet_model(TransformerMixin, BaseEstimator):
return self.model(X,).asnumpy()
def __getstate__(self):
# Handling unpicklable objects
......
......@@ -41,6 +41,7 @@ class OpenCVModel(TransformerMixin, BaseEstimator):
This structure only can be used for CAFFE pretrained model.
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.model = None
......@@ -59,7 +60,7 @@ class OpenCVModel(TransformerMixin, BaseEstimator):
def _load_model(self):
net = cv2.dnn.readNetFromCaffe(opencv_model_prototxt, opencv_model_directory)
net = cv2.dnn.readNetFromCaffe(opencv_model_prototxt,opencv_model_directory)
self.model = net
......@@ -78,17 +79,18 @@ class OpenCVModel(TransformerMixin, BaseEstimator):
feature : 2D or 3D :py:class:`numpy.ndarray` (floats)
The list of features extracted from the image.
"""
if self.model is None:
self._load_model()
img = np.array(X)
img = img / 255
img = img/255
self.model.setInput(img)
return self.model.forward()
def __getstate__(self):
# Handling unpicklable objects
......@@ -97,4 +99,4 @@ class OpenCVModel(TransformerMixin, BaseEstimator):
return d
def _more_tags(self):
return {"stateless": True, "requires_fit": False}
return {"stateless": True, "requires_fit": False}
\ No newline at end of file
......@@ -25,7 +25,7 @@ opencv_model_directory = rc["bob.extractor_model.opencv"]
opencv_model_prototxt = rc["bob.extractor_weights.opencv"]
class opencv_model(TransformerMixin, BaseEstimator):
class OpenCVModel(TransformerMixin, BaseEstimator):
"""Extracts features using deep face recognition models under OpenCV Interface
Users can download the pretrained face recognition models with OpenCV Interface. The path to downloaded models should be specified before running the extractor (usually before running the pipeline file that includes the extractor). That is, set config of the model frame to :py:class:`bob.extractor_model.opencv`, and set config of the parameters to :py:class:`bob.extractor_weights.opencv`.
......@@ -39,15 +39,11 @@ class opencv_model(TransformerMixin, BaseEstimator):
.. note::
This structure only can be used for CAFFE pretrained model.
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.model = None
internal_path = pkg_resources.resource_filename(
__name__, os.path.join("data", "opencv_model"),
......@@ -63,7 +59,7 @@ class opencv_model(TransformerMixin, BaseEstimator):
def _load_model(self):
net = cv2.dnn.readNetFromCaffe(opencv_model_prototxt,opencv_model_directory)
net = cv2.dnn.readNetFromCaffe(opencv_model_prototxt, opencv_model_directory)
self.model = net
......@@ -82,17 +78,16 @@ class opencv_model(TransformerMixin, BaseEstimator):
feature : 2D or 3D :py:class:`numpy.ndarray` (floats)
The list of features extracted from the image.
"""
if self.model is None:
self._load_model()
img = np.array(X)
img = img / 255
self.model.setInput(img)
return self.model.forward()
return self.model.forward()
def __getstate__(self):
# Handling unpicklable objects
......@@ -102,5 +97,4 @@ class opencv_model(TransformerMixin, BaseEstimator):
return d
def _more_tags(self):
return {"stateless": True, "requires_fit": False}
......@@ -16,7 +16,6 @@ import imp
pytorch_model_directory = rc["bob.extractor_model.pytorch"]
pytorch_weight_directory = rc["bob.extractor_weights.pytorch"]
class PyTorchLoadedModel(TransformerMixin, BaseEstimator):
"""Extracts features using deep face recognition models under PyTorch Interface, especially for the models and weights that need to load by hand.
......@@ -28,7 +27,7 @@ class PyTorchLoadedModel(TransformerMixin, BaseEstimator):
$ bob config set bob.extractor_weights.pytorch /PATH/TO/WEIGHTS/
The extracted features can be combined with different the algorithms.
"""
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
......@@ -49,12 +48,12 @@ class PyTorchLoadedModel(TransformerMixin, BaseEstimator):
def _load_model(self):
MainModel = imp.load_source("MainModel", pytorch_model_directory)
MainModel = imp.load_source('MainModel', pytorch_model_directory)
network = torch.load(pytorch_weight_directory)
network.eval()
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
network.to(self.device)
self.model = network
......@@ -78,10 +77,11 @@ class PyTorchLoadedModel(TransformerMixin, BaseEstimator):
self._load_model()
X = torch.Tensor(X)
X = X / 255
X = X/255
return self.model(X).detach().numpy()
def __getstate__(self):
# Handling unpicklable objects
......@@ -91,8 +91,14 @@ class PyTorchLoadedModel(TransformerMixin, BaseEstimator):
def _more_tags(self):
return {"stateless": True, "requires_fit": False}
class PyTorchLibraryModel(TransformerMixin, BaseEstimator):
"""Extracts features using deep face recognition with registered model frames in the PyTorch Library.
......@@ -122,8 +128,8 @@ class PyTorchLibraryModel(TransformerMixin, BaseEstimator):
self.device = None
def _load_model(self):
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
self.model.to(self.device)
def transform(self, X):
......@@ -146,10 +152,11 @@ class PyTorchLibraryModel(TransformerMixin, BaseEstimator):
self._load_model()
X = torch.Tensor(X)
X = X / 255
X = X/255
return self.model(X).detach().numpy()
def __getstate__(self):
# Handling unpicklable objects
......@@ -158,4 +165,4 @@ class PyTorchLibraryModel(TransformerMixin, BaseEstimator):
return d
def _more_tags(self):
return {"stateless": True, "requires_fit": False}
return {"stateless": True, "requires_fit": False}
\ No newline at end of file
......@@ -16,7 +16,8 @@ import imp
pytorch_model_directory = rc["bob.extractor_model.pytorch"]
pytorch_weight_directory = rc["bob.extractor_weights.pytorch"]
class pytorch_loaded_model(TransformerMixin, BaseEstimator):
class PyTorchLoadedModel(TransformerMixin, BaseEstimator):
"""Extracts features using deep face recognition models under PyTorch Interface, especially for the models and weights that need to load by hand.
Users can download the pretrained face recognition models with PyTorch Interface. The path to downloaded models should be specified before running the extractor (usually before running the pipeline file that includes the extractor). That is, set config of the model frame to :py:class:`bob.extractor_model.pytorch`, and set config of the parameters to :py:class:`bob.extractor_weights.pytorch`.
......@@ -27,14 +28,11 @@ class pytorch_loaded_model(TransformerMixin, BaseEstimator):
$ bob config set bob.extractor_weights.pytorch /PATH/TO/WEIGHTS/
The extracted features can be combined with different the algorithms.
"""
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.model = None
internal_path = pkg_resources.resource_filename(
__name__, os.path.join("data", "resnet"),
......@@ -51,12 +49,12 @@ class pytorch_loaded_model(TransformerMixin, BaseEstimator):
def _load_model(self):
MainModel = imp.load_source('MainModel', pytorch_model_directory)
MainModel = imp.load_source("MainModel", pytorch_model_directory)
network = torch.load(pytorch_weight_directory)
network.eval()
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
network.to(self.device)
self.model = network
......@@ -76,15 +74,14 @@ class pytorch_loaded_model(TransformerMixin, BaseEstimator):
feature : 2D or 3D :py:class:`numpy.ndarray` (floats)
The list of features extracted from the image.
"""
if self.model is None:
self._load_model()
X = torch.Tensor(X)
X = X / 255
return self.model(X).detach().numpy()
def __getstate__(self):
# Handling unpicklable objects
......@@ -93,10 +90,10 @@ class pytorch_loaded_model(TransformerMixin, BaseEstimator):
return d
def _more_tags(self):
return {"stateless": True, "requires_fit": False}
class pytorch_library_model(TransformerMixin, BaseEstimator):
class PyTorchLibraryModel(TransformerMixin, BaseEstimator):
"""Extracts features using deep face recognition with registered model frames in the PyTorch Library.
Users can import the pretrained face recognition models from PyTorch library. The model should be called in the pipeline. Example: `facenet_pytorch <https://github.com/timesler/facenet-pytorch>`_
......@@ -105,7 +102,6 @@ class pytorch_library_model(TransformerMixin, BaseEstimator):
**Parameters:**
model: pytorch model calling from library.
use_gpu: True or False.
"""
def __init__(self, model=None, **kwargs):
......@@ -125,6 +121,11 @@ class pytorch_library_model(TransformerMixin, BaseEstimator):
self.checkpoint_path = checkpoint_path
self.device = None
def _load_model(self):
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
self.model.to(self.device)
def transform(self, X):
"""__call__(image) -> feature
......@@ -141,11 +142,14 @@ class pytorch_library_model(TransformerMixin, BaseEstimator):
The list of features extracted from the image.
"""
if self.model is None:
self._load_model()
X = torch.Tensor(X)
X = X / 255
return self.model(X).detach().numpy()
def __getstate__(self):
# Handling unpicklable objects
......@@ -154,4 +158,4 @@ class pytorch_library_model(TransformerMixin, BaseEstimator):
return d
def _more_tags(self):
return {"stateless": True, "requires_fit": False}
\ No newline at end of file
return {"stateless": True, "requires_fit": False}
......@@ -17,7 +17,6 @@ from tensorflow import keras
tf_model_directory = rc["bob.extractor_model.tf"]
class TensorFlowModel(TransformerMixin, BaseEstimator):
"""Extracts features using deep face recognition models under TensorFlow Interface.
......@@ -67,19 +66,20 @@ class TensorFlowModel(TransformerMixin, BaseEstimator):
feature : 2D or 3D :py:class:`numpy.ndarray` (floats)
The list of features extracted from the image.
"""
if self.model is None:
self._load_model()
X = check_array(X, allow_nd=True)
X = tf.convert_to_tensor(X)
X = to_channels_last(X)
X = X / 255
X = X/255
predict = self.model.predict(X)
return predict
def __getstate__(self):
# Handling unpicklable objects
......@@ -88,4 +88,4 @@ class TensorFlowModel(TransformerMixin, BaseEstimator):
return d
def _more_tags(self):
return {"stateless": True, "requires_fit": False}
return {"stateless": True, "requires_fit": False}
\ No newline at end of file
......@@ -17,7 +17,8 @@ from tensorflow import keras
tf_model_directory = rc["bob.extractor_model.tf"]
class tf_model(TransformerMixin, BaseEstimator):
class TensorFlowModel(TransformerMixin, BaseEstimator):
"""Extracts features using deep face recognition models under TensorFlow Interface.
Users can download the pretrained face recognition models with TensorFlow Interface. The path to downloaded models should be specified before running the extractor (usually before running the pipeline file that includes the extractor). That is, set config of the model to :py:class:`bob.extractor_model.tf`.
......@@ -27,8 +28,6 @@ class tf_model(TransformerMixin, BaseEstimator):
$ bob config set bob.extractor_model.tf /PATH/TO/MODEL/
The extracted features can be combined with different the algorithms.
"""
def __init__(self, **kwargs):
......@@ -68,19 +67,19 @@ class tf_model(TransformerMixin, BaseEstimator):