diff --git a/replay/db/__init__.py b/replay/db/__init__.py index 2326238e5173ade3fb077bcb30b6cd2a55796641..968e881ee714dd5b2d348bfbf2381eed37c615a3 100644 --- a/replay/db/__init__.py +++ b/replay/db/__init__.py @@ -3,47 +3,23 @@ # Andre Anjos <andre.dos.anjos@gmail.com> # Wed 18 May 09:28:44 2011 -"""The Idiap Replay attack database consists of Photo and Video attacks to -different identities under different illumination conditions. +"""The Replay-Attack Database for face spoofing consists of 1300 video clips of +photo and video attack attempts to 50 clients, under different lighting +conditions. This Database was produced at the Idiap Research Institute, in +Switzerland. + +If you use this database in your publication, please cite the following paper +on your references: + + @INPROCEEDINGS{Chingovska_BIOSIG-2012, + author = {Chingovska, Ivana and Anjos, Andr{\'{e}} and Marcel, S{\'{e}}bastien}, + keywords = {biometric, Counter-Measures, Local Binary Patterns, Spoofing Attacks}, + month = september, + title = {On the Effectiveness of Local Binary Patterns in Face Anti-spoofing}, + journal = {IEEE BIOSIG 2012}, + year = {2012}, + } """ -import os - -def dbname(): - '''Returns the database name''' - - return 'replay' - -def version(): - '''Returns the current version number defined in setup.py (DRY)''' - - import pkg_resources # part of setuptools - return pkg_resources.require('bob.db.%s' % dbname())[0].version - -def location(): - '''Returns the directory that contains the data''' - - return os.path.dirname(os.path.realpath(__file__)) - -def files(): - '''Returns a python iterable with all auxiliary files needed''' - - return ('db.sql3',) - -def type(): - '''Returns the type of auxiliary files you have for this database - - If you return 'sqlite', then we append special actions such as 'dbshell' - on 'bob_dbmanage.py' automatically for you. Otherwise, we don't. - - If you use auxiliary text files, just return 'text'. We may provide - special services for those types in the future. - ''' - - return 'sqlite' - -# these are required for the dbmanage.py driver from .query import Database -from .commands import add_commands - -__all__ = ['Database',] +__all__ = dir() diff --git a/replay/db/commands.py b/replay/db/driver.py similarity index 56% rename from replay/db/commands.py rename to replay/db/driver.py index 17f81212119fb8de036fb40ccebdd41491b398be..8e1b5af668ba57448fca321281517e44772578a4 100644 --- a/replay/db/commands.py +++ b/replay/db/driver.py @@ -1,13 +1,14 @@ #!/usr/bin/env python # vim: set fileencoding=utf-8 : -# Andre Anjos <andre.anjos@idiap.ch> -# Tue 28 Jun 2011 15:20:09 CEST +# Andre Anjos <andre.dos.anjos@gmail.com> +# Wed 15 Aug 11:26:11 2012 -"""Commands this database can respond to. +"""Bob Database Driver entry-point for the Replay Attack Database """ import os import sys +from bob.db.driver import Interface as BaseInterface def reverse(args): """Returns a list of file database identifiers given the path stems""" @@ -73,53 +74,45 @@ def path_command(subparsers): parser.set_defaults(func=path) #action -def add_commands(parser): - """Adds my subset of options and arguments to the top-level parser. For - details on syntax, please consult: +class Interface(BaseInterface): - http://docs.python.org/dev/library/argparse.html + def name(self): + return 'replay' - The strategy assumed here is that each command will have its own set of - options that are relevant to that command. So, we just scan such commands and - attach the options from those. - """ + def version(self): + import pkg_resources # part of setuptools + return pkg_resources.require('bob.db.%s' % self.name())[0].version - from . import dbname, location, version, type, files - from bob.db.utils import standard_commands - from . import __doc__ as dbdoc - from argparse import RawDescriptionHelpFormatter + def location(self): + return os.path.dirname(os.path.realpath(__file__)) - # creates a top-level parser for this database - myname = dbname() - top_level = parser.add_parser(myname, - formatter_class=RawDescriptionHelpFormatter, - help="Photo/Video Replay attack database", description=dbdoc) - top_level.set_defaults(dbname=myname) - top_level.set_defaults(location=location()) - top_level.set_defaults(version=version()) - top_level.set_defaults(type=type()) - top_level.set_defaults(files=files()) + def files(self): + return ('db.sql3',) - # declare it has subparsers for each of the supported commands - subparsers = top_level.add_subparsers(title="subcommands") + def type(self): + return 'sqlite' - # attach standard commands - standard_commands(subparsers, type(), files()) + def add_commands(self, parser): - # get the "create" action from a submodule - from .create import add_command as create_command - create_command(subparsers) + from . import __doc__ as docs + + subparsers = self.setup_parser(parser, + "Photo/Video Replay attack database", docs) - # get the "dumplist" action from a submodule - from .dumplist import add_command as dumplist_command - dumplist_command(subparsers) + # get the "create" action from a submodule + from .create import add_command as create_command + create_command(subparsers) - # get the "checkfiles" action from a submodule - from .checkfiles import add_command as checkfiles_command - checkfiles_command(subparsers) + # get the "dumplist" action from a submodule + from .dumplist import add_command as dumplist_command + dumplist_command(subparsers) - # adds the "reverse" command - reverse_command(subparsers) + # get the "checkfiles" action from a submodule + from .checkfiles import add_command as checkfiles_command + checkfiles_command(subparsers) - # adds the "path" command - path_command(subparsers) + # adds the "reverse" command + reverse_command(subparsers) + + # adds the "path" command + path_command(subparsers) diff --git a/replay/db/query.py b/replay/db/query.py index 3d7c4e2208c4af4a9880175d3e5e82fdf047969f..4d0ceb8401209eb58e39eac3fb80a2f533e5fbb7 100644 --- a/replay/db/query.py +++ b/replay/db/query.py @@ -11,9 +11,11 @@ import os import logging from bob.db import utils from .models import * -from . import dbname, type, location, files +from .driver import Interface -SQLITE_FILE = os.path.join(location(), files()[0]) +INFO = Interface() + +SQLITE_FILE = os.path.join(INFO.location(), INFO.files()[0]) class Database(object): """The dataset class opens and maintains a connection opened to the Database. @@ -32,7 +34,7 @@ class Database(object): self.session = None else: - self.session = utils.session(type(), location(), files()[0]) + self.session = utils.session(type(), INFO.location(), files()[0]) def is_valid(self): """Returns if a valid session has been opened for reading the database""" @@ -87,7 +89,7 @@ class Database(object): """ if not self.is_valid(): - raise RuntimeError, "Database '%s' cannot be found at expected location '%s'. Create it and then try re-connecting using Database.connect()" % (dbname(), SQLITE_FILE) + raise RuntimeError, "Database '%s' cannot be found at expected location '%s'. Create it and then try re-connecting using Database.connect()" % (INFO.name(), SQLITE_FILE) def check_validity(l, obj, valid, default): """Checks validity of user input data against a set of valid values""" @@ -157,7 +159,7 @@ class Database(object): """Returns the names of all registered protocols""" if not self.is_valid(): - raise RuntimeError, "Database '%s' cannot be found at expected location '%s'. Create it and then try re-connecting using Database.connect()" % (dbname(), SQLITE_FILE) + raise RuntimeError, "Database '%s' cannot be found at expected location '%s'. Create it and then try re-connecting using Database.connect()" % (INFO.name(), SQLITE_FILE) return tuple([k.name for k in self.session.query(Protocol)]) @@ -165,7 +167,7 @@ class Database(object): """Tells if a certain protocol is available""" if not self.is_valid(): - raise RuntimeError, "Database '%s' cannot be found at expected location '%s'. Create it and then try re-connecting using Database.connect()" % (dbname(), SQLITE_FILE) + raise RuntimeError, "Database '%s' cannot be found at expected location '%s'. Create it and then try re-connecting using Database.connect()" % (INFO.name(), SQLITE_FILE) return self.session.query(Protocol).filter(Protocol.name==name).count() != 0 @@ -174,7 +176,7 @@ class Database(object): an error if that does not exist.""" if not self.is_valid(): - raise RuntimeError, "Database '%s' cannot be found at expected location '%s'. Create it and then try re-connecting using Database.connect()" % (dbname(), SQLITE_FILE) + raise RuntimeError, "Database '%s' cannot be found at expected location '%s'. Create it and then try re-connecting using Database.connect()" % (INFO.name(), SQLITE_FILE) return self.session.query(Protocol).filter(Protocol.name==name).one() @@ -224,7 +226,7 @@ class Database(object): """ if not self.is_valid(): - raise RuntimeError, "Database '%s' cannot be found at expected location '%s'. Create it and then try re-connecting using Database.connect()" % (dbname(), SQLITE_FILE) + raise RuntimeError, "Database '%s' cannot be found at expected location '%s'. Create it and then try re-connecting using Database.connect()" % (INFO.name(), SQLITE_FILE) fobj = self.session.query(File).filter(File.id.in_(ids)) retval = [] @@ -246,7 +248,7 @@ class Database(object): """ if not self.is_valid(): - raise RuntimeError, "Database '%s' cannot be found at expected location '%s'. Create it and then try re-connecting using Database.connect()" % (dbname(), SQLITE_FILE) + raise RuntimeError, "Database '%s' cannot be found at expected location '%s'. Create it and then try re-connecting using Database.connect()" % (INFO.name(), SQLITE_FILE) fobj = self.session.query(File).filter(File.path.in_(paths)) retval = [] @@ -278,7 +280,7 @@ class Database(object): """ if not self.is_valid(): - raise RuntimeError, "Database '%s' cannot be found at expected location '%s'. Create it and then try re-connecting using Database.connect()" % (dbname(), SQLITE_FILE) + raise RuntimeError, "Database '%s' cannot be found at expected location '%s'. Create it and then try re-connecting using Database.connect()" % (INFO.name(), SQLITE_FILE) from bob.io import save