Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
bob
bob.db.fv3d
Commits
f934dbf1
Commit
f934dbf1
authored
Jan 13, 2017
by
André Anjos
💬
Browse files
Move package name, advance
parent
2c8971c0
Changes
15
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
f934dbf1
...
...
@@ -18,4 +18,4 @@ build
*.egg
src/
db.sql3
bob/db/
3d
fv/data/
bob/db/fv
3d
/data/
README.rst
View file @
f934dbf1
...
...
@@ -2,17 +2,17 @@
.. Fri 02 Dec 2016 11:41:17 CET
.. image:: http://img.shields.io/badge/docs-stable-yellow.png
:target: http://pythonhosted.org/bob.db.
3d
fv/index.html
:target: http://pythonhosted.org/bob.db.fv
3d
/index.html
.. image:: http://img.shields.io/badge/docs-latest-orange.png
:target: https://www.idiap.ch/software/bob/docs/latest/bob/bob.db.
3d
fv/master/index.html
.. image:: https://gitlab.idiap.ch/bob/bob.db.
3d
fv/badges/master/build.svg
:target: https://gitlab.idiap.ch/bob/bob.db.
3d
fv/commits/master
:target: https://www.idiap.ch/software/bob/docs/latest/bob/bob.db.fv
3d
/master/index.html
.. image:: https://gitlab.idiap.ch/bob/bob.db.fv
3d
/badges/master/build.svg
:target: https://gitlab.idiap.ch/bob/bob.db.fv
3d
/commits/master
.. image:: https://img.shields.io/badge/gitlab-project-0000c0.svg
:target: https://gitlab.idiap.ch/bob/bob.db.
3d
fv
.. image:: http://img.shields.io/pypi/v/bob.db.
3d
fv.png
:target: https://pypi.python.org/pypi/bob.db.
3d
fv
.. image:: http://img.shields.io/pypi/dm/bob.db.
3d
fv.png
:target: https://pypi.python.org/pypi/bob.db.
3d
fv
:target: https://gitlab.idiap.ch/bob/bob.db.fv
3d
.. image:: http://img.shields.io/pypi/v/bob.db.fv
3d
.png
:target: https://pypi.python.org/pypi/bob.db.fv
3d
.. image:: http://img.shields.io/pypi/dm/bob.db.fv
3d
.png
:target: https://pypi.python.org/pypi/bob.db.fv
3d
==========================================
...
...
bob/db/
3d
fv/__init__.py
→
bob/db/fv
3d
/__init__.py
View file @
f934dbf1
...
...
@@ -15,5 +15,30 @@ def get_config():
return
bob
.
extension
.
get_config
(
__name__
)
# gets sphinx autodoc done right - don't remove it
def
__appropriate__
(
*
args
):
"""Says object was actually declared here, an not on the import module.
Parameters:
*args: An iterable of objects to modify
Resolves `Sphinx referencing issues
<https://github.com/sphinx-doc/sphinx/issues/3048>`
"""
for
obj
in
args
:
obj
.
__module__
=
__name__
__appropriate__
(
Database
,
Client
,
Finger
,
File
,
Protocol
,
Model
,
Probe
,
)
# gets sphinx autodoc done right - don't remove it
__all__
=
[
_
for
_
in
dir
()
if
not
_
.
startswith
(
'_'
)]
bob/db/
3d
fv/create.py
→
bob/db/fv
3d
/create.py
View file @
f934dbf1
File moved
bob/db/
3d
fv/driver.py
→
bob/db/fv
3d
/driver.py
View file @
f934dbf1
...
...
@@ -70,7 +70,7 @@ class Interface(BaseInterface):
def
name
(
self
):
return
'
3d
fv'
return
'fv
3d
'
def
version
(
self
):
...
...
bob/db/
3d
fv/files.txt
→
bob/db/fv
3d
/files.txt
View file @
f934dbf1
File moved
bob/db/
3d
fv/models.py
→
bob/db/fv
3d
/models.py
View file @
f934dbf1
...
...
@@ -174,7 +174,7 @@ class File(Base, bob.db.base.File):
Filenames inside the 3D Fingervein are like these:
<session>/<attempt>/<client>-<age>-<gender><skin><occ><side><finger><session><attempt><snap><cam>
>
png
<client>/
<session>/<attempt>/<client>-<age>-<gender><skin><occ><side><finger><session><attempt><snap><cam>
.
png
The fields can have these values:
...
...
@@ -323,6 +323,8 @@ class Model(Base):
protocol_id
=
Column
(
Integer
,
ForeignKey
(
'protocol.id'
))
protocol
=
relationship
(
"Protocol"
,
backref
=
backref
(
"models"
,
order_by
=
id
))
UniqueConstraint
(
'name'
,
'protocol'
,
name
=
'name_protocol'
)
def
__init__
(
self
,
name
,
group
,
finger
,
protocol
):
self
.
name
=
name
...
...
bob/db/
3d
fv/query.py
→
bob/db/fv
3d
/query.py
View file @
f934dbf1
...
...
@@ -8,6 +8,9 @@ from .models import *
from
.driver
import
Interface
from
sqlalchemy
import
and_
,
not_
import
bob.core
logger
=
bob
.
core
.
log
.
setup
(
__name__
)
import
bob.db.base
SQLITE_FILE
=
Interface
().
files
()[
0
]
...
...
@@ -39,7 +42,7 @@ class Database(bob.db.base.SQLiteDatabase):
def
groups
(
self
):
"""Returns a list of all supported groups"""
return
Model
.
group_choices
return
(
'train'
,
'dev'
,
'eval'
)
def
genders
(
self
):
...
...
@@ -54,6 +57,12 @@ class Database(bob.db.base.SQLiteDatabase):
return
Finger
.
side_choices
def
fingers
(
self
):
"""Returns a list of all supported finger values"""
return
Finger
.
name_choices
def
sessions
(
self
):
"""Returns a list of all supported session values"""
...
...
@@ -63,11 +72,11 @@ class Database(bob.db.base.SQLiteDatabase):
def
finger_name_from_model_id
(
self
,
model_id
):
"""Returns the unique finger name in the database given a ``model_id``"""
return
self
.
query
(
File
).
filter
(
File
.
model_id
==
model_id
).
one
().
unique_
finger_
name
return
self
.
query
(
File
).
filter
(
File
.
model_id
==
model_id
).
one
().
unique_name
def
model_ids
(
self
,
protocol
=
None
,
groups
=
None
):
"""Returns a set of models for a given protocol/group
"""Returns a set of models
identifiers
for a given protocol/group
Parameters:
...
...
@@ -76,9 +85,8 @@ class Database(bob.db.base.SQLiteDatabase):
groups (:py:class:`str`, :py:class:`list`, optional): One or more of the
supported groups. If not set, returns data from all groups. Notice this
parameter should either not set or set to ``dev``. Otherwise, this
method will return an empty list given we don't have a test set, only a
development set.
parameter should either not set or set to ``dev``, ``eval`` or an
iterator that yields both.
Returns:
...
...
@@ -88,43 +96,41 @@ class Database(bob.db.base.SQLiteDatabase):
"""
protocols
=
None
if
protocol
:
valid_protocols
=
self
.
protocol_names
()
protocols
=
self
.
check_parameters_for_validity
(
protocol
,
"protocol"
,
valid_protocols
)
if
'train'
in
groups
:
# there are no models in the training set
if
len
(
groups
)
==
1
:
return
[]
#only group required, so return empty
groups
=
tuple
(
k
for
k
in
groups
if
k
!=
'train'
)
if
groups
:
valid_groups
=
self
.
groups
()
groups
=
self
.
check_parameters_for_validity
(
groups
,
"group"
,
valid_groups
)
valid_protocols
=
self
.
protocol_names
()
protocols
=
self
.
check_parameters_for_validity
(
protocol
,
"protocol"
,
valid_protocols
)
retval
=
self
.
query
(
File
)
valid_groups
=
Model
.
group_choices
groups
=
self
.
check_parameters_for_validity
(
groups
,
"group"
,
valid_groups
)
joins
=
[]
filters
=
[]
retval
=
self
.
query
(
Model
).
join
(
Protocol
)
retval
=
retval
.
filter
(
Protocol
.
name
.
in_
(
protocols
))
subquery
=
self
.
query
(
Subset
)
sub
filters
=
[]
if
groups
:
filters
.
append
(
Model
.
group
.
in_
(
groups
))
if
protocols
:
subquery
=
subquery
.
join
(
Protocol
)
subfilters
.
append
(
Protocol
.
name
.
in_
(
protocols
))
retval
=
retval
.
filter
(
*
filters
).
distinct
().
order_by
(
'id'
)
if
groups
:
subfilters
.
append
(
Subset
.
group
.
in_
(
groups
))
return
[
k
.
id
for
k
in
retval
]
subfilters
.
append
(
Subset
.
purpose
==
'enroll'
)
subsets
=
subquery
.
filter
(
*
subfilter
s
)
filters
.
append
(
File
.
subsets
.
any
(
Subset
.
id
.
in_
([
k
.
id
for
k
in
subsets
])))
def
_train_objects
(
self
,
protocols
,
genders
,
sides
,
fingers
,
session
s
)
:
"""Returns a query that yields objects related to training
retval
=
retval
.
join
(
*
joins
).
filter
(
*
filters
).
distinct
().
order_by
(
'id'
)
This is a private function, input parameters are assumed pre-checked
"""
return
sorted
(
set
([
k
.
model_id
for
k
in
retval
.
distinct
()]))
return
query
def
objects
(
self
,
protocol
=
None
,
groups
=
None
,
purposes
=
None
,
model_ids
=
None
,
genders
=
None
,
sides
=
None
,
sessions
=
None
):
model_ids
=
None
,
genders
=
None
,
sides
=
None
,
fingers
=
None
,
sessions
=
None
):
"""Returns objects filtered by criteria
...
...
@@ -148,6 +154,9 @@ class Database(bob.db.base.SQLiteDatabase):
sides (:py:class:`str`, :py:class:`list`, optional): If set, limit output
using the provided side identifier
fingers (:py:class:`str`, :py:class:`list`, optional): If set, limit
output using the provided finger identifiers
sessions (:py:class:`str`, :py:class:`list`, optional): If set, limit
output using the provided session identifiers
...
...
@@ -159,20 +168,26 @@ class Database(bob.db.base.SQLiteDatabase):
"""
protocols
=
None
if
protocol
:
valid_protocols
=
self
.
protocol_names
()
protocols
=
self
.
check_parameters_for_validity
(
protocol
,
"protocol"
,
valid_protocols
)
valid_protocols
=
self
.
protocol_names
()
protocols
=
self
.
check_parameters_for_validity
(
protocol
,
"protocol"
,
valid_protocols
)
if
groups
:
valid_groups
=
self
.
groups
()
groups
=
self
.
check_parameters_for_validity
(
groups
,
"group"
,
valid_groups
)
valid_groups
=
self
.
groups
()
groups
=
self
.
check_parameters_for_validity
(
groups
,
"group"
,
valid_groups
)
if
purposes
:
valid_purposes
=
self
.
purposes
()
purposes
=
self
.
check_parameters_for_validity
(
purposes
,
"purpose"
,
valid_purposes
)
valid_purposes
=
self
.
purposes
()
purposes
=
self
.
check_parameters_for_validity
(
purposes
,
"purpose"
,
valid_purposes
)
# cleans up groups and purposes to solve for the minimum
if
(
'train'
in
purposes
and
not
(
'train'
in
groups
)):
purposes
=
tuple
(
k
for
k
in
purposes
if
k
!=
'train'
)
if
(
'train'
in
groups
and
not
(
'train'
in
purposes
)):
groups
=
tuple
(
k
for
k
in
groups
if
k
!=
'train'
)
if
(
'enroll'
in
purposes
or
'probe'
in
purposes
)
and
not
'dev'
in
groups
:
purposes
=
tuple
(
k
for
k
in
purposes
if
k
not
in
[
'enroll'
,
'probe'
])
if
'dev'
in
groups
and
not
(
'enroll'
in
purposes
or
'probe'
in
purposes
):
groups
=
tuple
(
k
for
k
in
groups
if
k
!=
'dev'
)
# if only asking for 'probes', then ignore model_ids as all of our
# protocols do a full probe-model scan
...
...
@@ -184,57 +199,59 @@ class Database(bob.db.base.SQLiteDatabase):
model_ids
=
self
.
check_parameters_for_validity
(
model_ids
,
"model_ids"
,
valid_model_ids
)
if
genders
:
valid_genders
=
self
.
genders
()
genders
=
self
.
check_parameters_for_validity
(
genders
,
"genders"
,
valid_genders
)
if
sides
:
valid_sides
=
self
.
sides
()
sides
=
self
.
check_parameters_for_validity
(
sides
,
"sides"
,
valid_sides
)
if
sessions
:
valid_sessions
=
self
.
sessions
()
sessions
=
self
.
check_parameters_for_validity
(
sessions
,
"sessions"
,
valid_sessions
)
retval
=
self
.
query
(
File
)
joins
=
[]
filters
=
[]
if
protocols
or
groups
or
purposes
:
subquery
=
self
.
query
(
Subset
)
subfilters
=
[]
if
protocols
:
subquery
=
subquery
.
join
(
Protocol
)
subfilters
.
append
(
Protocol
.
name
.
in_
(
protocols
))
if
groups
:
subfilters
.
append
(
Subset
.
group
.
in_
(
groups
))
if
purposes
:
subfilters
.
append
(
Subset
.
purpose
.
in_
(
purposes
))
subsets
=
subquery
.
filter
(
*
subfilters
)
filters
.
append
(
File
.
subsets
.
any
(
Subset
.
id
.
in_
([
k
.
id
for
k
in
subsets
])))
if
genders
or
sides
:
joins
.
append
(
Finger
)
if
genders
:
fingers
=
self
.
query
(
Finger
).
join
(
Client
).
filter
(
Client
.
gender
.
in_
(
genders
))
filters
.
append
(
Finger
.
id
.
in_
([
k
.
id
for
k
in
fingers
]))
if
sides
:
filters
.
append
(
Finger
.
side
.
in_
(
sides
))
if
sessions
:
filters
.
append
(
File
.
session
.
in_
(
sessions
))
if
model_ids
:
filters
.
append
(
File
.
model_id
.
in_
(
model_ids
))
retval
=
retval
.
join
(
*
joins
).
filter
(
*
filters
).
distinct
().
order_by
(
'id'
)
return
list
(
retval
)
valid_genders
=
self
.
genders
()
genders
=
self
.
check_parameters_for_validity
(
genders
,
"genders"
,
valid_genders
)
valid_fingers
=
self
.
fingers
()
fingers
=
self
.
check_parameters_for_validity
(
fingers
,
"fingers"
,
valid_fingers
)
valid_sides
=
self
.
sides
()
sides
=
self
.
check_parameters_for_validity
(
sides
,
"sides"
,
valid_sides
)
valid_sessions
=
self
.
sessions
()
sessions
=
self
.
check_parameters_for_validity
(
sessions
,
"sessions"
,
valid_sessions
)
# this database contains 3 sets of "files" for each protocol: the ones
# related to the training_set, models and probes related to both dev and
# eval groups. These file lists don't overlap
retval
=
None
if
'train'
in
purposes
:
q
=
self
.
query
(
File
).
join
(
Protocol
.
training_set
)
q
=
q
.
join
(
Finger
).
join
(
Client
)
q
=
q
.
filter
(
Protocol
.
name
.
in_
(
protocols
))
q
=
q
.
filter
(
Client
.
gender
.
in_
(
genders
))
q
=
q
.
filter
(
Finger
.
side
.
in_
(
sides
))
q
=
q
.
filter
(
Finger
.
name
.
in_
(
fingers
))
q
=
q
.
filter
(
File
.
session
.
in_
(
sessions
))
retval
=
q
if
'enroll'
in
purposes
:
q
=
self
.
query
(
File
).
join
(
Model
.
files
)
q
=
q
.
join
(
Finger
).
join
(
Client
)
q
=
q
.
filter
(
Model
.
group
.
in_
(
groups
))
if
model_ids
:
q
=
q
.
filter
(
Model
.
id
.
in_
(
model_ids
))
#q = q.filter(Protocol.name.in_(protocols))
q
=
q
.
filter
(
Client
.
gender
.
in_
(
genders
))
q
=
q
.
filter
(
Finger
.
side
.
in_
(
sides
))
q
=
q
.
filter
(
Finger
.
name
.
in_
(
fingers
))
q
=
q
.
filter
(
File
.
session
.
in_
(
sessions
))
retval
=
q
if
retval
is
None
else
retval
.
union
(
q
)
if
'probe'
in
purposes
:
q
=
self
.
query
(
File
).
join
(
Probe
.
file
).
join
(
Model
.
protocol
)
q
=
q
.
join
(
Finger
).
join
(
Client
)
q
=
q
.
filter
(
Probe
.
group
.
in_
(
groups
))
q
=
q
.
filter
(
File
.
protocol
.
name
.
in_
(
protocols
))
q
=
q
.
filter
(
Client
.
gender
.
in_
(
genders
))
q
=
q
.
filter
(
Finger
.
side
.
in_
(
sides
))
q
=
q
.
filter
(
Finger
.
name
.
in_
(
fingers
))
q
=
q
.
filter
(
File
.
session
.
in_
(
sessions
))
retval
=
q
if
retval
is
None
else
retval
.
union
(
q
)
# combine all queries, sort and uniq'fy
return
list
(
retval
.
distinct
().
order_by
(
'id'
))
bob/db/
3d
fv/test.py
→
bob/db/fv
3d
/test.py
View file @
f934dbf1
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
"""A few checks at the
VERA
Fingervein database.
"""A few checks at the
3D
Fingervein database.
"""
import
os
import
numpy
from
.
import
Database
from
.
query
import
Database
import
nose.tools
from
nose.plugins.skip
import
SkipTest
# base directories where the VERA files sit
DATABASE_PATH
=
"/idiap/project/vera/databases/VERA-fingervein"
def
sql3_available
(
test
):
"""Decorator for detecting if the sql3 file is available"""
def
metadata_available
(
test
):
"""Decorator for detecting if the metadata is available"""
from
bob.io.base.test_utils
import
datafile
from
nose.plugins.skip
import
SkipTest
...
...
@@ -29,7 +26,7 @@ def sql3_available(test):
if
os
.
path
.
exists
(
dbfile
):
return
test
(
*
args
,
**
kwargs
)
else
:
raise
SkipTest
(
"The interface SQL file (%s) is not available; did you forget to run 'bob_dbmanage.py %s create' ?"
%
(
dbfile
,
'
vera
'
))
raise
SkipTest
(
"The interface SQL file (%s) is not available; did you forget to run 'bob_dbmanage.py %s create' ?"
%
(
dbfile
,
'
fv3d
'
))
return
wrapper
...
...
@@ -51,24 +48,38 @@ def db_available(test):
return
wrapper
@
sql3_available
@
metadata_available
def
test_recreate
():
from
bob.db.base.script.dbmanage
import
main
nose
.
tools
.
eq_
(
main
(
'fv3d create --recreate'
.
split
()),
None
)
@
metadata_available
def
test_counts
():
# test whether the correct number of clients is returned
db
=
Database
()
nose
.
tools
.
eq_
(
db
.
groups
(),
(
'train'
,
'dev'
))
nose
.
tools
.
eq_
(
db
.
groups
(),
(
'train'
,
'dev'
,
'eval'
))
protocols
=
db
.
protocol_names
()
nose
.
tools
.
eq_
(
len
(
protocols
),
4
)
assert
'Nom'
in
protocols
assert
'Full'
in
protocols
assert
'Fifty'
in
protocols
assert
'B'
in
protocols
nose
.
tools
.
eq_
(
len
(
protocols
),
1
)
assert
'central'
in
protocols
nose
.
tools
.
eq_
(
db
.
purposes
(),
(
'train'
,
'enroll'
,
'probe'
))
nose
.
tools
.
eq_
(
db
.
genders
(),
(
'M'
,
'F'
))
nose
.
tools
.
eq_
(
db
.
sides
(),
(
'L'
,
'R'
))
nose
.
tools
.
eq_
(
db
.
genders
(),
(
'm'
,
'f'
))
nose
.
tools
.
eq_
(
db
.
sides
(),
(
'l'
,
'r'
))
nose
.
tools
.
eq_
(
db
.
fingers
(),
(
't'
,
'i'
,
'm'
,
'r'
,
'l'
))
# FDV: 89 subjects * 2 fingers * 5 snapshots * 1 attempt = 890
# IDI: 2 subjects * 6 fingers * 2 snapshots = 48
# Total: 938 images
nose
.
tools
.
eq_
(
len
(
db
.
objects
(
protocol
=
'central'
,
groups
=
'train'
)),
938
)
# IDI: 50 subjects * 6 fingers * 2 snapshots * 2 attempts = 1200 images
nose
.
tools
.
eq_
(
len
(
db
.
objects
(
protocol
=
'central'
,
groups
=
'dev'
,
purposes
=
'enroll'
)),
1200
)
# test model ids
model_ids
=
db
.
model_ids
()
...
...
@@ -124,17 +135,19 @@ def test_counts():
purposes
=
'probe'
,
model_ids
=
model_ids
[
0
])),
440
)
@
sql3_available
@
nose
.
tools
.
nottest
@
metadata_available
def
test_driver_api
():
from
bob.db.base.script.dbmanage
import
main
nose
.
tools
.
eq_
(
main
(
'
verafinger
dumplist --self-test'
.
split
()),
0
)
nose
.
tools
.
eq_
(
main
(
'
verafinger
dumplist --protocol=Full --group=dev --purpose=enroll --model=101_L_1 --self-test'
.
split
()),
0
)
nose
.
tools
.
eq_
(
main
(
'
verafinger
checkfiles --self-test'
.
split
()),
0
)
nose
.
tools
.
eq_
(
main
(
'
fv3d
dumplist --self-test'
.
split
()),
0
)
nose
.
tools
.
eq_
(
main
(
'
fv3d
dumplist --protocol=Full --group=dev --purpose=enroll --model=101_L_1 --self-test'
.
split
()),
0
)
nose
.
tools
.
eq_
(
main
(
'
fv3d
checkfiles --self-test'
.
split
()),
0
)
@
sql3_available
@
nose
.
tools
.
nottest
@
metadata_available
@
db_available
def
test_load
():
...
...
@@ -149,32 +162,8 @@ def test_load():
nose
.
tools
.
eq_
(
image
.
dtype
,
numpy
.
uint8
)
@
sql3_available
@
db_available
def
test_annotations
():
db
=
Database
()
for
f
in
db
.
objects
():
# loads an image from the database
image
=
f
.
load
(
DATABASE_PATH
)
roi
=
f
.
roi
()
assert
isinstance
(
roi
,
numpy
.
ndarray
)
nose
.
tools
.
eq_
(
len
(
roi
.
shape
),
2
)
#it is a 2D array
nose
.
tools
.
eq_
(
roi
.
shape
[
1
],
2
)
#two columns
nose
.
tools
.
eq_
(
roi
.
dtype
,
numpy
.
uint16
)
assert
len
(
roi
)
>
10
#at least 10 points
# ensures all annotation points are within image boundary
Y
,
X
=
image
.
shape
for
y
,
x
in
roi
:
assert
y
<
Y
,
'Annotation (%d, %d) for %s surpasses the image size (%d, %d)'
%
(
y
,
x
,
f
.
path
,
Y
,
X
)
assert
x
<
X
,
'Annotation (%d, %d) for %s surpasses the image size (%d, %d)'
%
(
y
,
x
,
f
.
path
,
Y
,
X
)
@
sql3_available
@
nose
.
tools
.
nottest
@
metadata_available
def
test_model_id_to_finger_name_conversion
():
db
=
Database
()
...
...
buildout.cfg
View file @
f934dbf1
...
...
@@ -4,7 +4,7 @@
[buildout]
parts = scripts
develop = .
eggs = bob.db.
3d
fv
eggs = bob.db.fv
3d
extensions = bob.buildout
newest = false
verbose = true
...
...
develop.cfg
View file @
f934dbf1
...
...
@@ -3,7 +3,7 @@
[buildout]
parts = scripts
eggs = bob.db.
3d
fv
eggs = bob.db.fv
3d
extensions = bob.buildout
mr.developer
auto-checkout = *
...
...
doc/conf.py
View file @
f934dbf1
...
...
@@ -80,7 +80,7 @@ source_suffix = '.rst'
master_doc
=
'index'
# General information about the project.
project
=
u
'bob.db.
3d
fv'
project
=
u
'bob.db.fv
3d
'
import
time
copyright
=
u
'%s, Idiap Research Institute'
%
time
.
strftime
(
'%Y'
)
...
...
doc/index.rst
View file @
f934dbf1
.. vim: set fileencoding=utf-8 :
.. Fri 02 Dec 2016 11:45:48 CET
.. _bob.db.
3d
fv:
.. _bob.db.fv
3d
:
========================
==
========================
3D Fingervein Database
========================
==
========================
The `3D Fingervein Database <https://www.idiap.ch/dataset/3d-fingervein>`_
for finger vein recognition consists of 440 images from 110 clients.
This database was produced at the `Idiap Research Institute
<http://www.idiap.ch>`_, in Switzerland.
for finger vein recognition consists of 13614 images from 141 subjects
collected in various acquisition campaigns. This database was produced at the
`Idiap Research Institute <http://www.idiap.ch>`_, in Switzerland.
Notice this package does not contain the raw data files from this dataset,
which need to be obtained through the link provided above.
If you use this database in your publication, please cite the following paper
on your references:
...
...
@@ -25,11 +28,74 @@ on your references:
.. title = {On the Vulnerability of Finger Vein Recognition to Spoofing},
.. booktitle = {IEEE International Conference of the Biometrics Special Interest Group (BIOSIG)},
.. year = {2014},
.. location = {Darmstadt, Germay},
.. location = {Darmstadt, Germa
n
y},
.. url = {http://publications.idiap.ch/index.php/publications/show/2910}
.. }
Data Acquisition Campaign
-------------------------
Data for the 3DFV database was collected through various campaings in
Switzerland, at different locations. Each of the campaigns and outcomes are
summarized next:
* Foire du Valais (FDV): 89 subjects provided data from both index fingers in a
single data-acquisition session with a single attempt. For each subject
finger, 5 snapshots were taken. The unique subject identifiers vary between 1
and 94, but numeration is not contiguous.
* Idiap (IDI): 50 subjects provided data from both left and right index, middle
and ring fingers in 3 data acquisition sessions, each with 2 attempts. Two
more subjects provided data for the same fingers, but for only 1 acquisition
session (subjects 131 and 147). The unique subject identifiers range from 101
to 153. Numeration is contiguous.
Filename Structure
------------------
Filenames inside the 3D Fingervein are structured like this:
.. code-block:: text
<database-root>/<client:%03d>/<session:%d>/<attempt:%d>/<client:%03d>-<age:%02d>-<gender:%s><skin:%s><occ:%s><side:%s><finger:%s><session:%d><attempt:%d><snap:%d><cam:%d>.png
Each field can have these values: