Coverage for src/bob/bio/vein/extractor/WideLineDetector.py: 100%
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
5import scipy
7from PIL import Image
9from bob.bio.base.extractor import Extractor
12class WideLineDetector(Extractor):
13 """Wide Line Detector feature extractor
15 Based on B. Huang, Y. Dai, R. Li, D. Tang and W. Li. [HDLTL10]_
16 """
18 def __init__(
19 self,
20 radius=5, # Radius of the circular neighbourhood region
21 threshold=1, # Neigborhood threshold
22 g=41, # Sum of neigbourhood threshold
23 rescale=True,
24 ):
25 # call base class constructor
26 Extractor.__init__(
27 self,
28 radius=radius,
29 threshold=threshold,
30 g=g,
31 rescale=rescale,
32 )
34 # block parameters
35 self.radius = radius
36 self.threshold = threshold
37 self.g = g
38 self.rescale = rescale
40 def wide_line_detector(self, finger_image, mask):
41 """Computes and returns the Wide Line Detector features for the given input
42 fingervein image"""
44 finger_image = finger_image.astype(numpy.float64)
46 finger_mask = numpy.zeros(mask.shape)
47 finger_mask[mask == True] = 1 # noqa: E712
49 # Rescale image if required
50 if self.rescale:
51 scaling_factor = 0.24
53 new_size = tuple(
54 (numpy.array(finger_image.shape) * scaling_factor).astype(int)
55 )
56 finger_image = numpy.array(
57 Image.fromarray(finger_image).resize(size=new_size)
58 ).T
60 new_size = tuple(
61 (numpy.array(finger_mask.shape) * scaling_factor).astype(int)
62 )
63 finger_mask = numpy.array(
64 Image.fromarray(finger_mask).resize(size=new_size)
65 ).T
67 # To eliminate residuals from the scalation of the binary mask
68 finger_mask = scipy.ndimage.binary_dilation(
69 finger_mask, structure=numpy.ones((1, 1))
70 ).astype(int)
72 x = numpy.arange((-1) * self.radius, self.radius + 1)
73 y = numpy.arange((-1) * self.radius, self.radius + 1)
74 X, Y = numpy.meshgrid(x, y)
76 N = X**2 + Y**2 <= self.radius**2 # Neighbourhood mask
78 img_h, img_w = finger_image.shape # Image height and width
80 veins = numpy.zeros(finger_image.shape)
82 for y in range(self.radius, img_h - self.radius):
83 for x in range(self.radius, img_w - self.radius):
84 s = (
85 finger_image[
86 y - self.radius : y + self.radius + 1,
87 x - self.radius : x + self.radius + 1,
88 ]
89 - finger_image[y, x]
90 ) <= self.threshold
91 m = (s * N).sum()
92 veins[y, x] = float(m <= self.g)
94 # Mask the vein image with the finger region
95 img_veins_bin = veins * finger_mask
97 return img_veins_bin
99 def __call__(self, image):
100 """Reads the input image, extract the features based on Wide Line Detector
101 of the fingervein image, and writes the resulting template"""
102 # For debugging
104 finger_image = image[0] # Normalized image with histogram equalization
105 finger_mask = image[1]
107 return self.wide_line_detector(finger_image, finger_mask)