diff --git a/bob/bio/vein/config/database/verafinger_contactless_nom.py b/bob/bio/vein/config/database/verafinger_contactless_nom.py new file mode 100644 index 0000000000000000000000000000000000000000..89fc5ffcc117d63e5e2d28c5de78702ae9b3b0c2 --- /dev/null +++ b/bob/bio/vein/config/database/verafinger_contactless_nom.py @@ -0,0 +1,3 @@ +from bob.bio.vein.database.verafinger_contactless import VerafingerContactless + +database = VerafingerContactless(protocol="nom") diff --git a/bob/bio/vein/database/utfvp.py b/bob/bio/vein/database/utfvp.py index 2b7552cb3883d9fb545617df766db9e78a9f1c95..9b601d004a1d7bd155b45ee267cd544b0be6d59b 100644 --- a/bob/bio/vein/database/utfvp.py +++ b/bob/bio/vein/database/utfvp.py @@ -16,6 +16,122 @@ import bob.io.image class UtfvpDatabase(CSVDataset): """ The University of Twente Finger Vascular Pattern dataset + + .. warning:: + + To use this dataset protocol, you need to have the original files of the UTFVP dataset. + Once you have it downloaded, please run the following command to set the path for Bob + + .. code-block:: sh + + bob config set bob.bio.vein.utfvp.directory [DATABASE PATH] + + The fingervein image database consists of 1440 images taken in 2 distinct + session in two days (May 9th, 2012 and May 23rd, 2012) using a custom built + fingervein sensor. In each session, each of the 60 subjects in the dataset were + asked to present 6 fingers to the sensor twice, making up separate tries. The + six fingers are the left and right ring, middle and index fingers. Therefore, + the database contains 60x6 = 360 unique fingers. + + Files in the database have a strict naming convention and are organized in + directories following their subject identifier like so: + ``0003/0003_5_2_120509-141536``. The fields can be interpreted as + ``<subject-id>/<subject-id>_<finger-name>_<trial>_<date>-<hour>``. The subject + identifier is written as a 4-digit number with leading zeroes, varying from 1 + to 60. The finger name is one of the following: + + * **1**: Left ring + * **2**: Left middle + * **3**: Left index + * **4**: Right index + * **5**: Right middle + * **6**: Right ring + + The trial identifiers can vary between 1 and 4. The first two tries were + captured during the first session while the last two, on the second session. + Given the difference in the images between trials on the same day, we assume + users were asked to remove the finger from the device and re-position it + afterwards. + + **Protocols** + + There are 15 protocols implemented in this package: + + * 1vsall + * nom + * nomLeftRing + * nomLeftMiddle + * nomLeftIndex + * nomRightIndex + * nomRightMiddle + * nomRightRing + * full + * fullLeftRing + * fullLeftMiddle + * fullLeftIndex + * fullRightIndex + * fullRightMiddle + * fullRightRing + + **"nom" Protocols** + + "nom" means "normal operation mode". In this set of protocols, images from + different clients are separated in different sets that can be used for system + training, validation and evaluation: + + * Fingers from clients in the range [1, 10] are used on the training set + * Fingers from clients in the range [11, 28] are used on the development (or validation) set + * Fingers from clients in the range [29, 60] are used in the evaluation (or test) set + + Data from the first session (both trials) can be used for enrolling the finger + while data on the last session (both trials) should be used exclusively for + probing the finger. In the way setup by this database interface, each of the + samples is returned as a separate enrollment model. If a single score per + finger is required, the user must manipulate the final score listings and fuse + results themselves. + + Matching happens exhaustively between all probes and models. The variants named + "nomLeftRing", for example, contain the data filtered by finger name as per the + listings above. For example, "Left Ring" means all files named + ``*/*_1_*_*-*.png``. Therefore, the equivalent protocol contains only 1/6 of + the files of its complete ``nom`` version. + + + **"full" Protocols** + + + "full" protocols are meant to match current practices in fingervein reporting + in which most published material don't use a separate evaluation set. All data + is placed on the development (or validation) set. In these protocols, all + images are used both for enrolling and probing for fingers. It is, of course, + a biased setup. Matching happens exhaustively between all samples in the + development set. + + + The variants named "fullLeftRing", for example, contain the data filtered by + finger name as per the listings above. For example, "Left Ring" means all files + named ``*/*_1_*_*-*.png``. Therefore, the equivalent protocol contains only 1/6 + of the files of its complete ``full`` version. + + + **"1vsall" Protocol** + + The "1vsall" protocol is meant as a cross-validation protocol. All data from + the dataset is split into training and development (or validation). No samples + are allocated for a separate evaluation (or test) set. The training set is + composed of all samples of fingers ``0001_1`` (left ring finger of subject 1), + ``0002_2`` (left middle finger of subject 2), ``0003_3`` (left index finger of + subject 3), ``0004_4`` (right index finger of subject 4), ``0005_5`` (right + middle finger of subject 5), ``0006_6`` (right ring finger of subject 6), + ``0007_1`` (left ring finger of subject 7), ``0008_2`` (left middle finger of + subject 8) and so on, until subject 35 (inclusive). There are 140 images in + total on this set. + + All other 1300 samples from the dataset are used as a development (or + validation) set. Each sample generates a single model and is used as a probe + for all other models. Matching happens exhaustively, but with the same image + that generated the model being matched. So, there are 1299 probes per model. + """ def __init__(self, protocol): diff --git a/bob/bio/vein/database/verafinger_contactless.py b/bob/bio/vein/database/verafinger_contactless.py new file mode 100644 index 0000000000000000000000000000000000000000..b3d7ae65428c38ddc4e02c9d1d2c85c05aab0438 --- /dev/null +++ b/bob/bio/vein/database/verafinger_contactless.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python +# vim: set fileencoding=utf-8 : +# Victor <vbros@idiap.ch> + +""" + VERA-Fingervein-Contactless database implementation +""" + +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 + + +class VerafingerContactless(CSVDataset): + """ + The VERA Fingervein Contactless database contains 1330 finger vein images of 133 persons, + with id ranging from 1 to 137 (with 4 defects). + Both hands of the subjects have been imaged over 5 different sessions, with a total of 10 images per person. + The sensor is described in `this paper <https://ieeexplore.ieee.org/abstract/document/7314596>`_. + + .. warning:: + + To use this dataset protocol, you need to have the original files of the VERA Fingervein Contactless dataset. + Once you have it downloaded, please run the following command to set the path for Bob + + .. code-block:: sh + + bob config set bob.bio.vein.verafinger_contactless.directory [DATABASE PATH] + + + **Metadata** + + Associated to each sample, you may find the metadata configuration for each capture : + + * EXPOSURE : exposure time (in ms) + * ORTHOLED : Power of the ORTHOLED (in % of the max power) + * CENTERLED : Power of the CENTERLED (in % of the max power) + * CROSSLED : Power of the CROSSLED (in % of the max power) + + + **Protocols** + + **NOM (Normal Operation Mode) protocol** + + * Development set : Even subject ids + * Evaluation set : Odd subject ids + * Enrolled : session 1 & 2 + * Probes : session 3, 4 &5 + + """ + + def __init__(self, protocol): + urls = VerafingerContactless.urls() + filename = get_file( + "verafinger_contactless.tar.gz", + urls, + file_hash="c664a83b8fcba3396b010c4d3e60e425e14b32111c4b955892072e5d687485bd", + ) + + super().__init__( + name="verafinger_contactless", + 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.verafinger_contactless.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"] + + @staticmethod + def urls(): + return ["https://www.idiap.ch/software/bob/databases/latest/verafinger_contactless-c664a83b.tar.gz", + "http://www.idiap.ch/software/bob/databases/latest/verafinger_contactless-c664a83b.tar.gz", + ] diff --git a/bob/bio/vein/tests/test_databases.py b/bob/bio/vein/tests/test_databases.py index 7e07010412fe80601a8d2085521fe28a371ccaef..a16755c7c2d946bd087bfdf88a0ed4c85bce8464 100644 --- a/bob/bio/vein/tests/test_databases.py +++ b/bob/bio/vein/tests/test_databases.py @@ -11,6 +11,56 @@ import os from bob.extension.download import get_file +def test_verafinger_contactless(): + from bob.bio.vein.database.verafinger_contactless import VerafingerContactless + + # Getting the absolute path + urls = VerafingerContactless.urls() + filename = get_file("verafinger_contactless.tar.gz", urls) + + # Removing the file before the test + try: + os.remove(filename) + except Exception: + pass + + # nom + nom_parameters = {'N_dev': 65, + 'N_eval': 68, + 'N_session_references': 2, + 'N_session_probes': 3, + 'N_hands': 2, + } + + protocols_parameters = {'nom': nom_parameters, + } + + def _check_protocol(p, parameters, eval=False): + database = VerafingerContactless(protocol=p) + + assert len(database.references(group="dev")) == \ + parameters['N_dev'] * parameters['N_hands'] * parameters['N_session_references'] + assert len(database.probes(group="dev")) == \ + parameters['N_dev'] * parameters['N_hands'] * parameters['N_session_probes'] + + if eval: + assert len(database.references(group="eval")) == \ + parameters['N_eval'] * parameters['N_hands'] * parameters['N_session_references'] + assert len(database.probes(group="eval")) == \ + parameters['N_eval'] * parameters['N_hands'] * parameters['N_session_probes'] + + return p + + checked_protocols = [] + + checked_protocols.append( + _check_protocol("nom", protocols_parameters['nom'], eval=True) + ) + + for p in VerafingerContactless.protocols(): + assert p in checked_protocols, "Protocol {} untested".format(p) + + def test_utfvp(): from bob.bio.vein.database.utfvp import UtfvpDatabase diff --git a/doc/api.rst b/doc/api.rst index 5eb74b6d158d2fa9283e7009af7ebd9a98b8e62d..e3940b523006f033e60b8fb21c3008cf218f49b9 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -35,6 +35,10 @@ UTFVP Database .. automodule:: bob.bio.vein.database.fv3d +VERA Fingervein Contactless Database +==================================== + +.. automodule:: bob.bio.vein.database.verafinger_contactless Pre-processors diff --git a/setup.py b/setup.py index a31d06f586a5c933b6dfc705a8316cadd1c73475..f9e3d9e5fa923cb2599f83edf4526a1ba6b057f4 100644 --- a/setup.py +++ b/setup.py @@ -53,12 +53,15 @@ setup( "mc = bob.bio.vein.config.maximum_curvature", "rlt = bob.bio.vein.config.repeated_line_tracking", "wld = bob.bio.vein.config.wide_line_detector", + # verafinger contactless + "vera_nom = bob.bio.vein.config.database.verafinger_contactless_nom", ], "bob.bio.database": [ "verafinger = bob.bio.vein.config.database.verafinger: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", + "verafinger_contactless = bob.bio.vein.config.database.verafinger_contactless_nom:database", ], "bob.bio.pipeline": [ "wld = bob.bio.vein.config.wide_line_detector:pipeline",