Commit c95c92d6 authored by Amir MOHAMMADI's avatar Amir MOHAMMADI
Browse files

Merge branch 'wrapper-api' into 'dask-pipelines'

Wrappers and aggregators

See merge request !185
parents 34a0591c 81f38592
Pipeline #39680 passed with stage
in 4 minutes and 47 seconds
from bob.bio.base.pipelines.vanilla_biometrics.implemented import CheckpointDistance
from bob.bio.base.pipelines.vanilla_biometrics.legacy import (
DatabaseConnector,
Preprocessor,
Extractor,
AlgorithmAsBioAlg,
)
from bob.bio.face.database.mobio import MobioBioDatabase
from bob.bio.face.preprocessor import FaceCrop
from bob.extension import rc
from bob.pipelines.transformers import CheckpointSampleLinearize, CheckpointSamplePCA
from sklearn.pipeline import make_pipeline
import functools
import os
import bob.bio.face
import math
base_dir = "example"
database = DatabaseConnector(
MobioBioDatabase(
original_directory=rc["bob.db.mobio.directory"],
annotation_directory=rc["bob.db.mobio.annotation_directory"],
original_extension=".png",
protocol="mobile0-male",
)
)
database.allow_score_multiple_references = True
# Using face crop
CROPPED_IMAGE_HEIGHT = 80
CROPPED_IMAGE_WIDTH = CROPPED_IMAGE_HEIGHT * 4 // 5
# eye positions for frontal images
RIGHT_EYE_POS = (CROPPED_IMAGE_HEIGHT // 5, CROPPED_IMAGE_WIDTH // 4 - 1)
LEFT_EYE_POS = (CROPPED_IMAGE_HEIGHT // 5, CROPPED_IMAGE_WIDTH // 4 * 3)
# FaceCrop
preprocessor = functools.partial(
bob.bio.face.preprocessor.INormLBP,
face_cropper=functools.partial(
bob.bio.face.preprocessor.FaceCrop,
cropped_image_size=(CROPPED_IMAGE_HEIGHT, CROPPED_IMAGE_WIDTH),
cropped_positions={"leye": LEFT_EYE_POS, "reye": RIGHT_EYE_POS},
color_channel="gray",
),
)
extractor = functools.partial(
bob.bio.face.extractor.GridGraph,
# Gabor parameters
gabor_sigma=math.sqrt(2.0) * math.pi,
# what kind of information to extract
normalize_gabor_jets=True,
# setup of the fixed grid
node_distance=(8, 8),
)
transformer = make_pipeline(
Preprocessor(preprocessor, features_dir=os.path.join(base_dir, "face_cropper")),
Extractor(extractor, features_dir=os.path.join(base_dir, "gabor_graph")),
)
## algorithm
gabor_jet = functools.partial(
bob.bio.face.algorithm.GaborJet,
gabor_jet_similarity_type="PhaseDiffPlusCanberra",
multiple_feature_scoring="max_jet",
gabor_sigma=math.sqrt(2.0) * math.pi,
)
algorithm = AlgorithmAsBioAlg(callable=gabor_jet, features_dir=base_dir, allow_score_multiple_references=True)
#algorithm = AlgorithmAsBioAlg(callable=gabor_jet, features_dir=base_dir)
from bob.bio.base.pipelines.vanilla_biometrics import VanillaBiometrics, dask_vanilla_biometrics
#pipeline = VanillaBiometrics(transformer, algorithm)
pipeline = dask_vanilla_biometrics(VanillaBiometrics(transformer, algorithm), npartitions=48)
from bob.bio.face.database import AtntBioDatabase
from bob.bio.gmm.algorithm import ISV
from bob.bio.face.preprocessor import FaceCrop
from sklearn.pipeline import make_pipeline
from bob.bio.base.pipelines.vanilla_biometrics.legacy import DatabaseConnector, Preprocessor, AlgorithmAsTransformer, AlgorithmAsBioAlg, Extractor
import functools
from bob.bio.base.pipelines.vanilla_biometrics.implemented import (
Distance,
CheckpointDistance,
)
import os
# DATABASE
database = DatabaseConnector(
AtntBioDatabase(original_directory="./atnt", protocol="Default"),
)
database.allow_scoring_with_all_biometric_references = True
base_dir = "example/isv"
# PREPROCESSOR LEGACY
# Cropping
CROPPED_IMAGE_HEIGHT = 80
CROPPED_IMAGE_WIDTH = CROPPED_IMAGE_HEIGHT * 4 // 5
# eye positions for frontal images
RIGHT_EYE_POS = (CROPPED_IMAGE_HEIGHT // 5, CROPPED_IMAGE_WIDTH // 4 - 1)
LEFT_EYE_POS = (CROPPED_IMAGE_HEIGHT // 5, CROPPED_IMAGE_WIDTH // 4 * 3)
# RANDOM EYES POSITIONS
# I JUST MADE UP THESE NUMBERS
FIXED_RIGHT_EYE_POS = (30, 30)
FIXED_LEFT_EYE_POS = (20, 50)
face_cropper = functools.partial(
FaceCrop,
cropped_image_size=(CROPPED_IMAGE_HEIGHT, CROPPED_IMAGE_WIDTH),
cropped_positions={"leye": LEFT_EYE_POS, "reye": RIGHT_EYE_POS},
fixed_positions={"leye": FIXED_LEFT_EYE_POS, "reye": FIXED_RIGHT_EYE_POS},
)
import bob.bio.face
extractor = functools.partial(
bob.bio.face.extractor.DCTBlocks,
block_size=12,
block_overlap=11,
number_of_dct_coefficients=45,
)
# ALGORITHM LEGACY
isv = functools.partial(ISV, subspace_dimension_of_u=10, number_of_gaussians=2)
model_path=os.path.join(base_dir, "ubm_u.hdf5")
transformer = make_pipeline(
Preprocessor(callable=face_cropper, features_dir=os.path.join(base_dir,"face_crop")),
Extractor(extractor, features_dir=os.path.join(base_dir, "dcts")),
AlgorithmAsTransformer(
callable=isv, features_dir=os.path.join(base_dir,"isv"), model_path=model_path
),
)
algorithm = AlgorithmAsBioAlg(callable=isv, features_dir=base_dir, model_path=model_path)
from bob.bio.base.pipelines.vanilla_biometrics import VanillaBiometrics, dask_vanilla_biometrics
#pipeline = VanillaBiometrics(transformer, algorithm)
pipeline = dask_vanilla_biometrics(VanillaBiometrics(transformer, algorithm))
from bob.bio.face.database import AtntBioDatabase
from bob.bio.base.algorithm import LDA
from bob.bio.face.preprocessor import FaceCrop
from sklearn.pipeline import make_pipeline
from bob.pipelines.transformers import CheckpointSampleLinearize
from bob.bio.base.pipelines.vanilla_biometrics.legacy import DatabaseConnector, Preprocessor, AlgorithmAsTransformer
import functools
from bob.bio.base.pipelines.vanilla_biometrics.implemented import (
Distance,
CheckpointDistance,
)
# DATABASE
database = DatabaseConnector(
AtntBioDatabase(original_directory="./atnt", protocol="Default"),
)
# PREPROCESSOR LEGACY
# Cropping
CROPPED_IMAGE_HEIGHT = 80
CROPPED_IMAGE_WIDTH = CROPPED_IMAGE_HEIGHT * 4 // 5
# eye positions for frontal images
RIGHT_EYE_POS = (CROPPED_IMAGE_HEIGHT // 5, CROPPED_IMAGE_WIDTH // 4 - 1)
LEFT_EYE_POS = (CROPPED_IMAGE_HEIGHT // 5, CROPPED_IMAGE_WIDTH // 4 * 3)
# RANDOM EYES POSITIONS
# I JUST MADE UP THESE NUMBERS
FIXED_RIGHT_EYE_POS = (30, 30)
FIXED_LEFT_EYE_POS = (20, 50)
face_cropper = functools.partial(
FaceCrop,
cropped_image_size=(CROPPED_IMAGE_HEIGHT, CROPPED_IMAGE_WIDTH),
cropped_positions={"leye": LEFT_EYE_POS, "reye": RIGHT_EYE_POS},
fixed_positions={"leye": FIXED_LEFT_EYE_POS, "reye": FIXED_RIGHT_EYE_POS},
)
# ALGORITHM LEGACY
lda = functools.partial(LDA, use_pinv=True, pca_subspace_dimension=0.90)
transformer = make_pipeline(
Preprocessor(callable=face_cropper, features_dir="./example/transformer0"),
CheckpointSampleLinearize(features_dir="./example/transformer1"),
AlgorithmAsTransformer(
callable=lda, features_dir="./example/transformer2", model_path="./example/lda_projector.hdf5"
),
)
algorithm = CheckpointDistance(features_dir="./example/")
# algorithm = Distance()
from bob.bio.base.pipelines.vanilla_biometrics import VanillaBiometrics, dask_vanilla_biometrics
#pipeline = VanillaBiometrics(transformer, algorithm)
pipeline = dask_vanilla_biometrics(VanillaBiometrics(transformer, algorithm))
from bob.bio.face.database import AtntBioDatabase
from bob.bio.base.algorithm import LDA
from bob.bio.face.preprocessor import FaceCrop
from sklearn.pipeline import make_pipeline
from bob.pipelines.transformers import CheckpointSampleLinearize
from bob.bio.base.pipelines.vanilla_biometrics.legacy import DatabaseConnector, Preprocessor, AlgorithmAsTransformer, AlgorithmAsBioAlg
import functools
from bob.bio.base.pipelines.vanilla_biometrics.implemented import (
Distance,
CheckpointDistance,
)
import os
# DATABASE
database = DatabaseConnector(
AtntBioDatabase(original_directory="./atnt", protocol="Default"),
)
base_dir = "example"
# PREPROCESSOR LEGACY
# Cropping
CROPPED_IMAGE_HEIGHT = 80
CROPPED_IMAGE_WIDTH = CROPPED_IMAGE_HEIGHT * 4 // 5
# eye positions for frontal images
RIGHT_EYE_POS = (CROPPED_IMAGE_HEIGHT // 5, CROPPED_IMAGE_WIDTH // 4 - 1)
LEFT_EYE_POS = (CROPPED_IMAGE_HEIGHT // 5, CROPPED_IMAGE_WIDTH // 4 * 3)
# RANDOM EYES POSITIONS
# I JUST MADE UP THESE NUMBERS
FIXED_RIGHT_EYE_POS = (30, 30)
FIXED_LEFT_EYE_POS = (20, 50)
face_cropper = functools.partial(
FaceCrop,
cropped_image_size=(CROPPED_IMAGE_HEIGHT, CROPPED_IMAGE_WIDTH),
cropped_positions={"leye": LEFT_EYE_POS, "reye": RIGHT_EYE_POS},
fixed_positions={"leye": FIXED_LEFT_EYE_POS, "reye": FIXED_RIGHT_EYE_POS},
)
# ALGORITHM LEGACY
lda = functools.partial(LDA, use_pinv=True, pca_subspace_dimension=0.90)
transformer = make_pipeline(
Preprocessor(callable=face_cropper, features_dir=os.path.join(base_dir,"transformer0")),
CheckpointSampleLinearize(features_dir=os.path.join(base_dir,"transformer1")),
AlgorithmAsTransformer(
callable=lda, features_dir=os.path.join(base_dir,"transformer2"), model_path=os.path.join(base_dir, "lda.hdf5")
),
)
algorithm = AlgorithmAsBioAlg(callable=lda, features_dir="./example/")
from bob.bio.base.pipelines.vanilla_biometrics import VanillaBiometrics, dask_vanilla_biometrics
#pipeline = VanillaBiometrics(transformer, algorithm)
pipeline = dask_vanilla_biometrics(VanillaBiometrics(transformer, algorithm))
from bob.bio.base.pipelines.vanilla_biometrics.legacy import DatabaseConnector
from sklearn.pipeline import make_pipeline
from bob.pipelines.transformers import CheckpointSampleLinearize, CheckpointSamplePCA
from bob.bio.base.pipelines.vanilla_biometrics.implemented import (
CheckpointDistance,
)
from bob.bio.face.database import AtntBioDatabase
import os
base_dir = "example"
database = DatabaseConnector(AtntBioDatabase(original_directory="./atnt", protocol="Default"))
database.allow_scoring_with_all_biometric_references = True
transformer = make_pipeline(
CheckpointSampleLinearize(features_dir=os.path.join(base_dir, "linearize")),
CheckpointSamplePCA(
features_dir=os.path.join(base_dir, "pca_features"), model_path=os.path.join(base_dir, "pca.pkl")
),
)
algorithm = CheckpointDistance(features_dir=base_dir, allow_score_multiple_references=True)
# # comment out the code below to disable dask
from bob.pipelines.mixins import estimator_dask_it, mix_me_up
from bob.bio.base.pipelines.vanilla_biometrics.mixins import (
BioAlgDaskMixin,
)
from bob.bio.base.pipelines.vanilla_biometrics import VanillaBiometrics, dask_vanilla_biometrics
pipeline = VanillaBiometrics(transformer, algorithm)
#pipeline = dask_vanilla_biometrics(VanillaBiometrics(transformer, algorithm))
from bob.bio.base.pipelines.vanilla_biometrics.implemented import (
CheckpointDistance,
)
from bob.bio.base.pipelines.vanilla_biometrics.legacy import (
DatabaseConnector,
Preprocessor,
)
from bob.bio.face.database.mobio import MobioBioDatabase
from bob.bio.face.preprocessor import FaceCrop
from bob.extension import rc
from bob.pipelines.transformers import CheckpointSampleLinearize, CheckpointSamplePCA
from sklearn.pipeline import make_pipeline
import functools
database = DatabaseConnector(
MobioBioDatabase(
original_directory=rc["bob.db.mobio.directory"],
annotation_directory=rc["bob.db.mobio.annotation_directory"],
original_extension=".png",
protocol="mobile0-male",
)
)
# Using face crop
CROPPED_IMAGE_HEIGHT = 80
CROPPED_IMAGE_WIDTH = CROPPED_IMAGE_HEIGHT * 4 // 5
# eye positions for frontal images
RIGHT_EYE_POS = (CROPPED_IMAGE_HEIGHT // 5, CROPPED_IMAGE_WIDTH // 4 - 1)
LEFT_EYE_POS = (CROPPED_IMAGE_HEIGHT // 5, CROPPED_IMAGE_WIDTH // 4 * 3)
# FaceCrop
preprocessor = functools.partial(
FaceCrop,
cropped_image_size=(CROPPED_IMAGE_HEIGHT, CROPPED_IMAGE_WIDTH),
cropped_positions={"leye": LEFT_EYE_POS, "reye": RIGHT_EYE_POS},
)
transformer = make_pipeline(
Preprocessor(preprocessor, features_dir="./example/extractor0"),
CheckpointSampleLinearize(features_dir="./example/extractor1"),
CheckpointSamplePCA(
features_dir="./example/extractor2", model_path="./example/pca.pkl"
),
)
algorithm = CheckpointDistance(features_dir="./example/")
from bob.bio.base.pipelines.vanilla_biometrics import VanillaBiometrics, dask_vanilla_biometrics
#pipeline = VanillaBiometrics(transformer, algorithm)
pipeline = dask_vanilla_biometrics(VanillaBiometrics(transformer, algorithm), npartitions=48)
# see https://docs.python.org/3/library/pkgutil.html
from pkgutil import extend_path
from .pipelines import VanillaBiometricsPipeline
from .biometric_algorithms import Distance
from .score_writers import FourColumnsScoreWriter, CSVScoreWriter
from .wrappers import BioAlgorithmCheckpointWrapper, BioAlgorithmDaskWrapper, dask_vanilla_biometrics
from .pipeline import VanillaBiometrics, dask_vanilla_biometrics
__path__ = extend_path(__path__, __name__)
from .legacy import BioAlgorithmLegacy, DatabaseConnector
\ No newline at end of file
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
from abc import ABCMeta, abstractmethod
from bob.pipelines.sample import Sample, SampleSet, DelayedSample
import functools
......@@ -9,14 +13,9 @@ class BioAlgorithm(metaclass=ABCMeta):
biometric model enrollement, via ``enroll()`` and scoring, with
``score()``.
Parameters
----------
"""
def __init__(self, allow_score_multiple_references=False, **kwargs):
self.allow_score_multiple_references = allow_score_multiple_references
def __init__(self, **kwargs):
self.stacked_biometric_references = None
def enroll_samples(self, biometric_references):
......@@ -61,7 +60,12 @@ class BioAlgorithm(metaclass=ABCMeta):
"""
pass
def score_samples(self, probe_features, biometric_references, allow_scoring_with_all_biometric_references=False):
def score_samples(
self,
probe_features,
biometric_references,
allow_scoring_with_all_biometric_references=False,
):
"""Scores a new sample against multiple (potential) references
Parameters
......@@ -78,7 +82,7 @@ class BioAlgorithm(metaclass=ABCMeta):
allow_scoring_with_all_biometric_references: bool
If true will call `self.score_multiple_biometric_references`, at scoring time, to compute scores in one shot with multiple probes.
This optiization is useful when all probes needs to be compared with all biometric references AND
This optimization is useful when all probes needs to be compared with all biometric references AND
your scoring function allows this broadcast computation.
......@@ -87,18 +91,29 @@ class BioAlgorithm(metaclass=ABCMeta):
scores : list
For each sample in a probe, returns as many scores as there are
samples in the probe, together with the probe's and the
samples in the probe, together with the probes and the
relevant reference's subject identifiers.
"""
retval = []
for p in probe_features:
retval.append(self._score_sample_set(p, biometric_references, allow_scoring_with_all_biometric_references=allow_scoring_with_all_biometric_references))
retval.append(
self._score_sample_set(
p,
biometric_references,
allow_scoring_with_all_biometric_references=allow_scoring_with_all_biometric_references,
)
)
return retval
def _score_sample_set(self, sampleset, biometric_references, allow_scoring_with_all_biometric_references):
"""Given a sampleset for probing, compute the scores and retures a sample set with the scores
def _score_sample_set(
self,
sampleset,
biometric_references,
allow_scoring_with_all_biometric_references,
):
"""Given a sampleset for probing, compute the scores and returns a sample set with the scores
"""
# Stacking the samples from a sampleset
......@@ -106,15 +121,10 @@ class BioAlgorithm(metaclass=ABCMeta):
# Compute scores for each sample inside of the sample set
# TODO: In some cases we want to compute 1 score per sampleset (IJB-C)
# We should add an agregator function here so we can properlly agregate samples from
# We should add an aggregator function here so we can properly aggregator samples from
# a sampleset either after or before scoring.
# To be honest, this should be the default behaviour
# To be honest, this should be the default behavior
retval = []
def _write_sample(ref, probe, score):
data = make_four_colums_score(ref.subject, probe.subject, probe.path, score)
return Sample(data, parent=ref)
for subprobe_id, (s, parent) in enumerate(zip(data, sampleset.samples)):
# Creating one sample per comparison
subprobe_scores = []
......@@ -128,21 +138,25 @@ class BioAlgorithm(metaclass=ABCMeta):
scores = self.score_multiple_biometric_references(
self.stacked_biometric_references, s
)
# Wrapping the scores in samples
for ref, score in zip(biometric_references, scores):
subprobe_scores.append(_write_sample(ref, sampleset, score))
subprobe_scores.append(Sample(score, parent=ref))
else:
for ref in [
r for r in biometric_references if r.key in sampleset.references
]:
score = self.score(ref.data, s)
subprobe_scores.append(_write_sample(ref, sampleset, score))
# Creating one sampleset per probe
subprobe = SampleSet(subprobe_scores, parent=sampleset)
subprobe.subprobe_id = subprobe_id
subprobe_scores.append(Sample(score, parent=ref))
# Fetching metadata from the probe
kwargs = dict(
(metadata, sampleset.__dict__[metadata])
for metadata in sampleset.__dict__.keys()
if metadata not in ["samples", "key", "data", "load", "_data"]
)
subprobe = SampleSet(subprobe_scores, parent=parent, **kwargs)
retval.append(subprobe)
return retval
......@@ -245,26 +259,23 @@ class Database(metaclass=ABCMeta):
pass
def make_four_colums_score(
biometric_reference_subject, probe_subject, probe_path, score,
):
data = "{0} {1} {2} {3}\n".format(
biometric_reference_subject, probe_subject, probe_path, score,
)
return data
def create_score_delayed_sample(path, probe):
class ScoreWriter(metaclass=ABCMeta):
"""
Write scores in the four columns format
Defines base methods to read, write scores and concatenate scores
for :any:`BioAlgorithm`
"""
with open(path, "w") as f:
for score_line in probe.samples:
f.write(score_line.data)
def __init__(self, extension=".txt"):
self.extension = extension
def load():
with open(path) as f:
return f.read()
@abstractmethod
def write(self, sampleset, path):
pass
return DelayedSample(load, parent=probe)
@abstractmethod
def read(self, path):
pass
@abstractmethod
def concatenate_write_scores(self, sampleset, path):
pass
......@@ -2,8 +2,10 @@ import scipy.spatial.distance
from sklearn.utils.validation import check_array
import numpy
from .abstract_classes import BioAlgorithm
from .mixins import BioAlgCheckpointMixin
from scipy.spatial.distance import cdist
import os
from bob.pipelines import DelayedSample, Sample, SampleSet
import functools
class Distance(BioAlgorithm):
......@@ -69,7 +71,3 @@ class Distance(BioAlgorithm):
)
return list(scores.flatten())
class CheckpointDistance(BioAlgCheckpointMixin, Distance):
pass
......@@ -11,17 +11,16 @@ from bob.bio.base import utils
from .abstract_classes import (
BioAlgorithm,
Database,
create_score_delayed_sample,
make_four_colums_score,
)
from bob.io.base import HDF5File
from bob.pipelines.mixins import SampleMixin, CheckpointMixin
from bob.pipelines.sample import DelayedSample, SampleSet, Sample
from bob.pipelines.utils import is_picklable
from sklearn.base import TransformerMixin, BaseEstimator