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

1#!/usr/bin/env python 

2# vim: set fileencoding=utf-8 : 

3 

4import numpy 

5 

6from scipy.ndimage import gaussian_filter 

7 

8from bob.bio.base.extractor import Extractor 

9 

10 

11class PrincipalCurvature(Extractor): 

12 """MiuraMax feature extractor 

13 

14 Based on [CW09]_. 

15 """ 

16 

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 ) 

34 

35 # block parameters 

36 self.sigma = sigma 

37 self.threshold = threshold 

38 

39 def ut_gauss(self, img, sigma, dx, dy): 

40 return gaussian_filter(numpy.float64(img), sigma, order=[dx, dy]) 

41 

42 def principal_curvature(self, image, mask): 

43 """Computes and returns the Maximum Curvature features for the given input 

44 fingervein image""" 

45 

46 finger_mask = numpy.zeros(mask.shape) 

47 finger_mask[mask == True] = 1 # noqa: E712 

48 

49 sigma = numpy.sqrt(self.sigma**2 / 2) 

50 

51 gx = self.ut_gauss(image, self.sigma, 1, 0) 

52 gy = self.ut_gauss(image, self.sigma, 0, 1) 

53 

54 Gmag = numpy.sqrt(gx**2 + gy**2) # Gradient magnitude 

55 

56 # Apply threshold 

57 gamma = (self.threshold / 100) * numpy.max(Gmag) 

58 

59 indices = numpy.where(Gmag < gamma) 

60 

61 gx[indices] = 0 

62 gy[indices] = 0 

63 

64 # Normalize 

65 Gmag[numpy.where(Gmag == 0)] = 1 # Avoid dividing by zero 

66 gx = gx / Gmag 

67 gy = gy / Gmag 

68 

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) 

72 

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 

79 

80 # Normalise 

81 veins = veins - numpy.min(veins[:]) 

82 veins = veins / numpy.max(veins[:]) 

83 

84 veins = veins * finger_mask 

85 

86 # Binarise the vein image by otsu 

87 md = numpy.median(veins[veins > 0]) 

88 img_veins_bin = veins > md 

89 

90 return img_veins_bin.astype(numpy.float64) 

91 

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""" 

95 

96 finger_image = image[ 

97 0 

98 ] # Normalized image with or without histogram equalization 

99 finger_mask = image[1] 

100 

101 return self.principal_curvature(finger_image, finger_mask)