MaximumCurvature.py 8.32 KB
Newer Older
Pedro TOME's avatar
Pedro TOME committed
1
2
3
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :

4
5
6
import math
import numpy

Pedro TOME's avatar
Pedro TOME committed
7
8
9
import bob.core
import bob.io.base

10
from bob.bio.base.extractor import Extractor
11

Pedro TOME's avatar
Pedro TOME committed
12
13
from .. import utils

14

Pedro TOME's avatar
Pedro TOME committed
15
class MaximumCurvature (Extractor):
Olegs NIKISINS's avatar
Olegs NIKISINS committed
16
17
  """
  MiuraMax feature extractor.
18
19
20
21
22

  Based on N. Miura, A. Nagasaka, and T. Miyatake, Extraction of Finger-Vein
  Pattern Using Maximum Curvature Points in Image Profiles. Proceedings on IAPR
  conference on machine vision applications, 9 (2005), pp. 347--350

Olegs NIKISINS's avatar
Olegs NIKISINS committed
23
  **Parameters:**
24

Olegs NIKISINS's avatar
Olegs NIKISINS committed
25
26
  sigma : :py:class:`int`
      Optional: Sigma used for determining derivatives.
André Anjos's avatar
André Anjos committed
27
  """
Pedro TOME's avatar
Pedro TOME committed
28

29

André Anjos's avatar
André Anjos committed
30
31
  def __init__(self, sigma = 5):
    Extractor.__init__(self, sigma = sigma)
Pedro TOME's avatar
Pedro TOME committed
32
    self.sigma = sigma
33
34
35
36
37
38


  def maximum_curvature(self, image, mask):
    """Computes and returns the Maximum Curvature features for the given input
    fingervein image"""

Pedro TOME's avatar
Pedro TOME committed
39
40
41
42
43
    if image.dtype != numpy.uint8:
       image = bob.core.convert(image,numpy.uint8,(0,255),(0,1))
    #No es necesario pasarlo a uint8, en matlab lo dejan en float64. Comprobar si varian los resultados en vera database y ajustar.

    finger_mask = numpy.zeros(mask.shape)
44
45
    finger_mask[mask == True] = 1

Pedro TOME's avatar
Pedro TOME committed
46
    winsize = numpy.ceil(4*self.sigma)
47

Pedro TOME's avatar
Pedro TOME committed
48
49
50
    x = numpy.arange(-winsize, winsize+1)
    y = numpy.arange(-winsize, winsize+1)
    X, Y = numpy.meshgrid(x, y)
51

Pedro TOME's avatar
Pedro TOME committed
52
53
54
55
56
57
    h = (1/(2*math.pi*self.sigma**2))*numpy.exp(-(X**2 + Y**2)/(2*self.sigma**2))
    hx = (-X/(self.sigma**2))*h
    hxx = ((X**2 - self.sigma**2)/(self.sigma**4))*h
    hy = hx.T
    hyy = hxx.T
    hxy = ((X*Y)/(self.sigma**4))*h
58

Pedro TOME's avatar
Pedro TOME committed
59
    # Do the actual filtering
60

61
62
63
64
65
    fx = utils.imfilter(image, hx)
    fxx = utils.imfilter(image, hxx)
    fy = utils.imfilter(image, hy)
    fyy = utils.imfilter(image, hyy)
    fxy = utils.imfilter(image, hxy)
66

Pedro TOME's avatar
Pedro TOME committed
67
68
69
70
    f1  = 0.5*numpy.sqrt(2)*(fx + fy)   # \  #
    f2  = 0.5*numpy.sqrt(2)*(fx - fy)   # /  #
    f11 = 0.5*fxx + fxy + 0.5*fyy       # \\ #
    f22 = 0.5*fxx - fxy + 0.5*fyy       # // #
71

Pedro TOME's avatar
Pedro TOME committed
72
    img_h, img_w = image.shape  #Image height and width
73

Pedro TOME's avatar
Pedro TOME committed
74
75
76
77
78
79
    # Calculate curvatures
    k = numpy.zeros((img_h, img_w, 4))
    k[:,:,0] = (fxx/((1 + fx**2)**(3/2)))*finger_mask  # hor #
    k[:,:,1] = (fyy/((1 + fy**2)**(3/2)))*finger_mask  # ver #
    k[:,:,2] = (f11/((1 + f1**2)**(3/2)))*finger_mask  # \   #
    k[:,:,3] = (f22/((1 + f2**2)**(3/2)))*finger_mask  # /   #
80

Pedro TOME's avatar
Pedro TOME committed
81
82
83
    # Scores
    Vt = numpy.zeros(image.shape)
    Wr = 0
