MiuraMatch.py 3.05 KB
Newer Older
Pedro TOME's avatar
Pedro TOME committed
1
2
3
4
5
6
7
8
9
10
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :

import bob.sp
import bob.ip.base

import numpy
import math
import scipy.signal

11
from bob.bio.base.algorithm import Algorithm
Pedro TOME's avatar
Pedro TOME committed
12

13
14
15
16
17
18
19
20

class MiuraMatch (Algorithm):
  """Finger vein matching: match ratio

  Based on N. Miura, A. Nagasaka, and T. Miyatake. Feature extraction of finger
  vein patterns based on repeated line tracking and its application to personal
  identification. Machine Vision and Applications, Vol. 15, Num. 4, pp.
  194--203, 2004
21
22
23
24
25
26
27
28
29
30


  Parameters:

    ch (int, Optional): Maximum search displacement in y-direction. Different
      defult values based on the different features.

    cw (int, Optional): Maximum search displacement in x-direction. Different
      defult values based on the different features.

Pedro TOME's avatar
Pedro TOME committed
31
32
  """

33
  def __init__(self,
Pedro TOME's avatar
Pedro TOME committed
34
35
      ch = 8,       # Maximum search displacement in y-direction
      cw = 5,       # Maximum search displacement in x-direction
36
      ):
Pedro TOME's avatar
Pedro TOME committed
37
38

    # call base class constructor
39
    Algorithm.__init__(
Pedro TOME's avatar
Pedro TOME committed
40
41
42
43
44
45
46
47
48
49
50
51
        self,

        ch = ch,
        cw = cw,

        multiple_model_scoring = None,
        multiple_probe_scoring = None
    )

    self.ch = ch
    self.cw = cw

52

Pedro TOME's avatar
Pedro TOME committed
53
54
  def enroll(self, enroll_features):
    """Enrolls the model by computing an average graph for each model"""
55

Pedro TOME's avatar
Pedro TOME committed
56
57
58
59
60
61
62
63
64
    # return the generated model
    return numpy.array(enroll_features)


  def convfft(self, t, a):
    # Determine padding size in x and y dimension
    size_t  = numpy.array(t.shape)
    size_a  = numpy.array(a.shape)
    outsize = size_t + size_a - 1
65

Pedro TOME's avatar
Pedro TOME committed
66
67
68
69
70
71
72
    # Determine 2D cross correlation in Fourier domain
    taux = numpy.zeros(outsize)
    taux[0:size_t[0],0:size_t[1]] = t
    Ft = bob.sp.fft(taux.astype(numpy.complex128))
    aaux = numpy.zeros(outsize)
    aaux[0:size_a[0],0:size_a[1]] = a
    Fa = bob.sp.fft(aaux.astype(numpy.complex128))
73

Pedro TOME's avatar
Pedro TOME committed
74
    convta = numpy.real(bob.sp.ifft(Ft*Fa))
75

Pedro TOME's avatar
Pedro TOME committed
76
77
    [w, h] = size_t-size_a+1
    output = convta[size_a[0]-1:size_a[0]-1+w, size_a[1]-1:size_a[1]-1+h]
78

Pedro TOME's avatar
Pedro TOME committed
79
80
81
82
83
84
85
86
87
    return output


  def score(self, model, probe):
    """Computes the score of the probe and the model
         Return score - Value between 0 and 0.5, larger value is better match
    """
    #print model.shape
    #print probe.shape
88

Pedro TOME's avatar
Pedro TOME committed
89
    I=probe.astype(numpy.float64)
90
91

    if len(model.shape) == 2:
Pedro TOME's avatar
Pedro TOME committed
92
      model = numpy.array([model])
93

Pedro TOME's avatar
Pedro TOME committed
94
95
96
97
98
99
100
101
102
    n_models = model.shape[0]

    scores = []
    for i in range(n_models):
      R=model[i,:].astype(numpy.float64)
      h, w = R.shape
      crop_R = R[self.ch:h-self.ch, self.cw:w-self.cw]
      rotate_R = numpy.zeros((crop_R.shape[0], crop_R.shape[1]))
      bob.ip.base.rotate(crop_R, rotate_R, 180)
103
      #FFT for scoring!
Pedro TOME's avatar
Pedro TOME committed
104
      #Nm=bob.sp.ifft(bob.sp.fft(I)*bob.sp.fft(rotate_R))
André Anjos's avatar
André Anjos committed
105
106
      Nm = self.convfft(I, rotate_R)
      #Nm2 = scipy.signal.convolve2d(I, rotate_R, 'valid')
107

Pedro TOME's avatar
Pedro TOME committed
108
109
110
      t0, s0 = numpy.unravel_index(Nm.argmax(), Nm.shape)
      Nmm = Nm[t0,s0]
      #Nmm = Nm.max()
111
      #mi = numpy.argwhere(Nmm == Nm)
Pedro TOME's avatar
Pedro TOME committed
112
113
      #t0, s0 = mi.flatten()[:2]
      scores.append(Nmm/(sum(sum(crop_R)) + sum(sum(I[t0:t0+h-2*self.ch, s0:s0+w-2*self.cw]))))
114

Pedro TOME's avatar
Pedro TOME committed
115
    return numpy.mean(scores)