Skip to content

Commit

Permalink
Added bob.db.gbu interface for the GBU database.
Browse files Browse the repository at this point in the history
  • Loading branch information
Manuel Guenther committed May 16, 2012
1 parent c9e9d6f commit effcc86
Show file tree
Hide file tree
Showing 8 changed files with 1,018 additions and 0 deletions.
6 changes: 6 additions & 0 deletions python/db/CMakeLists.txt
Expand Up @@ -47,6 +47,7 @@ bob_setup_db(mobio)
bob_setup_db(multipie)
bob_setup_db(scface)
bob_setup_db(xm2vts)
bob_setup_db(gbu)

# Installs our script driver
bob_python_script(db "bob_dbmanage.py" "lib/script/dbmanage.py" "main")
Expand Down Expand Up @@ -173,6 +174,11 @@ bob_python_add_unittest(db lib/test/atnt.py main)
bob_python_add_test(db-atnt-dumplist bob_dbmanage.py atnt dumplist --self-test)
bob_python_add_test(db-atnt-checkfiles bob_dbmanage.py atnt checkfiles -d "." --self-test)

# GBU database driver tests.
bob_python_add_unittest(db lib/test/gbu.py main)
bob_python_add_test(db-gbu-dumplist bob_dbmanage.py gbu dumplist --self-test)
bob_python_add_test(db-gbu-checkfiles bob_dbmanage.py gbu checkfiles -d "." --self-test)

# Our examples (run and install)
bob_python_example(db iris_lda.py lib/example/iris_lda.py)
bob_python_add_test(db iris_lda.py --self-test)
Expand Down
1 change: 1 addition & 0 deletions python/db/lib/__init__.py
Expand Up @@ -20,6 +20,7 @@
import nuaa
import casia_fasd
import atnt
import gbu