84

Pedro TOME's avatar
Pedro TOME committed
85
86
    # Horizontal direction
    bla = k[:,:,0] > 0
87
88
    for y in range(0,img_h):
        for x in range(0,img_w):
Pedro TOME's avatar
Pedro TOME committed
89
90
91
92
93
94
95
96
            if (bla[y,x]):
                Wr = Wr + 1
            if ( Wr > 0 and (x == (img_w-1) or not bla[y,x]) ):
                if (x == (img_w-1)):
                    # Reached edge of image
                    pos_end = x
                else:
                    pos_end = x - 1
97
98

                pos_start = pos_end - Wr + 1 # Start pos of concave
Pedro TOME's avatar
Pedro TOME committed
99
100
                if (pos_start == pos_end):
                    I=numpy.argmax(k[y,pos_start,0])
101
                else:
Pedro TOME's avatar
Pedro TOME committed
102
                    I=numpy.argmax(k[y,pos_start:pos_end+1,0])
103

Pedro TOME's avatar
Pedro TOME committed
104
105
106
                pos_max = pos_start + I
                Scr = k[y,pos_max,0]*Wr
                Vt[y,pos_max] = Vt[y,pos_max] + Scr
107
108
                Wr = 0

Pedro TOME's avatar
Pedro TOME committed
109
110
111

    # Vertical direction
    bla = k[:,:,1] > 0
112
113
    for x in range(0,img_w):
        for y in range(0,img_h):
Pedro TOME's avatar
Pedro TOME committed
114
115
116
117
118
119
120
            if (bla[y,x]):
                Wr = Wr + 1
            if ( Wr > 0 and (y == (img_h-1) or not bla[y,x]) ):
                if (y == (img_h-1)):
                    # Reached edge of image
                    pos_end = y
                else:
121
122
                    pos_end = y - 1

Pedro TOME's avatar
Pedro TOME committed
123
124
125
126
127
                pos_start = pos_end - Wr + 1 # Start pos of concave
                if (pos_start == pos_end):
                    I=numpy.argmax(k[pos_start,x,1])
                else:
                    I=numpy.argmax(k[pos_start:pos_end+1,x,1])
128
129

                pos_max = pos_start + I
Pedro TOME's avatar
Pedro TOME committed
130
                Scr = k[pos_max,x,1]*Wr
131

Pedro TOME's avatar
Pedro TOME committed
132
133
                Vt[pos_max,x] = Vt[pos_max,x] + Scr
                Wr = 0
134

Pedro TOME's avatar
Pedro TOME committed
135
136
137
138
139
140
141
142
143
144
145
    # Direction: \ #
    bla = k[:,:,2] > 0
    for start in range(0,img_w+img_h-1):
        # Initial values
        if (start <= img_w-1):
            x = start
            y = 0
        else:
            x = 0
            y = start - img_w + 1
        done = False
146

Pedro TOME's avatar
Pedro TOME committed
147
148
149
        while (not done):
            if(bla[y,x]):
                Wr = Wr + 1
150

Pedro TOME's avatar
Pedro TOME committed
151
152
153
154
155
156
157
158
            if ( Wr > 0 and (y == img_h-1 or x == img_w-1 or not bla[y,x]) ):
                if (y == img_h-1 or x == img_w-1):
                    # Reached edge of image
                    pos_x_end = x
                    pos_y_end = y
                else:
                    pos_x_end = x - 1
                    pos_y_end = y - 1
159

Pedro TOME's avatar
Pedro TOME committed
160
161
                pos_x_start = pos_x_end - Wr + 1
                pos_y_start = pos_y_end - Wr + 1
162

Pedro TOME's avatar
Pedro TOME committed
163
164
165
166
167
168
169
170
                if (pos_y_start == pos_y_end and pos_x_start == pos_x_end):
                    d = k[pos_y_start, pos_x_start, 2]
                elif (pos_y_start == pos_y_end):
                    d = numpy.diag(k[pos_y_start, pos_x_start:pos_x_end+1, 2])
                elif (pos_x_start == pos_x_end):
                    d = numpy.diag(k[pos_y_start:pos_y_end+1, pos_x_start, 2])
                else:
                    d = numpy.diag(k[pos_y_start:pos_y_end+1, pos_x_start:pos_x_end+1, 2])
171
172
173
174
175
176

                I = numpy.argmax(d)

                pos_x_max = pos_x_start + I
                pos_y_max = pos_y_start + I

Pedro TOME's avatar
Pedro TOME committed
177
                Scr = k[pos_y_max,pos_x_max,2]*Wr
178

