diff --git a/bob/bio/vein/config/database/protocol_utfvp/full.py b/bob/bio/vein/config/database/protocol_utfvp/full.py deleted file mode 100644 index 5a94135aa2a32dde74a63a7e2b6548a957d0701e..0000000000000000000000000000000000000000 --- a/bob/bio/vein/config/database/protocol_utfvp/full.py +++ /dev/null @@ -1,26 +0,0 @@ -# author: Yannick Dayer <yannick.dayer@idiap.ch> -# Wed 21 Oct 2020 10:32:56 UTC+02 - -# This is a config file for bob.bio.vein -# It defines the database protocol to use with the Database Interface for the -# utfvp dataset, defined at bob.db.utfvp. - -# It is defined as a resource in the setup file of this package. - -# Usage: -# $ bob bio pipelines vanilla-biometrics <pipeline> full utfvp -# or: -# $ bob bio pipelines vanilla-biometrics -p <pipeline> full utfvp - -# The protocol resource must be specified before the database resource. - - -# Available protocols are (some require the creation of your own config file): -# '1vsall', 'full', 'fullLeftIndex', 'fullLeftMiddle', 'fullLeftRing', -# 'fullRightIndex', 'fullRightMiddle', 'fullRightRing', 'nom', 'nomLeftIndex', -# 'nomLeftMiddle', 'nomLeftRing', 'nomRightIndex', 'nomRightMiddle', -# 'nomRightRing' - - -protocol = 'full' - diff --git a/bob/bio/vein/config/database/protocol_utfvp/nom.py b/bob/bio/vein/config/database/protocol_utfvp/nom.py deleted file mode 100644 index 415379379f8c78f84dedbfec1396865f713db0c6..0000000000000000000000000000000000000000 --- a/bob/bio/vein/config/database/protocol_utfvp/nom.py +++ /dev/null @@ -1,28 +0,0 @@ -# author: Yannick Dayer <yannick.dayer@idiap.ch> -# Wed 21 Oct 2020 10:30:22 UTC+02 - -# This is a config file for bob.bio.vein -# It defines the database protocol to use with the Database Interface for the -# utfvp dataset, defined at bob.db.utfvp. - -# It is defined as a resource in the setup file of this package. - -# Usage: -# $ bob bio pipelines vanilla-biometrics <pipeline> nom utfvp -# or: -# $ bob bio pipelines vanilla-biometrics -p <pipeline> nom utfvp - -# The protocol resource must be specified before the database resource. - - -# Available protocols are (some require the creation of your own config file): -# '1vsall', 'full', 'fullLeftIndex', 'fullLeftMiddle', 'fullLeftRing', -# 'fullRightIndex', 'fullRightMiddle', 'fullRightRing', 'nom', 'nomLeftIndex', -# 'nomLeftMiddle', 'nomLeftRing', 'nomRightIndex', 'nomRightMiddle', -# 'nomRightRing' - - -# This will be the default protocol if none is specified. - -protocol = 'nom' - diff --git a/bob/bio/vein/config/database/protocol_utfvp/one_vs_all.py b/bob/bio/vein/config/database/protocol_utfvp/one_vs_all.py deleted file mode 100644 index d5cc70894a888fb1425bbc502bd607de0df11e0f..0000000000000000000000000000000000000000 --- a/bob/bio/vein/config/database/protocol_utfvp/one_vs_all.py +++ /dev/null @@ -1,26 +0,0 @@ -# author: Yannick Dayer <yannick.dayer@idiap.ch> -# Wed 21 Oct 2020 10:34:41 UTC+02 - -# This is a config file for bob.bio.vein -# It defines the database protocol to use with the Database Interface for the -# utfvp dataset, defined at bob.db.utfvp. - -# It is defined as a resource in the setup file of this package. - -# Usage: -# $ bob bio pipelines vanilla-biometrics <pipeline> 1vsall utfvp -# or: -# $ bob bio pipelines vanilla-biometrics -p <pipeline> 1vsall utfvp - -# The protocol resource must be specified before the database resource. - - -# Available protocols are (some require the creation of your own config file): -# '1vsall', 'full', 'fullLeftIndex', 'fullLeftMiddle', 'fullLeftRing', -# 'fullRightIndex', 'fullRightMiddle', 'fullRightRing', 'nom', 'nomLeftIndex', -# 'nomLeftMiddle', 'nomLeftRing', 'nomRightIndex', 'nomRightMiddle', -# 'nomRightRing' - - -protocol = 'full' - diff --git a/bob/bio/vein/config/database/utfvp.py b/bob/bio/vein/config/database/utfvp.py deleted file mode 100644 index fe3a7c8fc1e93d71417ad30392e56cde60add223..0000000000000000000000000000000000000000 --- a/bob/bio/vein/config/database/utfvp.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python -# vim: set fileencoding=utf-8 : -# Tue 27 Sep 2016 16:47:45 CEST - -"""`UTFVP`_ is a database for biometric fingervein recognition - -The University of Twente Finger Vascular Pattern (UTFVP) Database is made -publically available in order to support and stimulate research efforts in the -area of developing, testing and evaluating algorithms for vascular patter -recognition. The University of Twente, Enschede, The Netherlands (henceforth, -UT) owns copyright of and serves as the source for the UTFVP database, which is -now distributed to any research group approved by the UTFVP principal -investigator. The reference citation is [TV13]_. - -You can download the raw data of the `UTFVP`_ database by following the link. - -.. include:: links.rst -""" - -from bob.extension import rc -from bob.bio.vein.database.utfvp import Database -from bob.bio.base.pipelines.vanilla_biometrics import DatabaseConnector - -import logging - -logger = logging.getLogger("bob.bio.vein") - -_utfvp_directory = rc.get("bob.db.utfvp.directory", "") -"""Value in ``~/.bobrc`` for this dataset directory""" - -# Set default protocol if not given via a config file -if "protocol" not in locals(): - logger.info("protocol not specified, using default: 'nom'") - protocol = "nom" - -legacy_database = Database( - original_directory=_utfvp_directory, original_extension=".png", protocol=protocol, -) -"""The :py:class:`bob.bio.base.database.BioDatabase` derivative with UTFVP settings -""" - -database = DatabaseConnector( - legacy_database, annotation_type=None, fixed_positions=None -) -""" -The database interface wrapped for vanilla-biometrics - -.. warning:: - - This class only provides a programmatic interface to load data in an orderly - manner, respecting usage protocols. It does **not** contain the raw - datafiles. You should procure those yourself. - -Notice that ``original_directory`` is set to ``rc[bob.db.utfvp.directory]``. -You must make sure to set this value with -``bob config set bob.db.utfvp.directory`` to the place where you actually -installed the `utfvp`_ dataset, as explained in the section -:ref:`bob.bio.vein.baselines`. -""" - -logger.debug(f"Loaded database utfvp config file, using protocol '{protocol}'.") diff --git a/bob/bio/vein/config/database/utfvp_1vsall.py b/bob/bio/vein/config/database/utfvp_1vsall.py new file mode 100644 index 0000000000000000000000000000000000000000..bfc8b7fa08f2259aa93f39643891854146637ee9 --- /dev/null +++ b/bob/bio/vein/config/database/utfvp_1vsall.py @@ -0,0 +1,3 @@ +from bob.bio.vein.database.utfvp import UtfvpDatabase + +database = UtfvpDatabase(protocol="1vsall") diff --git a/bob/bio/vein/config/database/utfvp_full.py b/bob/bio/vein/config/database/utfvp_full.py new file mode 100644 index 0000000000000000000000000000000000000000..a8e01a7d77f23e71daa2980bc8ddf8e7f92402f3 --- /dev/null +++ b/bob/bio/vein/config/database/utfvp_full.py @@ -0,0 +1,3 @@ +from bob.bio.vein.database.utfvp import UtfvpDatabase + +database = UtfvpDatabase(protocol="full") diff --git a/bob/bio/vein/config/database/utfvp_nom.py b/bob/bio/vein/config/database/utfvp_nom.py new file mode 100644 index 0000000000000000000000000000000000000000..90a62ac4bd74f1ad075b66024bb0ebf02310afbc --- /dev/null +++ b/bob/bio/vein/config/database/utfvp_nom.py @@ -0,0 +1,3 @@ +from bob.bio.vein.database.utfvp import UtfvpDatabase + +database = UtfvpDatabase(protocol="nom") diff --git a/bob/bio/vein/database/utfvp.py b/bob/bio/vein/database/utfvp.py index 8ed153abbce616ba8e41ab21fd0e7c20aa94046e..2b7552cb3883d9fb545617df766db9e78a9f1c95 100644 --- a/bob/bio/vein/database/utfvp.py +++ b/bob/bio/vein/database/utfvp.py @@ -1,83 +1,56 @@ #!/usr/bin/env python # vim: set fileencoding=utf-8 : -# Tue 27 Sep 2016 16:48:57 CEST +# Victor <vbros@idiap.ch> +""" + Utfvp database implementation +""" -from bob.bio.base.database import BioFile, BioDatabase +from bob.bio.base.database import CSVDataset +from bob.bio.base.database import CSVToSampleLoaderBiometrics +from bob.extension import rc +from bob.extension.download import get_file +import bob.io.image -from . import AnnotatedArray -from ..preprocessor.utils import poly_to_mask - -class File(BioFile): +class UtfvpDatabase(CSVDataset): """ - Implements extra properties of vein files for the UTFVP database - - - Parameters: - - f (object): Low-level file (or sample) object that is kept inside - + The University of Twente Finger Vascular Pattern dataset """ - def __init__(self, f): - - super(File, self).__init__(client_id=f.unique_finger_name, path=f.path, - file_id=f.id) - self.__f = f - - - def load(self, *args, **kwargs): - """(Overrides base method) Loads both image and mask""" - - image = super(File, self).load(*args, **kwargs) - roi = self.__f.roi() - return AnnotatedArray(image, metadata=dict(roi=roi)) - - -class Database(BioDatabase): - """ - Implements verification API for querying UTFVP database. - """ - - def __init__(self, **kwargs): - - super(Database, self).__init__(name='utfvp', **kwargs) - from bob.db.utfvp.query import Database as LowLevelDatabase - self._db = LowLevelDatabase() - - self.low_level_group_names = ('train', 'dev', 'eval') - self.high_level_group_names = ('world', 'dev', 'eval') - - def groups(self): - - return self.convert_names_to_highlevel(self._db.groups(), - self.low_level_group_names, self.high_level_group_names) - - def client_id_from_model_id(self, model_id, group='dev'): - """Required as ``model_id != client_id`` on this database""" - - return self._db.finger_name_from_model_id(model_id) - - - def model_ids_with_protocol(self, groups=None, protocol=None, **kwargs): - - groups = self.convert_names_to_lowlevel(groups, - self.low_level_group_names, self.high_level_group_names) - return self._db.model_ids(groups=groups, protocol=protocol) - - - def objects(self, groups=None, protocol=None, purposes=None, - model_ids=None, **kwargs): - - groups = self.convert_names_to_lowlevel(groups, - self.low_level_group_names, self.high_level_group_names) - retval = self._db.objects(groups=groups, protocol=protocol, - purposes=purposes, model_ids=model_ids, - **kwargs) - - return [File(f) for f in retval] - - - def annotations(self, file): - return None + def __init__(self, protocol): + # Downloading model if not exists + urls = UtfvpDatabase.urls() + filename = get_file( + "utfvp_csv.tar.gz", + urls, + file_hash="0b22a4ea6a78d54879dc3d866a22108b7513d169cd5c1bceb044854a871f200a", + ) + + super().__init__( + name="utfvp", + dataset_protocol_path=filename, + protocol=protocol, + csv_to_sample_loader=CSVToSampleLoaderBiometrics( + data_loader=bob.io.image.load, + dataset_original_directory=rc.get( + "bob.bio.vein.utfvp.directory", "" + ), + extension='', + reference_id_equal_subject_id=False + ), + allow_scoring_with_all_biometric_references=True, + ) + + @staticmethod + def protocols(): + # TODO: Until we have (if we have) a function that dumps the protocols, let's use this one. + return ["nom", "full", "1vsall", + "nomLeftRing", "nomRightRing", "nomLeftMiddle", "nomRightMiddle", "nomLeftIndex", "nomRightIndex", + "fullLeftRing", "fullRightRing", "fullLeftMiddle", "fullRightMiddle", "fullLeftIndex", "fullRightIndex"] + + @staticmethod + def urls(): + return ["https://www.idiap.ch/software/bob/databases/latest/utfvp_csv-0b22a4ea.tar.gz", + "http://www.idiap.ch/software/bob/databases/latest/utfvp_csv-0b22a4ea.tar.gz", + ] diff --git a/bob/bio/vein/tests/test_databases.py b/bob/bio/vein/tests/test_databases.py index d665d2710d2c4a1b8589d9155b546a106b23be27..7e07010412fe80601a8d2085521fe28a371ccaef 100644 --- a/bob/bio/vein/tests/test_databases.py +++ b/bob/bio/vein/tests/test_databases.py @@ -7,27 +7,154 @@ from nose.plugins.skip import SkipTest import bob.bio.base from bob.bio.base.test.utils import db_available from bob.bio.base.test.test_database_implementations import check_database +import os +from bob.extension.download import get_file -@db_available('utfvp') def test_utfvp(): - module = bob.bio.base.load_resource('utfvp', 'config', - preferred_package='bob.bio.vein') + from bob.bio.vein.database.utfvp import UtfvpDatabase + + # Getting the absolute path + urls = UtfvpDatabase.urls() + filename = get_file("utfvp_csv.tar.gz", urls) + + # Removing the file before the test try: - check_database(module.database, protocol='nomLeftIndex', groups=('dev', - 'eval')) - except IOError as e: - raise SkipTest( - "The database could not queried; probably the db.sql3 file is missing. Here is the error: '%s'" % e) + os.remove(filename) + except Exception: + pass + + N_SUBJECTS, N_FINGERS, N_SESSIONS = 60, 6, 4 + # nom + nom_parameters = {'N_train': 10, + 'N_dev': 18, + 'N_eval': 32, + 'N_session': N_SESSIONS // 2, + 'N_session_training': N_SESSIONS, + 'N_fingers': 6, + 'N_fingers_training': 6, + } + # full + full_parameters = {'N_train': 0, + 'N_dev': N_SUBJECTS, + 'N_eval': 0, + 'N_session': N_SESSIONS, + 'N_fingers': 6, + } + + # 1vsall + onevsall_parameters = {'N_train': 35, + 'N_dev': 65, + 'N_eval': 0, + 'N_session': N_SESSIONS, + 'N_session_training': N_SESSIONS, + 'N_fingers': 5, + 'N_fingers_training': 1, + } + # subnom + subnom_parameters = {'N_train': 10, + 'N_dev': 18, + 'N_eval': 32, + 'N_session': N_SESSIONS // 2, + 'N_session_training': N_SESSIONS, + 'N_fingers': 1, + 'N_fingers_training': 1, + } + + # subfull + subfull_parameters = {'N_train': 0, + 'N_dev': N_SUBJECTS, + 'N_eval': 0, + 'N_session': N_SESSIONS, + 'N_fingers': 1, + } + + protocols_parameters = {'nom': nom_parameters, + 'full': full_parameters, + '1vsall': onevsall_parameters, + 'subnom': subnom_parameters, + 'subfull': subfull_parameters, + } + + def _check_protocol(p, parameters, train=False, eval=False): + database = UtfvpDatabase(protocol=p) + + if train: + assert len(database.background_model_samples()) == \ + parameters['N_train'] * parameters['N_fingers_training'] * parameters['N_session_training'] + + assert len(database.references(group="dev")) == \ + parameters['N_dev'] * parameters['N_fingers'] * parameters['N_session'] + assert len(database.probes(group="dev")) == \ + parameters['N_dev'] * parameters['N_fingers'] * parameters['N_session'] + + if eval: + assert len(database.references(group="eval")) == \ + parameters['N_eval'] * parameters['N_fingers'] * parameters['N_session'] + assert len(database.probes(group="eval")) == \ + parameters['N_eval'] * parameters['N_fingers'] * parameters['N_session'] + + return p + + checked_protocols = [] + + checked_protocols.append( + _check_protocol("nom", protocols_parameters['nom'], train=True, eval=True) + ) + checked_protocols.append( + _check_protocol("full", protocols_parameters['full'], train=False, eval=False) + ) + checked_protocols.append( + _check_protocol("1vsall", protocols_parameters['1vsall'], train=True, eval=False) + ) + checked_protocols.append( + _check_protocol("nomLeftIndex", protocols_parameters['subnom'], train=True, eval=True) + ) + checked_protocols.append( + _check_protocol("nomLeftMiddle", protocols_parameters['subnom'], train=True, eval=True) + ) + checked_protocols.append( + _check_protocol("nomLeftRing", protocols_parameters['subnom'], train=True, eval=True) + ) + checked_protocols.append( + _check_protocol("nomRightIndex", protocols_parameters['subnom'], train=True, eval=True) + ) + checked_protocols.append( + _check_protocol("nomRightMiddle", protocols_parameters['subnom'], train=True, eval=True) + ) + checked_protocols.append( + _check_protocol("nomRightRing", protocols_parameters['subnom'], train=True, eval=True) + ) + checked_protocols.append( + _check_protocol("fullLeftIndex", protocols_parameters['subfull'], train=False, eval=False) + ) + checked_protocols.append( + _check_protocol("fullLeftMiddle", protocols_parameters['subfull'], train=False, eval=False) + ) + checked_protocols.append( + _check_protocol("fullLeftRing", protocols_parameters['subfull'], train=False, eval=False) + ) + checked_protocols.append( + _check_protocol("fullRightIndex", protocols_parameters['subfull'], train=False, eval=False) + ) + checked_protocols.append( + _check_protocol("fullRightMiddle", protocols_parameters['subfull'], train=False, eval=False) + ) + checked_protocols.append( + _check_protocol("fullRightRing", protocols_parameters['subfull'], train=False, eval=False) + ) + + for p in UtfvpDatabase.protocols(): + assert p in checked_protocols, "Protocol {} untested".format(p) @db_available('verafinger') def test_verafinger(): module = bob.bio.base.load_resource('verafinger', 'config', - preferred_package='bob.bio.vein') + preferred_package='bob.bio.vein') try: check_database(module.database, protocol='Fifty', groups=('dev', - 'eval')) + 'eval')) except IOError as e: raise SkipTest( "The database could not queried; probably the db.sql3 file is missing. Here is the error: '%s'" % e) @@ -36,7 +163,7 @@ def test_verafinger(): @db_available('fv3d') def test_fv3d(): module = bob.bio.base.load_resource('fv3d', 'config', - preferred_package='bob.bio.vein') + preferred_package='bob.bio.vein') try: check_database(module.database, protocol='central', groups=('dev',)) except IOError as e: @@ -47,7 +174,7 @@ def test_fv3d(): @db_available('putvein') def test_putvein(): module = bob.bio.base.load_resource('putvein', 'config', - preferred_package='bob.bio.vein') + preferred_package='bob.bio.vein') try: check_database(module.database, protocol='wrist-LR_1', groups=('dev',)) except IOError as e: diff --git a/setup.py b/setup.py index fbbe5a436ac65f84cedbffc656f40a2860e7bd45..a31d06f586a5c933b6dfc705a8316cadd1c73475 100644 --- a/setup.py +++ b/setup.py @@ -32,9 +32,9 @@ setup( "Full = bob.bio.vein.config.database.protocol_verafinger.full", "Cropped-Full = bob.bio.vein.config.database.protocol_verafinger.cropped_full", # utfvp - "nom = bob.bio.vein.config.database.protocol_utfvp.nom", - "full = bob.bio.vein.config.database.protocol_utfvp.full", - "1vsall = bob.bio.vein.config.database.protocol_utfvp.one_vs_all", + "nom = bob.bio.vein.config.database.utfvp_nom", + "full = bob.bio.vein.config.database.utfvp_full", + "1vsall = bob.bio.vein.config.database.utfvp_1vsall", # fv3d "central = bob.bio.vein.config.database.protocol_fv3d.central", "left = bob.bio.vein.config.database.protocol_fv3d.left", @@ -47,7 +47,6 @@ setup( "palm-LR-4 = bob.bio.vein.config.database.protocol_putvein.palm_lr_4", # legacy databases "verafinger = bob.bio.vein.config.database.verafinger", - "utfvp = bob.bio.vein.config.database.utfvp", "fv3d = bob.bio.vein.config.database.fv3d", "putvein = bob.bio.vein.config.database.putvein", # legacy baselines @@ -57,7 +56,7 @@ setup( ], "bob.bio.database": [ "verafinger = bob.bio.vein.config.database.verafinger:database", - "utfvp = bob.bio.vein.config.database.utfvp:database", + "utfvp = bob.bio.vein.config.database.utfvp_nom:database", "fv3d = bob.bio.vein.config.database.fv3d:database", "putvein = bob.bio.vein.config.database.putvein:database", ],