diff --git a/bob/bio/vein/configurations/principal_curvature.py b/bob/bio/vein/configurations/principal_curvature.py new file mode 100644 index 0000000000000000000000000000000000000000..8357ea2a5a92e104a63f7df2312abe7413704377 --- /dev/null +++ b/bob/bio/vein/configurations/principal_curvature.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# vim: set fileencoding=utf-8 : +# Tue 03 Nov 2020 16:48:32 CEST + +'''Principal Curvature and Miura Matching baseline + +References: + +1. [CW09]_ +2. [TV13]_ +3. [TVM14]_ + +''' + +sub_directory = 'pc' +"""Sub-directory where results will be placed. + +You may change this setting using the ``--sub-directory`` command-line option +or the attribute ``sub_directory`` in a configuration file loaded **after** +this resource. +""" + +from ..preprocessor import NoCrop, TomesLeeMask, HuangNormalization, \ + NoFilter, Preprocessor + +preprocessor = Preprocessor( + crop=NoCrop(), + mask=TomesLeeMask(), + normalize=HuangNormalization(), + filter=NoFilter(), + ) +"""Preprocessing using gray-level based finger cropping and no post-processing +""" + +from ..extractor import PrincipalCurvature +extractor = PrincipalCurvature() +"""Features are the output of the principal curvature algorithm, as described on +[CW09]_. + +Defaults taken from [CW09]_. +""" + +# Notice the values of ch and cw are different than those from the +# repeated-line tracking baseline. +from ..algorithm import MiuraMatch +algorithm = MiuraMatch() +"""Miura-matching algorithm with specific settings for search displacement + +Defaults taken from [TV13]_. +""" diff --git a/bob/bio/vein/extractor/PrincipalCurvature.py b/bob/bio/vein/extractor/PrincipalCurvature.py index c08cae315ea7e2c571cfe17565372f50962cc24c..3a8f97f324d7b51e655b0fcf7799ef1a77604385 100644 --- a/bob/bio/vein/extractor/PrincipalCurvature.py +++ b/bob/bio/vein/extractor/PrincipalCurvature.py @@ -7,87 +7,97 @@ import bob.io.base from bob.bio.base.extractor import Extractor +from scipy.ndimage import gaussian_filter + class PrincipalCurvature (Extractor): - """MiuraMax feature extractor + """MiuraMax feature extractor - Based on J.H. Choi, W. Song, T. Kim, S.R. Lee and H.C. Kim, Finger vein - extraction using gradient normalization and principal curvature. Proceedings - on Image Processing: Machine Vision Applications II, SPIE 7251, (2009) - """ + Based on J.H. Choi, W. Song, T. Kim, S.R. Lee and H.C. Kim, Finger vein + extraction using gradient normalization and principal curvature. Proceedings + on Image Processing: Machine Vision Applications II, SPIE 7251, (2009) + """ - def __init__( - self, - sigma = 2, # Gaussian standard deviation applied - threshold = 1.3, # Percentage of maximum used for hard thresholding - ): + def __init__( + self, + sigma = 3, # Gaussian standard deviation applied + threshold = 2, # Percentage of maximum used for hard thresholding + ): + """NOTE: In the reference paper where the size of the finger image is 320 by 128, + the proposed values for sigma and threshold are 3 and 4, respectively. + However, for other resolutions it is better to change the values for sigma and + threshold. e.g., in UTFVP dataset where the size of the finger image is 672 by 380, + sigma=6 and threshold=4 workes better results better features. + """ + # call base class constructor + Extractor.__init__( + self, + sigma = sigma, + threshold = threshold, + ) - # call base class constructor - Extractor.__init__( - self, - sigma = sigma, - threshold = threshold, - ) + # block parameters + self.sigma = sigma + self.threshold = threshold - # block parameters - self.sigma = sigma - self.threshold = threshold + def ut_gauss(self, img, sigma, dx, dy): + return gaussian_filter(numpy.float64(img), sigma, order = [dx,dy]) - def principal_curvature(self, image, mask): - """Computes and returns the Maximum Curvature features for the given input - fingervein image""" + def principal_curvature(self, image, mask): + """Computes and returns the Maximum Curvature features for the given input + fingervein image""" - finger_mask = numpy.zeros(mask.shape) - finger_mask[mask == True] = 1 + finger_mask = numpy.zeros(mask.shape) + finger_mask[mask == True] = 1 - sigma = numpy.sqrt(self.sigma**2/2) + sigma = numpy.sqrt(self.sigma**2/2) - gx = ut_gauss(img,sigma,1,0) - gy = ut_gauss(img,sigma,0,1) + gx = self.ut_gauss(image,self.sigma,1,0) + gy = self.ut_gauss(image,self.sigma,0,1) - Gmag = numpy.sqrt(gx**2 + gy**2) # Gradient magnitude + Gmag = numpy.sqrt(gx**2 + gy**2) # Gradient magnitude - # Apply threshold - gamma = (self.threshold/100)*max(max(Gmag)) + # Apply threshold + gamma = (self.threshold/100)*numpy.max(Gmag) - indices = find(Gmag < gamma) + indices = numpy.where(Gmag < gamma) - gx[indices] = 0 - gy[indices] = 0 + gx[indices] = 0 + gy[indices] = 0 - # Normalize - Gmag[find[Gmag==0]] = 1 # Avoid dividing by zero - gx = gx/Gmag - gy = gy/Gmag + # Normalize + Gmag[numpy.where(Gmag==0)] = 1 # Avoid dividing by zero + gx = gx/Gmag + gy = gy/Gmag - hxx = ut_gauss(gx,sigma,1,0) - hxy = ut_gauss(gx,sigma,0,1) - hyy = ut_gauss(gy,sigma,0,1) + hxx = self.ut_gauss(gx,sigma,1,0) + hxy = self.ut_gauss(gx,sigma,0,1) + hyy = self.ut_gauss(gy,sigma,0,1) - lambda1 = 0.5*(hxx + hyy + numpy.sqrt(hxx**2 + hyy**2 - 2*hxx**hyy + 4*hxy**2)) - veins = lambda1*finger_mask - # Normalise - veins = veins - min(veins[:]) - veins = veins/max(veins[:]) + lambda1 = 0.5*(hxx + hyy + numpy.sqrt(hxx**2 + hyy**2 - 2*hxx*hyy + 4*hxy**2)) + veins = lambda1*finger_mask - veins = veins*finger_mask + # Normalise + veins = veins - numpy.min(veins[:]) + veins = veins/numpy.max(veins[:]) + veins = veins*finger_mask - # Binarise the vein image by otsu - md = numpy.median(img_veins[img_veins>0]) - img_veins_bin = img_veins > md + # Binarise the vein image by otsu + md = numpy.median(veins[veins>0]) + img_veins_bin = veins > md - return img_veins_bin.astype(numpy.float64) + return img_veins_bin.astype(numpy.float64) - def __call__(self, image): - """Reads the input image, extract the features based on Principal Curvature - of the fingervein image, and writes the resulting template""" + def __call__(self, image): + """Reads the input image, extract the features based on Principal Curvature + of the fingervein image, and writes the resulting template""" - finger_image = image[0] #Normalized image with or without histogram equalization - finger_mask = image[1] + finger_image = image[0] #Normalized image with or without histogram equalization + finger_mask = image[1] - return self.principal_curvature(finger_image, finger_mask) + return self.principal_curvature(finger_image, finger_mask) \ No newline at end of file diff --git a/doc/references.rst b/doc/references.rst index 5265c8692e7e35d4edf62989ca46c4ca551abed2..8e5e16c8d0c672374f0ca175c0b9f368e1cfde34 100644 --- a/doc/references.rst +++ b/doc/references.rst @@ -27,3 +27,4 @@ .. [KK10] *R. Kabacinski and *M. Kowalski, **Human Vein Pattern Segmentation from Low Quality Images - A Comparison of Methods**, in: Image Processing and Communications Challenges 2, pp. 105-112, 2010. +.. [CW09] J.H. Choi, W. Song, T. Kim, S.R. Lee and H.C. Kim, **Finger vein extraction using gradient normalization and principal curvature**, Proceedings on Image Processing: Machine Vision Applications II, SPIE 7251, 2009. \ No newline at end of file diff --git a/setup.py b/setup.py index 7e146a7af885a87905ad99559844287082a051e0..9c8c358a729effe54757b85f2b94f277105c4d5d 100644 --- a/setup.py +++ b/setup.py @@ -2,106 +2,91 @@ # vim: set fileencoding=utf-8 : from setuptools import setup, dist -dist.Distribution(dict(setup_requires=['bob.extension'])) + +dist.Distribution(dict(setup_requires=["bob.extension"])) from bob.extension.utils import load_requirements, find_packages + install_requires = load_requirements() setup( - - name='bob.bio.vein', + name="bob.bio.vein", version=open("version.txt").read().rstrip(), - description='Vein Recognition Library', - - url='https://gitlab.idiap.ch/bob/bob.bio.vein', - license='GPLv3', - - author='Andre Anjos,Pedro Tome', - author_email='andre.anjos@idiap.ch,pedro.tome@idiap.ch', - - keywords = "bob, biometric recognition, evaluation, vein", - - long_description=open('README.rst').read(), - + description="Vein Recognition Library", + url="https://gitlab.idiap.ch/bob/bob.bio.vein", + license="GPLv3", + author="Andre Anjos,Pedro Tome", + author_email="andre.anjos@idiap.ch,pedro.tome@idiap.ch", + keywords="bob, biometric recognition, evaluation, vein", + long_description=open("README.rst").read(), packages=find_packages(), include_package_data=True, - zip_safe = False, - + zip_safe=False, install_requires=install_requires, - entry_points={ - - 'bob.bio.config': [ - # protocols (must be specified before the database in the cmd) - # verafinger - 'Nom = bob.bio.vein.config.database.protocol_verafinger.nom', - 'Cropped-Nom = bob.bio.vein.config.database.protocol_verafinger.cropped_nom', - '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', - # fv3d - 'central = bob.bio.vein.config.database.protocol_fv3d.central', - 'left = bob.bio.vein.config.database.protocol_fv3d.left', - 'right = bob.bio.vein.config.database.protocol_fv3d.right', - 'stitched = bob.bio.vein.config.database.protocol_fv3d.stitched', - # putvein - 'wrist-LR-1 = bob.bio.vein.config.database.protocol_putvein.wrist_lr_1', - 'wrist-LR-4 = bob.bio.vein.config.database.protocol_putvein.wrist_lr_4', - 'palm-LR-1 = bob.bio.vein.config.database.protocol_putvein.palm_lr_1', - '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 - 'mc = bob.bio.vein.config.maximum_curvature', - 'rlt = bob.bio.vein.config.repeated_line_tracking', - 'wld = bob.bio.vein.config.wide_line_detector', - - # other (legacy) - 'parallel = bob.bio.vein.config.parallel', - 'gridio4g48 = bob.bio.vein.config.gridio4g48', - 'grid = bob.bio.vein.config.gridio4g48', + "bob.bio.config": [ + # protocols (must be specified before the database in the cmd) + # verafinger + "Nom = bob.bio.vein.config.database.protocol_verafinger.nom", + "Cropped-Nom = bob.bio.vein.config.database.protocol_verafinger.cropped_nom", + "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", + # fv3d + "central = bob.bio.vein.config.database.protocol_fv3d.central", + "left = bob.bio.vein.config.database.protocol_fv3d.left", + "right = bob.bio.vein.config.database.protocol_fv3d.right", + "stitched = bob.bio.vein.config.database.protocol_fv3d.stitched", + # putvein + "wrist-LR-1 = bob.bio.vein.config.database.protocol_putvein.wrist_lr_1", + "wrist-LR-4 = bob.bio.vein.config.database.protocol_putvein.wrist_lr_4", + "palm-LR-1 = bob.bio.vein.config.database.protocol_putvein.palm_lr_1", + "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 + "mc = bob.bio.vein.config.maximum_curvature", + "rlt = bob.bio.vein.config.repeated_line_tracking", + "wld = bob.bio.vein.config.wide_line_detector", + # other (legacy) + "parallel = bob.bio.vein.config.parallel", + "gridio4g48 = bob.bio.vein.config.gridio4g48", + "grid = bob.bio.vein.config.gridio4g48", ], - - 'bob.bio.database': [ - 'verafinger = bob.bio.vein.config.database.verafinger:database', - 'utfvp = bob.bio.vein.config.database.utfvp:database', - 'fv3d = bob.bio.vein.config.database.fv3d:database', - 'putvein = bob.bio.vein.config.database.putvein:database', - ], - - 'bob.bio.pipeline': [ - 'wld = bob.bio.vein.config.wide_line_detector:pipeline', - 'mc = bob.bio.vein.config.maximum_curvature:pipeline', - 'rlt = bob.bio.vein.config.repeated_line_tracking:pipeline', - ], - - 'console_scripts': [ - 'bob_bio_vein_compare_rois.py = bob.bio.vein.script.compare_rois:main', - 'bob_bio_vein_view_sample.py = bob.bio.vein.script.view_sample:main', - 'bob_bio_vein_blame.py = bob.bio.vein.script.blame:main', - 'bob_bio_vein_markdet.py = bob.bio.vein.script.markdet:main', - 'bob_bio_vein_watershed_mask.py = bob.bio.vein.script.watershed_mask:main', - ] - }, - - classifiers = [ - 'Framework :: Bob', - 'Development Status :: 4 - Beta', - 'Intended Audience :: Science/Research', - 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', - 'Natural Language :: English', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3', - 'Topic :: Scientific/Engineering :: Artificial Intelligence', - 'Topic :: Software Development :: Libraries :: Python Modules', - ], - + "bob.bio.database": [ + "verafinger = bob.bio.vein.config.database.verafinger:database", + "utfvp = bob.bio.vein.config.database.utfvp:database", + "fv3d = bob.bio.vein.config.database.fv3d:database", + "putvein = bob.bio.vein.config.database.putvein:database", + ], + "bob.bio.pipeline": [ + "wld = bob.bio.vein.config.wide_line_detector:pipeline", + "mc = bob.bio.vein.config.maximum_curvature:pipeline", + "rlt = bob.bio.vein.config.repeated_line_tracking:pipeline", + ], + "console_scripts": [ + "bob_bio_vein_compare_rois.py = bob.bio.vein.script.compare_rois:main", + "bob_bio_vein_view_sample.py = bob.bio.vein.script.view_sample:main", + "bob_bio_vein_blame.py = bob.bio.vein.script.blame:main", + "bob_bio_vein_markdet.py = bob.bio.vein.script.markdet:main", + "bob_bio_vein_watershed_mask.py = bob.bio.vein.script.watershed_mask:main", + ], + }, + classifiers=[ + "Framework :: Bob", + "Development Status :: 4 - Beta", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", + "Natural Language :: English", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Topic :: Scientific/Engineering :: Artificial Intelligence", + "Topic :: Software Development :: Libraries :: Python Modules", + ], )