#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# Pavel Korshunov <pavel.korshunov@idiap.ch>
# Mon 12 Oct 14:43:22 CEST 2015
"""
Replay attack database implementation of bob.bio.base.database.BioDatabase interface.
It is an extension of an SQL-based database interface, which directly talks to Replay database, for
verification experiments (good to use in bob.bio.base framework).
It also implements a kind of hack so that you can run vulnerability analysis with it.
"""
from .database import FaceBioFile
from bob.bio.base.database import BioDatabase
class ReplayBioFile(FaceBioFile):
"""BioFile implementation for the bob.db.replay database"""
def __init__(self, f):
super(ReplayBioFile, self).__init__(client_id=f.client_id, path=f.path, file_id=f.id)
self._f = f
def load(self, directory=None, extension=None):
video = self._f.load(directory, extension)
# just return the 10th frame.
return video[10]
class ReplayBioDatabase(BioDatabase):
"""
Replay attack database implementation of bob.bio.base.database.BioDatabase interface.
It is an extension of an SQL-based database interface, which directly talks to Replay database, for
verification experiments (good to use in bob.bio.base framework).
It also implements a kind of hack so that you can run vulnerability analysis with it.
"""
__doc__ = __doc__
def __init__(self, **kwargs):
# call base class constructors to open a session to the database
super(ReplayBioDatabase, self).__init__(name='replay', **kwargs)
from bob.db.replay import Database as LowLevelDatabase
self._db = LowLevelDatabase()
self.low_level_group_names = ('train', 'devel', 'test')
self.high_level_group_names = ('world', 'dev', 'eval')
[docs] def protocol_names(self):
"""Returns all registered protocol names
Here I am going to hack and double the number of protocols
with -licit and -spoof. This is done for running vulnerability
analysis"""
names = [p.name + '-licit' for p in self._db.protocols()]
names += [p.name + '-spoof' for p in self._db.protocols()]
return names
[docs] def groups(self):
return self.convert_names_to_highlevel(
self._db.groups(), self.low_level_group_names, self.high_level_group_names)
[docs] def annotations(self, file):
"""Will return the bounding box annotation of 10th frame of the video."""
fn = 10 # 10th frame number
annots = file._f.bbx(directory=self.original_directory)
# bob uses the (y, x) format
topleft = (annots[fn][2], annots[fn][1])
bottomright = (annots[fn][2] + annots[fn][4], annots[fn][1] + annots[fn][3])
annotations = {'topleft': topleft, 'bottomright': bottomright}
return annotations
[docs] def model_ids_with_protocol(self, groups=None, protocol=None, **kwargs):
# since the low-level API does not support verification straight-forward-ly, we improvise.
files = self.objects(groups=groups, protocol=protocol, purposes='enroll', **kwargs)
return sorted(set(f.client_id for f in files))
[docs] def objects(self, groups=None, protocol=None, purposes=None, model_ids=None, **kwargs):
if protocol == '.':
protocol = None
protocol = self.check_parameter_for_validity(protocol, "protocol", self.protocol_names(), 'grandtest-licit')
groups = self.check_parameters_for_validity(groups, "group", self.groups(), self.groups())
purposes = self.check_parameters_for_validity(purposes, "purpose", ('enroll', 'probe'), ('enroll', 'probe'))
purposes = list(purposes)
groups = self.convert_names_to_lowlevel(
groups, self.low_level_group_names, self.high_level_group_names)
# protocol licit is not defined in the low level API
# so do a hack here.
if '-licit' in protocol:
# for licit we return the grandtest protocol
protocol = protocol.replace('-licit', '')
# The low-level API has only "attack", "real", "enroll" and "probe"
# should translate to "real" or "attack" depending on the protocol.
# enroll does not to change.
if 'probe' in purposes:
purposes.remove('probe')
purposes.append('real')
if len(purposes) == 1:
# making the model_ids to None will return all clients which make
# the impostor data also available.
model_ids = None
elif model_ids:
raise NotImplementedError(
'Currently returning both enroll and probe for specific '
'client(s) in the licit protocol is not supported. '
'Please specify one purpose only.')
elif '-spoof' in protocol:
protocol = protocol.replace('-spoof', '')
# you need to replace probe with attack and real for the spoof protocols.
# You can add the real here also to create positives scores also
# but usually you get these scores when you run the licit protocol
if 'probe' in purposes:
purposes.remove('probe')
purposes.append('attack')
# now, query the actual Replay database
objects = self._db.objects(groups=groups, protocol=protocol, cls=purposes, clients=model_ids, **kwargs)
# make sure to return BioFile representation of a file, not the database one
# also make sure you replace client ids with spoof/metatdata1/metadata2/...
retval = []
for f in objects:
if f.is_real():
retval.append(ReplayBioFile(f))
else:
temp = ReplayBioFile(f)
temp.client_id = 'attack'
retval.append(temp)
return retval
[docs] def arrange_by_client(self, files):
client_files = {}
for file in files:
if str(file.client_id) not in client_files:
client_files[str(file.client_id)] = []
client_files[str(file.client_id)].append(file)
files_by_clients = []
for client in sorted(client_files.keys()):
files_by_clients.append(client_files[client])
return files_by_clients