diff --git a/bob/pad/face/database/maskattack.py b/bob/pad/face/database/maskattack.py deleted file mode 100644 index a4d8daf72faa908428ff902a4bc0ef452abf387e..0000000000000000000000000000000000000000 --- a/bob/pad/face/database/maskattack.py +++ /dev/null @@ -1,238 +0,0 @@ -#!/usr/bin/env python2 -# -*- coding: utf-8 -*- - -import os -import numpy as np -import bob.io.video -from bob.bio.video import FrameSelector, FrameContainer -from bob.pad.face.database import VideoPadFile # Used in MsuMfsdPadFile class -from bob.pad.base.database import PadDatabase - -class MaskAttackPadFile(VideoPadFile): - """ - A high level implementation of the File class for the 3DMAD database. - """ - - def __init__(self, f): - """ - **Parameters:** - - ``f`` : :py:class:`object` - An instance of the File class defined in the low level db interface - of the 3DMAD database, in the bob.db.maskattack.models.py file. - """ - - self.f = f - if f.is_real(): - attack_type = None - else: - attack_type = 'mask' - - super(MaskAttackPadFile, self).__init__( - client_id=f.client_id, - path=f.path, - attack_type=attack_type, - file_id=f.id) - - #========================================================================== - def load(self, directory=None, extension='.avi', frame_selector=FrameSelector(selection_style='all')): - """ - Overridden version of the load method defined in the ``VideoPadFile``. - - **Parameters:** - - ``directory`` : :py:class:`str` - String containing the path to the MSU MFSD database. - Default: None - - ``extension`` : :py:class:`str` - Extension of the video files in the MSU MFSD database. - Note: ``extension`` value is not used in the code of this method. - Default: None - - ``frame_selector`` : ``FrameSelector`` - The frame selector to use. - - **Returns:** - - ``video_data`` : FrameContainer - Video data stored in the FrameContainer, see ``bob.bio.video.utils.FrameContainer`` - for further details. - """ - vfilename = self.make_path(directory, extension) - video = bob.io.video.reader(vfilename) - video_data_array = video.load() - - return frame_selector(video_data_array) - - -#============================================================================== -class MaskAttackPadDatabase(PadDatabase): - """ - A high level implementation of the Database class for the 3DMAD database. - """ - - def __init__( - self, - protocol=None, - original_directory=None, - original_extension='.avi', - **kwargs): - """ - **Parameters:** - - ``protocol`` : :py:class:`str` or ``None`` - The name of the protocol that defines the default experimental setup for this database. - - ``original_directory`` : :py:class:`str` - The directory where the original data of the database are stored. - - ``original_extension`` : :py:class:`str` - The file name extension of the original data. - - ``kwargs`` - The arguments of the :py:class:`bob.bio.base.database.BioDatabase` base class constructor. - """ - - from bob.db.maskattack 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 = ( - 'world', 'dev', - '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(MaskAttackPadDatabase, self).__init__( - name='maskattack', - protocol=protocol, - original_directory=original_directory, - original_extension=original_extension, - **kwargs) - - @property - def original_directory(self): - return self.db.original_directory - - @original_directory.setter - def original_directory(self, value): - self.db.original_directory = value - - #========================================================================== - def objects(self, - groups=None, - protocol=None, - purposes=None, - model_ids=None, - **kwargs): - """ - This function returns lists of MaskAttackPadFile objects, which fulfill the given restrictions. - - Keyword parameters: - - ``groups`` : :py:class:`str` - OR a list of strings. - The groups of which the clients should be returned. - Usually, groups are one or more elements of ('train', 'dev', 'eval') - - ``protocol`` : :py:class:`str` - The protocol for which the clients should be retrieved. - Note: this argument is not used in the code, because ``objects`` method of the - low-level BD interface of the MSU MFSD doesn't have ``protocol`` argument. - - ``purposes`` : :py:class:`str` - OR a list of strings. - The purposes for which File objects should be retrieved. - Usually it is either 'real' or 'attack'. - - ``model_ids`` - This parameter is not supported in PAD databases yet. - - **Returns:** - - ``files`` : [MsuMfsdPadFile] - A list of MsuMfsdPadFile objects. - """ - - # Convert group names to low-level group names here. - groups = self.convert_names_to_lowlevel( - groups, self.low_level_group_names, self.high_level_group_names) - # Since this database was designed for PAD experiments, nothing special - # needs to be done here. - - print("Objects method called with groups = {}, protocol = {}, purposes = {}, model_ids = {}".format(groups, protocol, purposes, model_ids)) - #print("Kwargs -> {}".format(**kwargs)) - #print("Translated groups = {}".frima) - - # for training - - # for dev - - # for eval - lowlevel_purposes = [] - if purposes == 'real': - lowlevel_purposes = ['trainReal', 'probeReal', 'classifyReal'] - else: - lowlevel_purposes = ['trainMask', 'probeMask', 'classifyMask'] - - #if groups == ['world']: - # lowlevel_purposes = ['trainMask'] - # if groups == ['world']: - # lowlevel_purposes = ['trainMask'] - #print(lowlevel_purposes) - files = self.db.objects(sets=groups, purposes=lowlevel_purposes, **kwargs) - - files = [MaskAttackPadFile(f) for f in files] - - return files - - #========================================================================== - def annotations(self, file): - """ - Return annotations for a given file object ``f``, which is an instance - of ``MsuMfsdPadFile`` defined in the HLDI of the MSU MFSD DB. - The ``load()`` method of ``MsuMfsdPadFile`` class (see above) - returns a video, therefore this method returns bounding-box annotations - for each video frame. The annotations are returned as dictionary of dictionaries. - - **Parameters:** - - ``f`` : :py:class:`object` - An instance of ``MsuMfsdPadFile`` defined above. - - **Returns:** - - ``annotations`` : :py:class:`dict` - A dictionary containing the annotations for each frame in the video. - Dictionary structure: ``annotations = {'1': frame1_dict, '2': frame1_dict, ...}``. - Where ``frameN_dict = {'topleft': (row, col), 'bottomright': (row, col)}`` - is the dictionary defining the coordinates of the face bounding box in frame N. - """ - return None - - #annots = f.f.bbx( - # directory=self.original_directory - #) # numpy array containing the face bounding box data for each video frame, returned data format described in the f.bbx() method of the low level interface - - #annotations = {} # dictionary to return - - #for frame_annots in annots: - - # topleft = (np.int(frame_annots[2]), np.int(frame_annots[1])) - # bottomright = (np.int(frame_annots[2] + frame_annots[4]), - # np.int(frame_annots[1] + frame_annots[3])) - - # annotations[str(np.int(frame_annots[0]))] = { - # 'topleft': topleft, - # 'bottomright': bottomright - # } - - #return annotations - - #def model_with_ids_protocol(groups=None, protocol=None): - # pass diff --git a/bob/pad/face/extractor/LTSS.py b/bob/pad/face/extractor/LTSS.py index c1077a8888af2d87088d2d900b1ee5731f49decf..2177e1edfa0417d7c02e0eab8989eb334fcb657f 100644 --- a/bob/pad/face/extractor/LTSS.py +++ b/bob/pad/face/extractor/LTSS.py @@ -54,7 +54,7 @@ class LTSS(Extractor, object): The length of the signal to consider (in seconds) """ - super(LTSS, self).__init__() + super(LTSS, self).__init__(**kwargs) self.framerate = framerate self.nfft = nfft self.debug = debug diff --git a/bob/pad/face/extractor/__init__.py b/bob/pad/face/extractor/__init__.py index 452450f4c8e12a7d295c201e378a35fdac9ef4d0..c5ccd9b4b7fb9ea6ea7776f18e882c7d8e6f8166 100644 --- a/bob/pad/face/extractor/__init__.py +++ b/bob/pad/face/extractor/__init__.py @@ -28,5 +28,8 @@ __appropriate__( LBPHistogram, ImageQualityMeasure, FrameDiffFeatures, + LiFeatures, + LTSS, + PPGSecure, ) __all__ = [_ for _ in dir() if not _.startswith('_')] diff --git a/bob/pad/face/preprocessor/Li.py b/bob/pad/face/preprocessor/LiICPR2016.py similarity index 93% rename from bob/pad/face/preprocessor/Li.py rename to bob/pad/face/preprocessor/LiICPR2016.py index 5f54a1bb5e14b7a690262bb5a4751b29028d6518..38ce33e34baa6f3cc91439ac43d49700742f4cf6 100644 --- a/bob/pad/face/preprocessor/Li.py +++ b/bob/pad/face/preprocessor/LiICPR2016.py @@ -17,10 +17,15 @@ from bob.rppg.cvpr14.filter_utils import detrend from bob.rppg.cvpr14.filter_utils import average -class Li(Preprocessor): +class LiICPR2016(Preprocessor): """Extract pulse signal from a video sequence. - The pulse is extracted according to Li's CVPR 14 algorithm. + The pulse is extracted according to a simplified version of Li's CVPR 14 algorithm. + + It is described in: + X. Li, J, Komulainen, G. Zhao, P-C Yuen and M. Pietikäinen + "Generalized face anti-spoofing by detecting pulse from face videos" + Intl Conf on Pattern Recognition (ICPR), 2016 See the documentation of `bob.rppg.base` @@ -65,7 +70,7 @@ class Li(Preprocessor): Plot some stuff """ - super(Li, self).__init__(**kwargs) + super(LiICPR2016, self).__init__(**kwargs) self.indent = indent self.lambda_ = lambda_ self.window = window diff --git a/bob/pad/face/preprocessor/__init__.py b/bob/pad/face/preprocessor/__init__.py index 651b372cf42308e68357b884b809cedb522e8703..3a0943870fd2f296facfe6271eae7c3048ef83c7 100644 --- a/bob/pad/face/preprocessor/__init__.py +++ b/bob/pad/face/preprocessor/__init__.py @@ -2,7 +2,7 @@ from .FaceCropAlign import FaceCropAlign from .FrameDifference import FrameDifference from .VideoSparseCoding import VideoSparseCoding -from .Li import Li +from .LiICPR2016 import LiICPR2016 from .Chrom import Chrom from .SSR import SSR from .PPGSecure import PPGSecure @@ -29,5 +29,9 @@ __appropriate__( FaceCropAlign, FrameDifference, VideoSparseCoding, + LiICPR2016, + Chrom, + SSR, + PPGSecure, ) __all__ = [_ for _ in dir() if not _.startswith('_')]