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.
27
  """
Pedro TOME's avatar
Pedro TOME committed
28

29

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

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)