__all__ = dir()
63 changes: 63 additions & 0 deletions python/db/lib/gbu/__init__.py
@@ -0,0 +1,63 @@
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# @author: Manuel Guenther <Manuel.Guenther@idiap.ch>
# @date: Fri Apr 20 12:04:44 CEST 2012
#
# Copyright (C) 2011-2012 Idiap Research Institute, Martigny, Switzerland
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""
The GBU (Good, Bad and Ugly) database consists of parts of the MBGC-v1 image sets.
It defines three protocols, i.e., Good, Bad and Ugly for which different model and probe images are used.
The database provides two different types of protocols:
* In the original protocol (called 'gbu') models are extracted for each file. This means that there may be
several models for the same client.
* The new protocol (called 'multi') provides one **or more** files for each model. Hence, only one model
per client is generated.
There are slight differences between the two protocol types:
1. The amount of models differ, and so the amount of scores does.
2. The model id differs. For 'multi' protocol, model id and client id are the same,
whereas for 'gbu' protocol, model id and file id are identical.
3. Only the results generated by the 'gbu' protocol are comparable to other reported results.
.. note::
To be consistent with other Bob databases, the default protocol type is 'multi'.
When you want to generate results comparable to literature,
you **always** have to specify type='gbu' when you query the database.
.. warning::
**Do never mix 'gbu' and 'multi' protocol types. When you are lucky, you will get an exception,
but also other weird things might happen!**
The three protocols 'Good', 'Bad' and 'Ugly' are provided for both protocol types.
Additionally, there are four different training sets, called 'x1', 'x2', 'x4' and 'x8' with different
numbers of training images (the number of training identities is the same for all training sets).
The GBU protocols do only provide a 'dev' set, but no 'eval' set. The default measurement reported is the ROC curve on the 'dev' set.
"""

def dbname():
"""Calculates my own name automatically."""
import os
return os.path.basename(os.path.dirname(__file__))

from .query import Database
from .commands import add_commands
129 changes: 129 additions & 0 deletions python/db/lib/gbu/commands.py
@@ -0,0 +1,129 @@
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# Laurent El Shafey <laurent.el-shafey@idiap.ch>

"""Commands this database can respond to.
"""

import os
import sys


def dumplist(args):
"""Dumps lists of files based on your criteria"""

from .query import Database
db = Database()

r = db.files(
directory=args.directory,
extension=args.extension,
groups=args.groups,
subworld=args.subworld,
protocol=args.protocol,
purposes=args.purposes)

output = sys.stdout
if args.selftest:
from ..utils import null
output = null()

for id, f in r.items():
output.write('%s\n' % (f,))


def checkfiles(args):
"""Checks existence of files based on your criteria"""

from .query import Database
db = Database()

r = db.files(
directory=args.directory,
extension=args.extension,
groups=args.groups,
subworld=args.subworld,
protocol=args.protocol,
purposes=args.purposes)

# go through all files, check if they are available on the filesystem
good = {}
bad = {}
for id, f in r.items():
if os.path.exists(f): good[id] = f
else: bad[id] = f

# report
output = sys.stdout
if args.selftest:
from ..utils import null
output = null()

if bad:
for id, f in bad.items():
output.write('Cannot find file "%s"\n' % (f,))
output.write('%d files (out of %d) were not found at "%s"\n' % \
(len(bad), len(r), args.directory))


def add_commands(parser):
"""Adds my subset of options and arguments to the top-level parser. For
details on syntax, please consult:
http://docs.python.org/dev/library/argparse.html
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.
"""

from . import dbname
from ..utils import location, standard_commands
from . import __doc__ as dbdoc
from argparse import RawDescriptionHelpFormatter, SUPPRESS

# creates a top-level parser for this database
myname = dbname()
top_level = parser.add_parser(myname,
formatter_class=RawDescriptionHelpFormatter,
help="GBU database", description=dbdoc)
top_level.set_defaults(dbname=myname)
top_level.set_defaults(location=location(myname))

# declare it has subparsers for each of the supported commands
subparsers = top_level.add_subparsers(title="subcommands")

# attach standard commands
standard_commands(subparsers)

# get the "create" action from a submodule
from .create import add_command as create_command
create_command(subparsers)

# get the "dumplist" action from a submodule
dump_list_parser = subparsers.add_parser('dumplist', help=dumplist.__doc__)

dump_list_parser.add_argument('-d', '--directory', help="if given, this path will be prepended to every entry returned (defaults to '%(default)s')")
dump_list_parser.add_argument('-e', '--extension', help="if given, this extension will be appended to every entry returned (defaults to '%(default)s')")
dump_list_parser.add_argument('-g', '--groups', help="if given, this value will limit the output files to those belonging to a particular group. (defaults to '%(default)s')", choices=('world', 'dev', ''))
dump_list_parser.add_argument('-s', '--subworld', help="if given, limits the dump to a particular subset of the data that corresponds to the given protocol (defaults to '%(default)s')", choices=('x1', 'x2', 'x4', 'x8', ''))
dump_list_parser.add_argument('-p', '--protocol', help="if given, limits the dump to a particular subset of the data that corresponds to the given protocol (defaults to '%(default)s')", choices=('Good', 'Bad', 'Ugly'''))
dump_list_parser.add_argument('-u', '--purposes', help="if given, this value will limit the output files to those designed for the given purposes. (defaults to '%(default)s')", choices=('enrol', 'probe', ''))
dump_list_parser.add_argument('--self-test', dest="selftest", default=False,
action='store_true', help=SUPPRESS)

dump_list_parser.set_defaults(func=dumplist) #action

# get the "checkfiles" action from a submodule
check_files_parser = subparsers.add_parser('checkfiles', help=checkfiles.__doc__)

check_files_parser.add_argument('-d', '--directory', help="if given, this path will be prepended to every entry returned (defaults to '%(default)s')")
check_files_parser.add_argument('-e', '--extension', help="if given, this extension will be appended to every entry returned (defaults to '%(default)s')")
check_files_parser.add_argument('-g', '--groups', help="if given, this value will limit the output files to those belonging to a particular group. (defaults to '%(default)s')", choices=('world', 'dev', ''))
check_files_parser.add_argument('-s', '--subworld', help="if given, limits the dump to a particular subset of the data that corresponds to the given protocol (defaults to '%(default)s')", choices=('x1', 'x2', 'x4', 'x8', ''))
check_files_parser.add_argument('-p', '--protocol', help="if given, limits the dump to a particular subset of the data that corresponds to the given protocol (defaults to '%(default)s')", choices=('Good', 'Bad', 'Ugly'''))
check_files_parser.add_argument('-u', '--purposes', help="if given, this value will limit the output files to those designed for the given purposes. (defaults to '%(default)s')", choices=('enrol', 'probe', ''))
check_files_parser.add_argument('--self-test', dest="selftest", default=False,
action='store_true', help=SUPPRESS)

check_files_parser.set_defaults(func=checkfiles) #action

0 comments on commit effcc86

Please sign in to comment.