Commit 30cff2d8 authored by Amir MOHAMMADI's avatar Amir MOHAMMADI

Change the API

parent 86a9144a
Pipeline #45564 failed with stage
in 4 minutes and 22 seconds
from .utils import *
from . import preprocessor
from . import extractor
from . import algorithm
from . import database
from . import test
from .utils import select_frames, VideoAsArray, VideoLikeContainer
from . import annotator
from . import transformer
def get_config():
"""Returns a string containing the configuration information.
"""
"""Returns a string containing the configuration information."""
import bob.extension
return bob.extension.get_config(__name__)
# gets sphinx autodoc done right - don't remove it
def __appropriate__(*args):
"""Says object was actually declared here, and not in the import module.
Fixing sphinx warnings of not being able to find classes, when path is
shortened.
Parameters
----------
*args
An iterable of objects to modify
Resolves `Sphinx referencing issues
<https://github.com/sphinx-doc/sphinx/issues/3048>`
"""
import bob.extension
return bob.extension.get_config(__name__)
for obj in args:
obj.__module__ = __name__
__appropriate__(
VideoAsArray,
VideoLikeContainer,
)
# gets sphinx autodoc done right - don't remove it
__all__ = [_ for _ in dir() if not _.startswith('_')]
__all__ = [_ for _ in dir() if not _.startswith("_")]
This diff is collapsed.
from .Wrapper import Wrapper
# gets sphinx autodoc done right - don't remove it
def __appropriate__(*args):
"""Says object was actually declared here, and not in the import module.
Fixing sphinx warnings of not being able to find classes, when path is shortened.
Parameters:
*args: An iterable of objects to modify
Resolves `Sphinx referencing issues
<https://github.com/sphinx-doc/sphinx/issues/3048>`
"""
for obj in args: obj.__module__ = __name__
__appropriate__(
Wrapper,
)
__all__ = [_ for _ in dir() if not _.startswith('_')]
import collections
import logging
import bob.bio.base
import bob.bio.face
from . import utils
logger = logging.getLogger(__name__)
def normalize_annotations(annotations, validator, max_age=-1):
"""Normalizes the annotations of one video sequence. It fills the
annotations for frames from previous ones if the annotation for the current
frame is not valid.
Parameters
----------
annotations : collections.OrderedDict
A dict of dict where the keys to the first dict are frame indices as
strings (starting from 0). The inside dicts contain annotations for that
frame. The dictionary needs to be an ordered dict in order for this to
work.
validator : ``callable``
Takes a dict (annotations) and returns True if the annotations are valid.
This can be a check based on minimal face size for example: see
:any:`bob.bio.face.annotator.min_face_size_validator`.
max_age : :obj:`int`, optional
An integer indicating for a how many frames a detected face is valid if
no detection occurs after such frame. A value of -1 == forever
Yields
------
str
The index of frame.
dict
The corrected annotations of the frame.
"""
# the annotations for the current frame
current = None
age = 0
for k, annot in annotations.items():
if validator(annot):
current = annot
age = 0
elif max_age < 0 or age < max_age:
age += 1
else: # no detections and age is larger than maximum allowed
current = None
yield k, current
class Base(bob.bio.base.annotator.Annotator):
"""The base class for video annotators.
Parameters
----------
frame_selector : :any:`bob.bio.video.FrameSelector`
A frame selector class to define, which frames of the video to use.
read_original_data : ``callable``
A function with the signature of
``data = read_original_data(biofile, directory, extension)``
that will be used to load the data from biofiles. By default the
``frame_selector`` is used to load the data.
"""
@staticmethod
def frame_ids_and_frames(frames):
"""Takes the frames and yields frame_ids and frames.
Parameters
----------
frames : :any:`bob.bio.video.FrameContainer` or an iterable of arrays
The frames of the video file.
Yields
------
frame_id : str
A string that represents the frame id.
frame : :any:`numpy.array`
The frame of the video file as an array.
"""
if isinstance(frames, utils.FrameContainer):
for fid, fr, _ in frames:
yield fid, fr
else:
for fid, fr in enumerate(frames):
yield str(fid), fr
def annotate(self, frames, **kwargs):
"""Annotates videos.
Parameters
----------
frames : :any:`bob.bio.video.FrameContainer` or :any:`numpy.array`
The frames of the video file.
**kwargs
Extra arguments that annotators may need.
Returns
-------
collections.OrderedDict
A dictionary where its key is the frame id as a string and its value
is a dictionary that are the annotations for that frame.
.. note::
You can use the :any:`Base.frame_ids_and_frames` functions to normalize
the input in your implementation.
"""
raise NotImplementedError()
class FailSafeVideo(Base):
"""A fail-safe video annotator.
It tries several annotators in order and tries the next one if the previous
one fails. However, the difference between this annotator and
:any:`bob.bio.base.annotator.FailSafe` is that this one tries to use
annotations from older frames (if valid) before trying the next annotator.
.. warning::
You must be careful in using this annotator since different annotators
could have different results. For example the bounding box of one
annotator be totally different from another annotator.
Parameters
----------
annotators : :any:`list`
A list of annotators to try.
max_age : int
The maximum number of frames that an annotation is valid for next frames.
This value should be positive. If you want to set max_age to infinite,
then you can use the :any:`bob.bio.video.annotator.Wrapper` instead.
validator : ``callable``
A function that takes the annotations of a frame and validates it.
Please see :any:`Base` for more accepted parameters.
"""
def __init__(
self,
annotators,
max_age=15,
validator=bob.bio.face.annotator.min_face_size_validator,
**kwargs,
):
super().__init__(**kwargs)
assert max_age > 0, "max_age: `{}' cannot be less than 1".format(max_age)
self.annotators = []
for annotator in annotators:
if isinstance(annotator, str):
annotator = bob.bio.base.load_resource(annotator, "annotator")
self.annotators.append(annotator)
self.max_age = max_age
self.validator = validator
def annotate(self, frames, **kwargs):
"""See :any:`Base.annotate`"""
annotations = collections.OrderedDict()
current = None
age = 0
for i, frame in self.frame_ids_and_frames(frames):
for annotator in self.annotators:
annot = annotator.annotate(frame, **kwargs)
if annot and self.validator(annot):
current = annot
age = 0
break
elif age < self.max_age:
age += 1
break
else: # no detections and age is larger than maximum allowed
current = None
if current is not annot:
logger.debug("Annotator `%s' failed.", annotator)
annotations[i] = current
return annotations
class Wrapper(Base):
"""Annotates video files using the provided image annotator.
See the documentation of :any:`Base` too.
Parameters
----------
annotator : :any:`bob.bio.base.annotator.Annotator` or str
The image annotator to be used. The annotator could also be the name of a
bob.bio.annotator resource which will be loaded.
max_age : int
see :any:`normalize_annotations`.
normalize : bool
If True, it will normalize annotations using :any:`normalize_annotations`
validator : object
See :any:`normalize_annotations` and
:any:`bob.bio.face.annotator.min_face_size_validator` for one example.
Please see :any:`Base` for more accepted parameters.
.. warning::
You should only set ``normalize`` to True only if you are annotating
**all** frames of the video file.
"""
def __init__(
self,
annotator,
normalize=False,
validator=bob.bio.face.annotator.min_face_size_validator,
max_age=-1,
**kwargs,
):
super().__init__(**kwargs)
# load annotator configuration
if isinstance(annotator, str):
annotator = bob.bio.base.load_resource(annotator, "annotator")
self.annotator = annotator
self.normalize = normalize
self.validator = validator
self.max_age = max_age
def annotate(self, frames, **kwargs):
"""See :any:`Base.annotate`"""
annotations = collections.OrderedDict()
for i, frame in self.frame_ids_and_frames(frames):
logger.debug("Annotating frame %s", i)
annotations[i] = self.annotator(frame, **kwargs)
if self.normalize:
annotations = collections.OrderedDict(
normalize_annotations(annotations, self.validator, self.max_age)
)
return annotations
import bob.bio.base
from .. import utils
class Base(bob.bio.base.annotator.Annotator):
"""The base class for video annotators.
Parameters
----------
frame_selector : :any:`bob.bio.video.FrameSelector`
A frame selector class to define, which frames of the video to use.
read_original_data : ``callable``
A function with the signature of
``data = read_original_data(biofile, directory, extension)``
that will be used to load the data from biofiles. By default the
``frame_selector`` is used to load the data.
"""
def __init__(self, frame_selector=utils.FrameSelector(selection_style='all'),
read_original_data=None, **kwargs):
def _read_video_data(biofile, directory, extension):
"""Read video data using the frame_selector of this object"""
if hasattr(biofile, 'frames'):
return biofile.frames
return biofile.load(directory, extension, frame_selector)
if read_original_data is None:
read_original_data = _read_video_data
super(Base, self).__init__(read_original_data=read_original_data, **kwargs)
@staticmethod
def frame_ids_and_frames(frames):
"""Takes the frames and yields frame_ids and frames.
Parameters
----------
frames : :any:`bob.bio.video.FrameContainer` or an iterable of arrays
The frames of the video file.
Yields
------
frame_id : str
A string that represents the frame id.
frame : :any:`numpy.array`
The frame of the video file as an array.
"""
if isinstance(frames, utils.FrameContainer):
for fid, fr, _ in frames:
yield fid, fr
else:
for fid, fr in enumerate(frames):
yield str(fid), fr
def annotate(self, frames, **kwargs):
"""Annotates videos.
Parameters
----------
frames : :any:`bob.bio.video.FrameContainer` or :any:`numpy.array`
The frames of the video file.
**kwargs
Extra arguments that annotators may need.
Returns
-------
collections.OrderedDict
A dictionary where its key is the frame id as a string and its value
is a dictionary that are the annotations for that frame.
.. note::
You can use the :any:`Base.frame_ids_and_frames` functions to normalize
the input in your implementation.
"""
raise NotImplementedError()
from . import Base
import bob.bio.face
import collections
import logging
import six
logger = logging.getLogger(__name__)
class FailSafeVideo(Base):
"""A fail-safe video annotator.
It tries several annotators in order and tries the next one if the previous
one fails. However, the difference between this annotator and
:any:`bob.bio.base.annotator.FailSafe` is that this one tries to use
annotations from older frames (if valid) before trying the next annotator.
.. warning::
You must be careful in using this annotator since different annotators
could have different results. For example the bounding box of one
annotator be totally different from another annotator.
Parameters
----------
annotators : :any:`list`
A list of annotators to try.
max_age : int
The maximum number of frames that an annotation is valid for next frames.
This value should be positive. If you want to set max_age to infinite,
then you can use the :any:`bob.bio.video.annotator.Wrapper` instead.
validator : ``callable``
A function that takes the annotations of a frame and validates it.
Please see :any:`Base` for more accepted parameters.
"""
def __init__(self, annotators, max_age=15,
validator=bob.bio.face.annotator.min_face_size_validator,
**kwargs):
super(FailSafeVideo, self).__init__(**kwargs)
assert max_age > 0, "max_age: `{}' cannot be less than 1".format(max_age)
self.annotators = []
for annotator in annotators:
if isinstance(annotator, six.string_types):
annotator = bob.bio.base.load_resource(annotator, 'annotator')
self.annotators.append(annotator)
self.max_age = max_age
self.validator = validator
def annotate(self, frames, **kwargs):
"""See :any:`Base.annotate`
"""
annotations = collections.OrderedDict()
current = None
age = 0
for i, frame in self.frame_ids_and_frames(frames):
for annotator in self.annotators:
annot = annotator.annotate(frame, **kwargs)
if annot and self.validator(annot):
current = annot
age = 0
break
elif age < self.max_age:
age += 1
break
else: # no detections and age is larger than maximum allowed
current = None
if current is not annot:
logger.debug("Annotator `%s' failed.", annotator)
annotations[i] = current
return annotations
import six
import collections
import bob.bio.base
import bob.bio.face
import logging
from . import Base, normalize_annotations
logger = logging.getLogger(__name__)
class Wrapper(Base):
"""Annotates video files using the provided image annotator.
See the documentation of :any:`Base` too.
Parameters
----------
annotator : :any:`bob.bio.base.annotator.Annotator` or str
The image annotator to be used. The annotator could also be the name of a
bob.bio.annotator resource which will be loaded.
max_age : int
see :any:`normalize_annotations`.
normalize : bool
If True, it will normalize annotations using :any:`normalize_annotations`
validator : object
See :any:`normalize_annotations` and
:any:`bob.bio.face.annotator.min_face_size_validator` for one example.
Please see :any:`Base` for more accepted parameters.
.. warning::
You should only set ``normalize`` to True only if you are annotating
**all** frames of the video file.
"""
def __init__(self,
annotator,
normalize=False,
validator=bob.bio.face.annotator.min_face_size_validator,
max_age=-1,
**kwargs
):
super(Wrapper, self).__init__(**kwargs)
self.annotator = annotator
self.normalize = normalize
self.validator = validator
self.max_age = max_age
# load annotator configuration
if isinstance(annotator, six.string_types):
self.annotator = bob.bio.base.load_resource(annotator, "annotator")
def annotate(self, frames, **kwargs):
"""See :any:`Base.annotate`
"""
annotations = collections.OrderedDict()
for i, frame in self.frame_ids_and_frames(frames):
logger.debug("Annotating frame %s", i)
annotations[i] = self.annotator(frame, **kwargs)
if self.normalize:
annotations = collections.OrderedDict(normalize_annotations(
annotations, self.validator, self.max_age))
return annotations
def normalize_annotations(annotations, validator, max_age=-1):
"""Normalizes the annotations of one video sequence. It fills the
annotations for frames from previous ones if the annotation for the current
frame is not valid.
Parameters
----------
annotations : collections.OrderedDict
A dict of dict where the keys to the first dict are frame indices as
strings (starting from 0). The inside dicts contain annotations for that
frame. The dictionary needs to be an ordered dict in order for this to
work.
validator : ``callable``
Takes a dict (annotations) and returns True if the annotations are valid.
This can be a check based on minimal face size for example: see
:any:`bob.bio.face.annotator.min_face_size_validator`.
max_age : :obj:`int`, optional
An integer indicating for a how many frames a detected face is valid if
no detection occurs after such frame. A value of -1 == forever
Yields
------
str
The index of frame.
dict
The corrected annotations of the frame.
"""
# the annotations for the current frame
current = None
age = 0
for k, annot in annotations.items():
if validator(annot):
current = annot
age = 0
elif max_age < 0 or age < max_age:
age += 1
else: # no detections and age is larger than maximum allowed
current = None
yield k, current
# these imports should be here to avoid circular dependencies
from .Base import Base
from .Wrapper import Wrapper
from .FailSafeVideo import FailSafeVideo
# gets sphinx autodoc done right - don't remove it
def __appropriate__(*args):
"""Says object was actually declared here, and not in the import module.
Fixing sphinx warnings of not being able to find classes, when path is
shortened.
Parameters
----------
*args
An iterable of objects to modify
Resolves `Sphinx referencing issues
<https://github.com/sphinx-doc/sphinx/issues/3048>`
"""
for obj in args:
obj.__module__ = __name__
__appropriate__(
Base,
Wrapper,
FailSafeVideo,
)
__all__ = [_ for _ in dir() if not _.startswith('_')]
try:
algorithm
from bob.bio.video.algorithm import Wrapper
algorithm = Wrapper(algorithm)
except NameError as e:
print("This configuration is meant to be used in chain loading of "
"configuration files. Please see the documentation of "
"bob.extension for chain loading.")
raise e
try:
annotator
from bob.bio.video.annotator import Wrapper
annotator = Wrapper(annotator)
except NameError as e:
print("This configuration is meant to be used in chain loading of "
"configuration files. Please see the documentation of "
"bob.extension for chain loading.")
raise e
try:
extractor
from bob.bio.video.extractor import Wrapper
extractor = Wrapper(extractor)
except NameError as e:
print("This configuration is meant to be used in chain loading of "
"configuration files. Please see the documentation of "
"bob.extension for chain loading.")
raise e
try:
preprocessor
from bob.bio.video.preprocessor import Wrapper
preprocessor = Wrapper(preprocessor)
except NameError as e:
print("This configuration is meant to be used in chain loading of "
"configuration files. Please see the documentation of "
"bob.extension for chain loading.")
raise e
try:
preprocessor
from bob.bio.video.preprocessor import Wrapper
preprocessor = Wrapper(preprocessor)
except NameError as e:
pass
try:
extractor
from bob.bio.video.extractor import Wrapper
extractor = Wrapper(extractor)
except NameError as e:
pass
try:
algorithm
from bob.bio.video.algorithm import Wrapper
algorithm = Wrapper(algorithm)
except NameError as e:
pass
try:
annotator
from bob.bio.video.annotator import Wrapper
annotator = Wrapper(annotator)
except NameError as e:
pass
#!/usr/bin/env python
from bob.bio.video.database import MobioBioDatabase
mobio_video_directory = "[YOUR_MOBIO_VIDEO_DIRECTORY]"
database = MobioBioDatabase(
original_directory=mobio_video_directory,
original_extension=".mp4",
protocol='male',
models_depend_on_protocol=True,
all_files_options={'subworld': 'twothirds-subsampled'},
extractor_training_options={'subworld': 'twothirds-subsampled'},
projector_training_options={'subworld': 'twothirds-subsampled'},
enroller_training_options={'subworld': 'twothirds-subsampled'},
)
from bob.bio.video.database import ReplayMobileVideoBioDatabase
database = ReplayMobileVideoBioDatabase(protocol='grandtest-licit')