Pedro TOME's avatar
Pedro TOME committed
179
180
                Vt[pos_y_max,pos_x_max] = Vt[pos_y_max,pos_x_max] + Scr
                Wr = 0
181

Pedro TOME's avatar
Pedro TOME committed
182
183
184
185
186
            if((x == img_w-1) or (y == img_h-1)):
                done = True
            else:
                x = x + 1
                y = y + 1
187

Pedro TOME's avatar
Pedro TOME committed
188
189
190
191
192
193
194
195
196
197
198
    # Direction: /
    bla = k[:,:,3] > 0
    for start in range(0,img_w+img_h-1):
        # Initial values
        if (start <= (img_w-1)):
            x = start
            y = img_h-1
        else:
            x = 0
            y = img_w+img_h-start-1
        done = False
199

Pedro TOME's avatar
Pedro TOME committed
200
201
202
203
204
205
206
207
208
209
210
        while (not done):
            if(bla[y,x]):
                Wr = Wr + 1
            if ( Wr > 0 and (y == 0 or x == img_w-1 or not bla[y,x]) ):
                if (y == 0 or x == img_w-1):
                    # Reached edge of image
                    pos_x_end = x
                    pos_y_end = y
                else:
                    pos_x_end = x - 1
                    pos_y_end = y + 1
211

Pedro TOME's avatar
Pedro TOME committed
212
213
                pos_x_start = pos_x_end - Wr + 1
                pos_y_start = pos_y_end + Wr - 1
214

Pedro TOME's avatar
Pedro TOME committed
215
216
217
218
219
220
221
222
                if (pos_y_start == pos_y_end and pos_x_start == pos_x_end):
                    d = k[pos_y_end, pos_x_start, 3]
                elif (pos_y_start == pos_y_end):
                    d = numpy.diag(numpy.flipud(k[pos_y_end, pos_x_start:pos_x_end+1, 3]))
                elif (pos_x_start == pos_x_end):
                    d = numpy.diag(numpy.flipud(k[pos_y_end:pos_y_start+1, pos_x_start, 3]))
                else:
                    d = numpy.diag(numpy.flipud(k[pos_y_end:pos_y_start+1, pos_x_start:pos_x_end+1, 3]))
223
224
225
226

                I = numpy.argmax(d)
                pos_x_max = pos_x_start + I
                pos_y_max = pos_y_start - I
Pedro TOME's avatar
Pedro TOME committed
227
228
229
                Scr = k[pos_y_max,pos_x_max,3]*Wr
                Vt[pos_y_max,pos_x_max] = Vt[pos_y_max,pos_x_max] + Scr
                Wr = 0
230

Pedro TOME's avatar
Pedro TOME committed
231
232
233
234
            if((x == img_w-1) or (y == 0)):
                done = True
            else:
                x = x + 1
235
                y = y - 1
Pedro TOME's avatar
Pedro TOME committed
236
237
238
239
240
241
242
243
244

    ## Connection of vein centres
    Cd = numpy.zeros((img_h, img_w, 4))
    for x in range(2,img_w-3):
        for y in range(2,img_h-3):
            Cd[y,x,0] = min(numpy.amax(Vt[y,x+1:x+3]), numpy.amax(Vt[y,x-2:x]))   # Hor  #
            Cd[y,x,1] = min(numpy.amax(Vt[y+1:y+3,x]), numpy.amax(Vt[y-2:y,x]))   # Vert #
            Cd[y,x,2] = min(numpy.amax(Vt[y-2:y,x-2:x]), numpy.amax(Vt[y+1:y+3,x+1:x+3])) # \  #
            Cd[y,x,3] = min(numpy.amax(Vt[y+1:y+3,x-2:x]), numpy.amax(Vt[y-2:y,x+1:x+3])) # /  #
245

Pedro TOME's avatar
Pedro TOME committed
246
247
    #Veins
    img_veins = numpy.amax(Cd,axis=2)
248

Pedro TOME's avatar
Pedro TOME committed
249
250
251
252
253
    # Binarise the vein image
    md = numpy.median(img_veins[img_veins>0])
    img_veins_bin = img_veins > md

    return img_veins_bin.astype(numpy.float64)
254
255
256


  def __call__(self, image):
Pedro TOME's avatar
Pedro TOME committed
257
    """Reads the input image, extract the features based on Maximum Curvature of the fingervein image, and writes the resulting template"""
258

André Anjos's avatar
André Anjos committed
259
    finger_image = image[0] #Normalized image with or without histogram equalization
260
261
262
    finger_mask = image[1]

    return self.maximum_curvature(finger_image, finger_mask)