Commit ffd5e023 authored by Olegs NIKISINS's avatar Olegs NIKISINS
Browse files

Merge branch 'batl_hldi' into 'master'

Added HLDI for the BATL database, added optional data normalization in FaceCropAlign

See merge request !59
parents fda0ad1a f627bc6c
Pipeline #18375 passed with stages
in 64 minutes and 32 seconds
#!/usr/bin/env python
"""
BATL Db is a database for face PAD experiments.
"""
from bob.pad.face.database import BatlPadDatabase
# Directory where the data files are stored.
# This directory is given in the .bob_bio_databases.txt file located in your home directory
ORIGINAL_DIRECTORY = "[YOUR_BATL_DB_DIRECTORY]"
"""Value of ``~/.bob_bio_databases.txt`` for this database"""
ORIGINAL_EXTENSION = ".h5" # extension of the data files
ANNOTATIONS_TEMP_DIR = ""
PROTOCOL = 'nowig-color-50'
database = BatlPadDatabase(
protocol=PROTOCOL,
original_directory=ORIGINAL_DIRECTORY,
original_extension=ORIGINAL_EXTENSION,
annotations_temp_dir=ANNOTATIONS_TEMP_DIR,
landmark_detect_method="mtcnn",
training_depends_on_protocol=True,
)
"""The :py:class:`bob.pad.base.database.BatlPadDatabase` derivative with BATL Db
database settings.
.. warning::
This class only provides a programmatic interface to load data in an orderly
manner, respecting usage protocols. It does **not** contain the raw
data files. You should procure those yourself.
Notice that ``original_directory`` is set to ``[BatlPadDatabase]``.
You must make sure to create ``${HOME}/.bob_bio_databases.txt`` file setting this
value to the places where you actually installed the BATL database.
"""
protocol = PROTOCOL
"""
You may modify this at runtime by specifying the option ``--protocol`` on the
command-line of ``spoof.py`` or using the keyword ``protocol`` on a
configuration file that is loaded **after** this configuration resource.
"""
groups = ["train", "dev", "eval"]
"""The default groups to use for reproducing the baselines.
You may modify this at runtime by specifying the option ``--groups`` on the
command-line of ``spoof.py`` or using the keyword ``groups`` on a
configuration file that is loaded **after** this configuration resource.
"""
#!/usr/bin/env python
"""
BATL Db is a database for face PAD experiments.
"""
from bob.pad.face.database import BatlPadDatabase
# Directory where the data files are stored.
# This directory is given in the .bob_bio_databases.txt file located in your home directory
ORIGINAL_DIRECTORY = "[YOUR_BATL_DB_DIRECTORY]"
"""Value of ``~/.bob_bio_databases.txt`` for this database"""
ORIGINAL_EXTENSION = ".h5" # extension of the data files
ANNOTATIONS_TEMP_DIR = ""
PROTOCOL = 'nowig-depth-50'
database = BatlPadDatabase(
protocol=PROTOCOL,
original_directory=ORIGINAL_DIRECTORY,
original_extension=ORIGINAL_EXTENSION,
annotations_temp_dir=ANNOTATIONS_TEMP_DIR,
landmark_detect_method="mtcnn",
training_depends_on_protocol=True,
)
"""The :py:class:`bob.pad.base.database.BatlPadDatabase` derivative with BATL Db
database settings.
.. warning::
This class only provides a programmatic interface to load data in an orderly
manner, respecting usage protocols. It does **not** contain the raw
data files. You should procure those yourself.
Notice that ``original_directory`` is set to ``[BatlPadDatabase]``.
You must make sure to create ``${HOME}/.bob_bio_databases.txt`` file setting this
value to the places where you actually installed the BATL database.
"""
protocol = PROTOCOL
"""
You may modify this at runtime by specifying the option ``--protocol`` on the
command-line of ``spoof.py`` or using the keyword ``protocol`` on a
configuration file that is loaded **after** this configuration resource.
"""
groups = ["train", "dev", "eval"]
"""The default groups to use for reproducing the baselines.
You may modify this at runtime by specifying the option ``--groups`` on the
command-line of ``spoof.py`` or using the keyword ``groups`` on a
configuration file that is loaded **after** this configuration resource.
"""
#!/usr/bin/env python
"""
BATL Db is a database for face PAD experiments.
"""
from bob.pad.face.database import BatlPadDatabase
# Directory where the data files are stored.
# This directory is given in the .bob_bio_databases.txt file located in your home directory
ORIGINAL_DIRECTORY = "[YOUR_BATL_DB_DIRECTORY]"
"""Value of ``~/.bob_bio_databases.txt`` for this database"""
ORIGINAL_EXTENSION = ".h5" # extension of the data files
ANNOTATIONS_TEMP_DIR = ""
PROTOCOL = 'nowig-infrared-50'
database = BatlPadDatabase(
protocol=PROTOCOL,
original_directory=ORIGINAL_DIRECTORY,
original_extension=ORIGINAL_EXTENSION,
annotations_temp_dir=ANNOTATIONS_TEMP_DIR,
landmark_detect_method="mtcnn",
training_depends_on_protocol=True,
)
"""The :py:class:`bob.pad.base.database.BatlPadDatabase` derivative with BATL Db
database settings.
.. warning::
This class only provides a programmatic interface to load data in an orderly
manner, respecting usage protocols. It does **not** contain the raw
data files. You should procure those yourself.
Notice that ``original_directory`` is set to ``[BatlPadDatabase]``.
You must make sure to create ``${HOME}/.bob_bio_databases.txt`` file setting this
value to the places where you actually installed the BATL database.
"""
protocol = PROTOCOL
"""
You may modify this at runtime by specifying the option ``--protocol`` on the
command-line of ``spoof.py`` or using the keyword ``protocol`` on a
configuration file that is loaded **after** this configuration resource.
"""
groups = ["train", "dev", "eval"]
"""The default groups to use for reproducing the baselines.
You may modify this at runtime by specifying the option ``--groups`` on the
command-line of ``spoof.py`` or using the keyword ``groups`` on a
configuration file that is loaded **after** this configuration resource.
"""
#!/usr/bin/env python
"""
BATL Db is a database for face PAD experiments.
"""
from bob.pad.face.database import BatlPadDatabase
# Directory where the data files are stored.
# This directory is given in the .bob_bio_databases.txt file located in your home directory
ORIGINAL_DIRECTORY = "[YOUR_BATL_DB_DIRECTORY]"
"""Value of ``~/.bob_bio_databases.txt`` for this database"""
ORIGINAL_EXTENSION = ".h5" # extension of the data files
ANNOTATIONS_TEMP_DIR = ""
PROTOCOL = 'nowig-thermal-50'
database = BatlPadDatabase(
protocol=PROTOCOL,
original_directory=ORIGINAL_DIRECTORY,
original_extension=ORIGINAL_EXTENSION,
annotations_temp_dir=ANNOTATIONS_TEMP_DIR,
landmark_detect_method="mtcnn",
training_depends_on_protocol=True,
)
"""The :py:class:`bob.pad.base.database.BatlPadDatabase` derivative with BATL Db
database settings.
.. warning::
This class only provides a programmatic interface to load data in an orderly
manner, respecting usage protocols. It does **not** contain the raw
data files. You should procure those yourself.
Notice that ``original_directory`` is set to ``[BatlPadDatabase]``.
You must make sure to create ``${HOME}/.bob_bio_databases.txt`` file setting this
value to the places where you actually installed the BATL database.
"""
protocol = PROTOCOL
"""
You may modify this at runtime by specifying the option ``--protocol`` on the
command-line of ``spoof.py`` or using the keyword ``protocol`` on a
configuration file that is loaded **after** this configuration resource.
"""
groups = ["train", "dev", "eval"]
"""The default groups to use for reproducing the baselines.
You may modify this at runtime by specifying the option ``--groups`` on the
command-line of ``spoof.py`` or using the keyword ``groups`` on a
configuration file that is loaded **after** this configuration resource.
"""
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
This file contains configurations to run LBP and SVM based face PAD baseline.
The settings are tuned for the Replay-attack database.
The idea of the algorithm is introduced in the following paper: [CAM12]_.
However some settings are different from the ones introduced in the paper.
"""
#=======================================================================================
sub_directory = 'lbp_svm'
"""
Sub-directory where results will be placed.
You may change this setting using the ``--sub-directory`` command-line option
or the attribute ``sub_directory`` in a configuration file loaded **after**
this resource.
"""
#=======================================================================================
# define preprocessor:
from ..preprocessor import FaceCropAlign
from bob.bio.video.preprocessor import Wrapper
from bob.bio.video.utils import FrameSelector
from ..preprocessor.FaceCropAlign import auto_norm_image as _norm_func
FACE_SIZE = 64 # The size of the resulting face
RGB_OUTPUT_FLAG = False # Gray-scale output
USE_FACE_ALIGNMENT = False # use annotations
MAX_IMAGE_SIZE = None # no limiting here
FACE_DETECTION_METHOD = None # use annotations
MIN_FACE_SIZE = 50 # skip small faces
NORMALIZATION_FUNCTION = _norm_func
NORMALIZATION_FUNCTION_KWARGS = {}
NORMALIZATION_FUNCTION_KWARGS = {'n_sigma':3.0, 'norm_method':'MAD'}
_image_preprocessor = FaceCropAlign(face_size = FACE_SIZE,
rgb_output_flag = RGB_OUTPUT_FLAG,
use_face_alignment = USE_FACE_ALIGNMENT,
max_image_size = MAX_IMAGE_SIZE,
face_detection_method = FACE_DETECTION_METHOD,
min_face_size = MIN_FACE_SIZE,
normalization_function = NORMALIZATION_FUNCTION,
normalization_function_kwargs = NORMALIZATION_FUNCTION_KWARGS)
_frame_selector = FrameSelector(selection_style = "all")
preprocessor = Wrapper(preprocessor = _image_preprocessor,
frame_selector = _frame_selector)
"""
In the preprocessing stage the face is cropped in each frame of the input video given facial annotations.
The size of the face is normalized to ``FACE_SIZE`` dimensions. The faces with the size
below ``MIN_FACE_SIZE`` threshold are discarded. The preprocessor is similar to the one introduced in
[CAM12]_, which is defined by ``FACE_DETECTION_METHOD = None``.
"""
#=======================================================================================
# define extractor:
from ..extractor import LBPHistogram
from bob.bio.video.extractor import Wrapper
LBPTYPE = 'uniform'
ELBPTYPE = 'regular'
RAD = 1
NEIGHBORS = 8
CIRC = False
DTYPE = None
extractor = Wrapper(LBPHistogram(
lbptype=LBPTYPE,
elbptype=ELBPTYPE,
rad=RAD,
neighbors=NEIGHBORS,
circ=CIRC,
dtype=DTYPE))
"""
In the feature extraction stage the LBP histograms are extracted from each frame of the preprocessed video.
The parameters are similar to the ones introduced in [CAM12]_.
"""
#=======================================================================================
# define algorithm:
from bob.pad.base.algorithm import LogRegr
C = 1. # The regularization parameter for the LR classifier
FRAME_LEVEL_SCORES_FLAG = True # Return one score per frame
algorithm = LogRegr(
C=C, frame_level_scores_flag=FRAME_LEVEL_SCORES_FLAG)
"""
The Logistic Regression is used to classify the data into *real* and *attack* classes.
One score is produced for each frame of the input video, ``frame_level_scores_flag = True``.
The sub-sampling of training data is not used here, sub-sampling flags have default ``False``
values.
"""
......@@ -4,6 +4,7 @@ from .replay_mobile import ReplayMobilePadDatabase
from .msu_mfsd import MsuMfsdPadDatabase
from .aggregated_db import AggregatedDbPadDatabase
from .mifs import MIFSPadDatabase
from .batl import BatlPadDatabase
# gets sphinx autodoc done right - don't remove it
......@@ -29,6 +30,7 @@ __appropriate__(
MsuMfsdPadDatabase,
AggregatedDbPadDatabase,
MIFSPadDatabase,
BatlPadDatabase,
)
__all__ = [_ for _ in dir() if not _.startswith('_')]
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# Used in BATLMobilePadFile class
from bob.pad.base.database import PadDatabase, PadFile
from bob.bio.video import FrameSelector
from bob.extension import rc
from bob.pad.face.preprocessor.FaceCropAlign import detect_face_landmarks_in_image
import json
import os
import bob.io.base
class BatlPadFile(PadFile):
"""
A high level implementation of the File class for the BATL
database.
"""
def __init__(self, f,
stream_type, # a list of streams to be loaded
max_frames,
reference_stream_type="color",
warp_to_reference=True,
convert_to_rgb=False,
crop=None,
video_data_only=True):
"""
**Parameters:**
``f`` : :py:class:`object`
An instance of the File class defined in the low level db interface
of the BATL database, in the ``bob.db.batl.models.py`` file.
``stream_type`` : [] or :py:class:`str`
A types of the streams to be loaded.
``max_frames`` : :py:class:`int`
A maximum number of frames to be loaded. Frames are
selected uniformly.
``reference_stream_type`` : :py:class:`str`
Align/register all channels to this one.
Default: "color".
``warp_to_reference`` : :py:class:`bool`
Align/register downloaded video to ``reference_stream_type``,
if set to ``True``.
Default: ``True``.
``convert_to_rgb`` : :py:class:`bool`
Type cast the non-RGB data to RGB data type,
if set to ``True``.
Default: ``False``.
``crop`` : []
Pre-crop the frames if given, see ``bob.db.batl`` for more
details.
Default: ``None``.
``video_data_only`` : :py:class:`bool`
Load video data only if ``True``. Otherwise more meta-data
is loaded, for example timestamps for each frame.
See the ``load()`` method in the low-level database
interface for more details.
Default: ``True``.
"""
self.f = f
if f.is_attack():
attack_type = 'attack'
else:
attack_type = None
super(BatlPadFile, self).__init__(
client_id=f.client_id,
path=f.path,
attack_type=attack_type,
file_id=f.id)
self.stream_type = stream_type
self.max_frames = max_frames
self.reference_stream_type = reference_stream_type # "color"
self.warp_to_reference = warp_to_reference # True
self.convert_to_rgb = convert_to_rgb # False
self.crop = crop # None
self.video_data_only = video_data_only # True
def load(self, directory=None, extension='.h5',
frame_selector=FrameSelector(selection_style='all')):
"""
Load method of the file class.
**Parameters:**
``directory`` : :py:class:`str`
String containing the path to BATL database.
Default: ``None``.
``extension`` : :py:class:`str`
Extension of the BATL database.
Default: ".h5".
``frame_selector`` : :any:`bob.bio.video.FrameSelector`, optional
Specifying the frames to be selected.
**Returns:**
``data`` : FrameContainer
Video data stored in the FrameContainer,
see ``bob.bio.video.utils.FrameContainer``
for further details.
"""
data = self.f.load(directory=directory,
extension=extension,
modality=self.stream_type,
reference_stream_type=self.reference_stream_type,
warp_to_reference=self.warp_to_reference,
convert_to_rgb=self.convert_to_rgb,
crop=self.crop,
max_frames=self.max_frames)
for meta_data in data.keys():
if meta_data != 'rppg':
data[meta_data] = frame_selector(data[meta_data])
if self.video_data_only:
data = data['video']
return data
class BatlPadDatabase(PadDatabase):
"""
A high level implementation of the Database class for the BATL
database.
"""
def __init__(
self,
protocol='nowig',
original_directory=rc['bob.db.batl.directory'],
original_extension='.h5',
annotations_temp_dir="",
landmark_detect_method="mtcnn",
**kwargs):
"""
**Parameters:**
``protocol`` : str or None
The name of the protocol that defines the default experimental
setup for this database. Also a "complex" protocols can be
parsed.
For example:
"nowig-color-5" - nowig protocol, color data only,
use 5 first frames.
"nowig-depth-5" - nowig protocol, depth data only,
use 5 first frames.
"nowig-color" - nowig protocol, depth data only, use all frames.
See the ``parse_protocol`` method of this class.
``original_directory`` : str
The directory where the original data of the database are stored.
``original_extension`` : str
The file name extension of the original data.
``annotations_temp_dir`` : str
Annotations computed in ``self.annotations(f)`` method of this
class will be save to this directory if path is specified /
non-empty string.
Default: ``""``.
``landmark_detect_method`` : str
Method to be used to compute annotations - face bounding box and
landmarks. Possible options: "dlib" or "mtcnn".
Default: ``"mtcnn"``.
``kwargs`` : dict
The arguments of the :py:class:`bob.bio.base.database.BioDatabase`
base class constructor.
"""
from bob.db.batl import Database as LowLevelDatabase
self.db = LowLevelDatabase()
# Since the high level API expects different group names than what the
# low level API offers, you need to convert them when necessary
self.low_level_group_names = (
'train', 'validation',
'test') # group names in the low-level database interface
self.high_level_group_names = (
'train', 'dev',
'eval') # names are expected to be like that in objects() function
# Always use super to call parent class methods.
super(BatlPadDatabase, self).__init__(
name='batl',
protocol=protocol,
original_directory=original_directory,
original_extension=original_extension,
**kwargs)
self.protocol = protocol
self.original_directory = original_directory
self.original_extension = original_extension
self.annotations_temp_dir = annotations_temp_dir
self.landmark_detect_method = landmark_detect_method
@property
def original_directory(self):
return self.db.original_directory
@original_directory.setter
def original_directory(self, value):
self.db.original_directory = value
def parse_protocol(self, protocol):
"""
Parse the protocol name, which is give as a string.
An example of protocols it can parse:
"nowig-color-5" - nowig protocol, color data only, use 5 first frames.
"nowig-depth-5" - nowig protocol, depth data only, use 5 first frames.
"nowig-color" - nowig protocol, depth data only, use all frames.
**Parameters:**
``protocol`` : str
Protocol name to be parsed. Example: "nowig-depth-5" .
**Returns:**
``protocol`` : str
The name of the protocol as defined in the low level db interface.
``stream_type`` : str
The name of the channel/stream_type to be loaded.
``max_frames`` : int
The number of frames to be loaded.
"""
components = protocol.split("-")
components = components + [None, None]
components = components[0:3]
protocol, stream_type, max_frames = components
if max_frames is not None:
max_frames = int(max_frames)
return protocol, stream_type, max_frames
def objects(self,
protocol=None,
groups=None,
purposes=None,
model_ids=None,
**kwargs):
"""
This function returns lists of BatlPadFile objects, which fulfill the
given restrictions.
**Parameters:**
``protocol`` : str
The protocol for which the clients should be retrieved.
The protocol is dependent on your database.
If you do not have protocols defined, just ignore this field.
``purposes`` : :obj:`str` or [:obj:`str`]
The purposes for which File objects should be retrieved.