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

Added documentation to BATL HLDI classes

parent 3dafc0c0
......@@ -6,8 +6,6 @@ from bob.pad.base.database import PadDatabase, PadFile
from bob.bio.video import FrameSelector
from bob.extension import rc
import pkg_resources
from bob.pad.face.preprocessor.FaceCropAlign import detect_face_landmarks_in_image
import json
......@@ -16,6 +14,7 @@ import os
import bob.io.base
class BatlPadFile(PadFile):
"""
A high level implementation of the File class for the BATL
......@@ -32,17 +31,48 @@ class BatlPadFile(PadFile):
video_data_only=True):
"""
Parameters
----------
f : object
**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.
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 = BATL_CONFIG[f.type_id]
# attack_type = '{} : {}'.format(attack['name'], attack['pai'][f.pai_id])
attack_type = 'attack'
else:
attack_type = None
......@@ -59,23 +89,46 @@ class BatlPadFile(PadFile):
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 # 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,
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,
warp_to_reference=self.warp_to_reference,
convert_to_rgb=self.convert_to_rgb,
crop=self.crop,
max_frames=self.max_frames)
for modality in data.keys():
if modality != 'rppg':
data[modality] = frame_selector(data[modality])
for meta_data in data.keys():
if meta_data != 'rppg':
data[meta_data] = frame_selector(data[meta_data])
if self.video_data_only:
......@@ -92,7 +145,6 @@ class BatlPadDatabase(PadDatabase):
def __init__(
self,
# nowig is the selected default protocol
protocol='nowig',
original_directory=rc['bob.db.batl.directory'],
original_extension='.h5',
......@@ -100,26 +152,38 @@ class BatlPadDatabase(PadDatabase):
landmark_detect_method="mtcnn",
**kwargs):
"""
Parameters
----------
**Parameters:**
protocol : str or None
``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-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
``original_directory`` : str
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.
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`
base class constructor.
"""
......@@ -205,34 +269,38 @@ class BatlPadDatabase(PadDatabase):
model_ids=None,
**kwargs):
"""
This function returns lists of BATLPadFile objects, which fulfill the
This function returns lists of BatlPadFile objects, which fulfill the
given restrictions.
Parameters
----------
protocol : str
**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`]
``purposes`` : :obj:`str` or [:obj:`str`]
The purposes for which File objects should be retrieved.
Usually it is either 'real' or 'attack'.
model_ids
``model_ids``
This parameter is not supported in PAD databases yet
**kwargs
Returns
-------
files : [BATLPadFile]
**Returns:**
``files`` : [BatlPadFile]
A list of BATLPadFile objects.
"""
if protocol is None:
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)
# Convert group names to low-level group names here.
......@@ -241,16 +309,43 @@ class BatlPadDatabase(PadDatabase):
# Since this database was designed for PAD experiments, nothing special
# 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]
return files
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")
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.reference_stream_type = "color"
......@@ -266,13 +361,13 @@ class BatlPadDatabase(PadDatabase):
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:
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)
......@@ -280,22 +375,14 @@ class BatlPadDatabase(PadDatabase):
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:
annotations = json.load(json_file)
if not annotations: # if dictionary is empty
if not annotations: # if dictionary is empty
return None
return annotations
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment