MiuraMatch.py 3.09 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
Pedro TOME's avatar
Pedro TOME committed
21
22
  """

23
  def __init__(self,
Pedro TOME's avatar
Pedro TOME committed
24
25
26
27
      # some similarity functions might need a GaborWaveletTransform class, so we have to provide the parameters here as well...
      ch = 8,       # Maximum search displacement in y-direction
      cw = 5,       # Maximum search displacement in x-direction
      gpu = False,
28
      ):
Pedro TOME's avatar
Pedro TOME committed
29
30

    # call base class constructor
31
    Algorithm.__init__(
Pedro TOME's avatar
Pedro TOME committed
32
33
34
35
36
37
38
39
40
41
42
43
44
        self,

        ch = ch,
        cw = cw,

        multiple_model_scoring = None,
        multiple_probe_scoring = None
    )

    self.ch = ch
    self.cw = cw
    self.gpu = gpu

45

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

Pedro TOME's avatar
Pedro TOME committed
49
50
51
52
53
54
55
56
57
    # 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
58

Pedro TOME's avatar
Pedro TOME committed
59
60
61
62
63
64
65
    # 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))
66

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

Pedro TOME's avatar
Pedro TOME committed
69
70
    [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]
71

Pedro TOME's avatar
Pedro TOME committed
72
73
74
75
76
77
78
79
80
    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
81

Pedro TOME's avatar
Pedro TOME committed
82
    I=probe.astype(numpy.float64)
83
84

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

Pedro TOME's avatar
Pedro TOME committed
87
88
89
90
91
92
93
94
95
    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)
96
      #FFT for scoring!
Pedro TOME's avatar
Pedro TOME committed
97
98
99
100
101
102
103
104
      #Nm=bob.sp.ifft(bob.sp.fft(I)*bob.sp.fft(rotate_R))
      if self.gpu == True:
          Nm = self.convfft(I, rotate_R)
          #import xbob.cusp
          #Nm = xbob.cusp.conv(I, rotate_R);
      else:
          Nm = self.convfft(I, rotate_R)
          #Nm2 = scipy.signal.convolve2d(I, rotate_R, 'valid')
105

Pedro TOME's avatar
Pedro TOME committed
106
107
108
      t0, s0 = numpy.unravel_index(Nm.argmax(), Nm.shape)
      Nmm = Nm[t0,s0]
      #Nmm = Nm.max()
109
      #mi = numpy.argwhere(Nmm == Nm)
Pedro TOME's avatar
Pedro TOME committed
110
111
      #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]))))
112

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