Source code for bob.db.replay.models

#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# Andre Anjos <andre.dos.anjos@gmail.com>
# Wed 11 May 18:52:38 2011

"""Table models and functionality for the Replay Attack DB.
"""

import os
from sqlalchemy import Table, Column, Integer, String, ForeignKey
from bob.db.base.sqlalchemy_migration import Enum, relationship
import bob.db.base
import bob.db.base.utils
from sqlalchemy.orm import backref
from sqlalchemy.ext.declarative import declarative_base
import numpy
import bob
import bob.io.video


Base = declarative_base()


[docs]class Client(Base): """Database clients, marked by an integer identifier and the set they belong to""" __tablename__ = 'client' set_choices = ('train', 'devel', 'test') """Possible groups to which clients may belong to""" id = Column(Integer, primary_key=True) """Key identifier for clients""" set = Column(Enum(*set_choices)) """Set to which this client belongs to""" def __init__(self, id, set): self.id = id self.set = set def __repr__(self): return "Client('%s', '%s')" % (self.id, self.set)
[docs]class File(Base, bob.db.base.File): """Generic file container""" __tablename__ = 'file' light_choices = ('controlled', 'adverse') """List of illumination conditions for data taking""" id = Column(Integer, primary_key=True) """Key identifier for files""" client_id = Column(Integer, ForeignKey('client.id')) # for SQL """The client identifier to which this file is bound to""" path = Column(String(100), unique=True) """The (unique) path to this file inside the database""" light = Column(Enum(*light_choices)) """The illumination condition in which the data for this file was taken""" # for Python client = relationship(Client, backref=backref('files', order_by=id)) """A direct link to the client object that this file belongs to""" def __init__(self, client, path, light): self.client = client self.path = path self.light = light bob.db.base.File.__init__(path) def __repr__(self): return "File('%s')" % self.path
[docs] def videofile(self, directory=None): """Returns the path to the database video file for this object Keyword parameters: directory An optional directory name that will be prefixed to the returned result. Returns a string containing the video file path. """ return self.make_path(directory, '.mov')
[docs] def facefile(self, directory=None): """Returns the path to the companion face bounding-box file Keyword parameters: directory An optional directory name that will be prefixed to the returned result. Returns a string containing the face file path. """ if not directory: directory = '' directory = os.path.join(directory, 'face-locations') return self.make_path(directory, '.face')
[docs] def bbx(self, directory=None): """Reads the file containing the face locations for the frames in the current video Keyword parameters: directory A directory name that will be prepended to the final filepaths where the face bounding boxes are located, if not on the current directory. Returns: A :py:class:`numpy.ndarray` containing information about the located faces in the videos. Each row of the :py:class:`numpy.ndarray` corresponds for one frame. The five columns of the :py:class:`numpy.ndarray` are (all integers): * Frame number (int) * Bounding box top-left X coordinate (int) * Bounding box top-left Y coordinate (int) * Bounding box width (int) * Bounding box height (int) Note that **not** all the frames may contain detected faces. """ return numpy.loadtxt(self.facefile(directory), dtype=int)
[docs] def is_real(self): """Returns True if this file belongs to a real access, False otherwise""" return bool(self.realaccess)
[docs] def get_realaccess(self): """Returns the real-access object equivalent to this file or raise""" if len(self.realaccess) == 0: raise RuntimeError("%s is not a real-access" % self) return self.realaccess[0]
[docs] def get_attack(self): """Returns the attack object equivalent to this file or raise""" if len(self.attack) == 0: raise RuntimeError("%s is not an attack" % self) return self.attack[0]
[docs] def load(self, directory=None, extension=None): """Loads the data at the specified location and using the given extension. Keyword parameters: data The data blob to be saved (normally a :py:class:`numpy.ndarray`). directory [optional] If not empty or None, this directory is prefixed to the final file destination extension [optional] The extension of the filename - this will control the type of output and the codec for saving the input blob. """ if extension is None: extension = '.mov' vfn = self.make_path(directory, extension) if extension == '.mov': video = bob.io.video.reader(self.make_path(directory, extension)) vin = video.load() else: vin = bob.io.base.load(self.make_path(directory, extension)) return vin #bob.io.base.load(self.make_path(directory, extension))
# Intermediate mapping from RealAccess's to Protocol's realaccesses_protocols = Table('realaccesses_protocols', Base.metadata, Column('realaccess_id', Integer, ForeignKey('realaccess.id')), Column('protocol_id', Integer, ForeignKey('protocol.id')), ) # Intermediate mapping from Attack's to Protocol's attacks_protocols = Table('attacks_protocols', Base.metadata, Column('attack_id', Integer, ForeignKey('attack.id')), Column('protocol_id', Integer, ForeignKey('protocol.id')), )
[docs]class Protocol(Base): """Replay attack protocol""" __tablename__ = 'protocol' id = Column(Integer, primary_key=True) """Unique identifier for the protocol (integer)""" name = Column(String(20), unique=True) """Protocol name""" def __init__(self, name): self.name = name def __repr__(self): return "Protocol('%s')" % (self.name,)
[docs]class RealAccess(Base): """Defines Real-Accesses (licit attempts to authenticate)""" __tablename__ = 'realaccess' purpose_choices = ('authenticate', 'enroll') """Types of purpose for this video""" id = Column(Integer, primary_key=True) """Unique identifier for this real-access object""" file_id = Column(Integer, ForeignKey('file.id')) # for SQL """The file identifier the current real-access is bound to""" purpose = Column(Enum(*purpose_choices)) """The purpose of this video""" take = Column(Integer) """Take number""" # for Python file = relationship(File, backref=backref('realaccess', order_by=id)) """A direct link to the :py:class:`.File` object this real-access belongs to""" protocols = relationship("Protocol", secondary=realaccesses_protocols, backref='realaccesses') """A direct link to the protocols this file is linked to""" def __init__(self, file, purpose, take): self.file = file self.purpose = purpose self.take = take def __repr__(self): return "RealAccess('%s')" % (self.file.path)
[docs]class Attack(Base): """Defines Spoofing Attacks (illicit attempts to authenticate)""" __tablename__ = 'attack' attack_support_choices = ('fixed', 'hand') """Types of attack support""" attack_device_choices = ('print', 'mobile', 'highdef', 'mask') """Types of devices used for spoofing""" sample_type_choices = ('video', 'photo') """Original sample type""" sample_device_choices = ('mobile', 'highdef') """Original sample device""" id = Column(Integer, primary_key=True) """Unique identifier for this attack""" file_id = Column(Integer, ForeignKey('file.id')) # for SQL """The file identifier this attack is linked to""" attack_support = Column(Enum(*attack_support_choices)) """The attack support""" attack_device = Column(Enum(*attack_device_choices)) """The attack device""" sample_type = Column(Enum(*sample_type_choices)) """The attack sample type""" sample_device = Column(Enum(*sample_device_choices)) """The attack sample device""" # for Python file = relationship(File, backref=backref('attack', order_by=id)) """A direct link to the :py:class:`.File` object bound to this attack""" protocols = relationship("Protocol", secondary=attacks_protocols, backref='attacks') """A direct link to the protocols this file is linked to""" def __init__(self, file, attack_support, attack_device, sample_type, sample_device): self.file = file self.attack_support = attack_support self.attack_device = attack_device self.sample_type = sample_type self.sample_device = sample_device def __repr__(self): return "<Attack('%s')>" % (self.file.path)