Coverage for src/bob/bio/vein/extractor/PrincipalCurvature.py: 21%
39 statements
« prev ^ index » next coverage.py v7.6.0, created at 2024-07-12 23:27 +0200
« prev ^ index » next coverage.py v7.6.0, created at 2024-07-12 23:27 +0200
1#!/usr/bin/env python
2# vim: set fileencoding=utf-8 :
4import numpy
6from scipy.ndimage import gaussian_filter
8from bob.bio.base.extractor import Extractor
11class PrincipalCurvature(Extractor):
12 """MiuraMax feature extractor
14 Based on [CW09]_.
15 """
17 def __init__(
18 self,
19 sigma=3, # Gaussian standard deviation applied
20 threshold=4, # Percentage of maximum used for hard thresholding
21 ):
22 """NOTE: In the reference paper where the size of the finger image is 320 by 128,
23 the proposed values for sigma and threshold are 3 and 4, respectively.
24 However, for other resolutions it is better to change the values for sigma and
25 threshold. e.g., in UTFVP dataset where the size of the finger image is 672 by 380,
26 sigma=6 and threshold=4 workes better results better features.
27 """
28 # call base class constructor
29 Extractor.__init__(
30 self,
31 sigma=sigma,
32 threshold=threshold,
33 )
35 # block parameters
36 self.sigma = sigma
37 self.threshold = threshold
39 def ut_gauss(self, img, sigma, dx, dy):
40 return gaussian_filter(numpy.float64(img), sigma, order=[dx, dy])
42 def principal_curvature(self, image, mask):
43 """Computes and returns the Maximum Curvature features for the given input
44 fingervein image"""
46 finger_mask = numpy.zeros(mask.shape)
47 finger_mask[mask == True] = 1 # noqa: E712
49 sigma = numpy.sqrt(self.sigma**2 / 2)
51 gx = self.ut_gauss(image, self.sigma, 1, 0)
52 gy = self.ut_gauss(image, self.sigma, 0, 1)
54 Gmag = numpy.sqrt(gx**2 + gy**2) # Gradient magnitude
56 # Apply threshold
57 gamma = (self.threshold / 100) * numpy.max(Gmag)
59 indices = numpy.where(Gmag < gamma)
61 gx[indices] = 0
62 gy[indices] = 0
64 # Normalize
65 Gmag[numpy.where(Gmag == 0)] = 1 # Avoid dividing by zero
66 gx = gx / Gmag
67 gy = gy / Gmag
69 hxx = self.ut_gauss(gx, sigma, 1, 0)
70 hxy = self.ut_gauss(gx, sigma, 0, 1)
71 hyy = self.ut_gauss(gy, sigma, 0, 1)
73 lambda1 = 0.5 * (
74 hxx
75 + hyy
76 + numpy.sqrt(hxx**2 + hyy**2 - 2 * hxx * hyy + 4 * hxy**2)
77 )
78 veins = lambda1 * finger_mask
80 # Normalise
81 veins = veins - numpy.min(veins[:])
82 veins = veins / numpy.max(veins[:])
84 veins = veins * finger_mask
86 # Binarise the vein image by otsu
87 md = numpy.median(veins[veins > 0])
88 img_veins_bin = veins > md
90 return img_veins_bin.astype(numpy.float64)
92 def __call__(self, image):
93 """Reads the input image, extract the features based on Principal Curvature
94 of the fingervein image, and writes the resulting template"""
96 finger_image = image[
97 0
98 ] # Normalized image with or without histogram equalization
99 finger_mask = image[1]
101 return self.principal_curvature(finger_image, finger_mask)