Skip to content
Snippets Groups Projects
Commit bf62bd2b authored by Olegs NIKISINS's avatar Olegs NIKISINS
Browse files

Added documentation to BATL HLDI classes

parent 3dafc0c0
No related branches found
No related tags found
1 merge request!59Added HLDI for the BATL database, added optional data normalization in FaceCropAlign
...@@ -6,8 +6,6 @@ from bob.pad.base.database import PadDatabase, PadFile ...@@ -6,8 +6,6 @@ from bob.pad.base.database import PadDatabase, PadFile
from bob.bio.video import FrameSelector from bob.bio.video import FrameSelector
from bob.extension import rc from bob.extension import rc
import pkg_resources
from bob.pad.face.preprocessor.FaceCropAlign import detect_face_landmarks_in_image from bob.pad.face.preprocessor.FaceCropAlign import detect_face_landmarks_in_image
import json import json
...@@ -16,6 +14,7 @@ import os ...@@ -16,6 +14,7 @@ import os
import bob.io.base import bob.io.base
class BatlPadFile(PadFile): class BatlPadFile(PadFile):
""" """
A high level implementation of the File class for the BATL A high level implementation of the File class for the BATL
...@@ -32,17 +31,48 @@ class BatlPadFile(PadFile): ...@@ -32,17 +31,48 @@ class BatlPadFile(PadFile):
video_data_only=True): video_data_only=True):
""" """
Parameters **Parameters:**
----------
f : object ``f`` : :py:class:`object`
An instance of the File class defined in the low level db interface 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. 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 self.f = f
if f.is_attack(): if f.is_attack():
# attack = BATL_CONFIG[f.type_id]
# attack_type = '{} : {}'.format(attack['name'], attack['pai'][f.pai_id])
attack_type = 'attack' attack_type = 'attack'
else: else:
attack_type = None attack_type = None
...@@ -59,23 +89,46 @@ class BatlPadFile(PadFile): ...@@ -59,23 +89,46 @@ class BatlPadFile(PadFile):
self.warp_to_reference = warp_to_reference # True self.warp_to_reference = warp_to_reference # True
self.convert_to_rgb = convert_to_rgb # False self.convert_to_rgb = convert_to_rgb # False
self.crop = crop # None self.crop = crop # None
self.video_data_only = video_data_only # return video data only if True 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.
def load(self, directory=None, extension='.hdf5', frame_selector=FrameSelector(selection_style='all')): **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, data = self.f.load(directory=directory,
extension=extension, extension=extension,
modality=self.stream_type, # TODO: this parameter is currently missing in bob.db.batl, add it there modality=self.stream_type,
reference_stream_type=self.reference_stream_type, reference_stream_type=self.reference_stream_type,
warp_to_reference=self.warp_to_reference, warp_to_reference=self.warp_to_reference,
convert_to_rgb=self.convert_to_rgb, convert_to_rgb=self.convert_to_rgb,
crop=self.crop, crop=self.crop,
max_frames=self.max_frames) max_frames=self.max_frames)
for modality in data.keys(): for meta_data in data.keys():
if modality != 'rppg': if meta_data != 'rppg':
data[modality] = frame_selector(data[modality]) data[meta_data] = frame_selector(data[meta_data])
if self.video_data_only: if self.video_data_only:
...@@ -92,7 +145,6 @@ class BatlPadDatabase(PadDatabase): ...@@ -92,7 +145,6 @@ class BatlPadDatabase(PadDatabase):
def __init__( def __init__(
self, self,
# nowig is the selected default protocol
protocol='nowig', protocol='nowig',
original_directory=rc['bob.db.batl.directory'], original_directory=rc['bob.db.batl.directory'],
original_extension='.h5', original_extension='.h5',
...@@ -100,26 +152,38 @@ class BatlPadDatabase(PadDatabase): ...@@ -100,26 +152,38 @@ class BatlPadDatabase(PadDatabase):
landmark_detect_method="mtcnn", landmark_detect_method="mtcnn",
**kwargs): **kwargs):
""" """
Parameters **Parameters:**
----------
protocol : str or None ``protocol`` : str or None
The name of the protocol that defines the default experimental The name of the protocol that defines the default experimental
setup for this database. Also a "complex" protocols can be setup for this database. Also a "complex" protocols can be
parsed. parsed.
For example: For example:
"nowig-color-5" - nowig protocol, color data only, use 5 first frames. "nowig-color-5" - nowig protocol, color data only,
"nowig-depth-5" - nowig protocol, depth data only, use 5 first frames. 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. "nowig-color" - nowig protocol, depth data only, use all frames.
See the ``parse_protocol`` method of this class. See the ``parse_protocol`` method of this class.
original_directory : str ``original_directory`` : str
The directory where the original data of the database are stored. The directory where the original data of the database are stored.
original_extension : str ``original_extension`` : str
The file name extension of the original data. The file name extension of the original data.
kwargs ``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` The arguments of the :py:class:`bob.bio.base.database.BioDatabase`
base class constructor. base class constructor.
""" """
...@@ -205,34 +269,38 @@ class BatlPadDatabase(PadDatabase): ...@@ -205,34 +269,38 @@ class BatlPadDatabase(PadDatabase):
model_ids=None, model_ids=None,
**kwargs): **kwargs):
""" """
This function returns lists of BATLPadFile objects, which fulfill the This function returns lists of BatlPadFile objects, which fulfill the
given restrictions. given restrictions.
Parameters **Parameters:**
----------
protocol : str ``protocol`` : str
The protocol for which the clients should be retrieved. The protocol for which the clients should be retrieved.
The protocol is dependent on your database. The protocol is dependent on your database.
If you do not have protocols defined, just ignore this field. If you do not have protocols defined, just ignore this field.
purposes : :obj:`str` or [:obj:`str`] ``purposes`` : :obj:`str` or [:obj:`str`]
The purposes for which File objects should be retrieved. The purposes for which File objects should be retrieved.
Usually it is either 'real' or 'attack'. Usually it is either 'real' or 'attack'.
model_ids ``model_ids``
This parameter is not supported in PAD databases yet This parameter is not supported in PAD databases yet
**kwargs
Returns **Returns:**
-------
files : [BATLPadFile] ``files`` : [BatlPadFile]
A list of BATLPadFile objects. A list of BATLPadFile objects.
""" """
if protocol is None: if protocol is None:
protocol = self.protocol protocol = self.protocol
if groups is None:
groups = self.high_level_group_names
if purposes is None:
purposes = ['real', 'attack']
protocol, stream_type, max_frames = self.parse_protocol(protocol) protocol, stream_type, max_frames = self.parse_protocol(protocol)
# Convert group names to low-level group names here. # Convert group names to low-level group names here.
...@@ -241,16 +309,43 @@ class BatlPadDatabase(PadDatabase): ...@@ -241,16 +309,43 @@ class BatlPadDatabase(PadDatabase):
# Since this database was designed for PAD experiments, nothing special # Since this database was designed for PAD experiments, nothing special
# needs to be done here. # needs to be done here.
files = self.db.objects(protocol=protocol, groups=groups, purposes=purposes, **kwargs) files = self.db.objects(protocol=protocol,
groups=groups,
purposes=purposes, **kwargs)
files = [BatlPadFile(f, stream_type, max_frames) for f in files] files = [BatlPadFile(f, stream_type, max_frames) for f in files]
return files return files
def annotations(self, f): def annotations(self, f):
"""
Computes annotations for a given file object ``f``, which
is an instance of the ``BatlPadFile`` class.
NOTE: you can pre-compute annotation in your first experiment
and then reuse them in other experiments setting
``self.annotations_temp_dir`` path of this class, where
precomputed annotations will be saved.
**Parameters:**
``f`` : :py:class:`object`
An instance of ``BatlPadFile`` defined above.
**Returns:**
``annotations`` : :py:class:`dict`
A dictionary containing annotations for
each frame in the video.
Dictionary structure:
``annotations = {'1': frame1_dict, '2': frame1_dict, ...}``.
Where
``frameN_dict`` contains coordinates of the
face bounding box and landmarks in frame N.
"""
file_path = os.path.join(self.annotations_temp_dir, f.f.path + ".json") file_path = os.path.join(self.annotations_temp_dir, f.f.path + ".json")
if not os.path.isfile(file_path): # no file with annotations if not os.path.isfile(file_path): # no file with annotations
f.stream_type = "color" f.stream_type = "color"
f.reference_stream_type = "color" f.reference_stream_type = "color"
...@@ -266,13 +361,13 @@ class BatlPadDatabase(PadDatabase): ...@@ -266,13 +361,13 @@ class BatlPadDatabase(PadDatabase):
for idx, image in enumerate(video.as_array()): for idx, image in enumerate(video.as_array()):
frame_annotations = detect_face_landmarks_in_image(image, method = self.landmark_detect_method) frame_annotations = detect_face_landmarks_in_image(image, method=self.landmark_detect_method)
if frame_annotations: if frame_annotations:
annotations[str(idx)] = frame_annotations annotations[str(idx)] = frame_annotations
if self.annotations_temp_dir: # if directory is not an empty string if self.annotations_temp_dir: # if directory is not an empty string
bob.io.base.create_directories_safe(directory=os.path.split(file_path)[0], dryrun=False) bob.io.base.create_directories_safe(directory=os.path.split(file_path)[0], dryrun=False)
...@@ -280,22 +375,14 @@ class BatlPadDatabase(PadDatabase): ...@@ -280,22 +375,14 @@ class BatlPadDatabase(PadDatabase):
json_file.write(json.dumps(annotations)) json_file.write(json.dumps(annotations))
else: # if file with annotations exists load them from file else: # if file with annotations exists load them from file
with open(file_path, 'r') as json_file: with open(file_path, 'r') as json_file:
annotations = json.load(json_file) annotations = json.load(json_file)
if not annotations: # if dictionary is empty if not annotations: # if dictionary is empty
return None return None
return annotations return annotations
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment