MiuraMatch.py 2.77 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
      ch = 8,       # Maximum search displacement in y-direction
      cw = 5,       # Maximum search displacement in x-direction
26
      ):
Pedro TOME's avatar
Pedro TOME committed
27 28

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

        ch = ch,
        cw = cw,

        multiple_model_scoring = None,
        multiple_probe_scoring = None
    )

    self.ch = ch
    self.cw = cw

42

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

Pedro TOME's avatar
Pedro TOME committed
46 47 48 49 50 51 52 53 54
    # 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
55

Pedro TOME's avatar
Pedro TOME committed
56 57 58 59 60 61 62
    # 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))
63

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

Pedro TOME's avatar
Pedro TOME committed
66 67
    [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]
68

Pedro TOME's avatar
Pedro TOME committed
69 70 71 72 73 74 75 76 77
    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
78

Pedro TOME's avatar
Pedro TOME committed
79
    I=probe.astype(numpy.float64)
80 81

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

Pedro TOME's avatar
Pedro TOME committed
84 85 86 87 88 89 90 91 92
    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)
93
      #FFT for scoring!
Pedro TOME's avatar
Pedro TOME committed
94
      #Nm=bob.sp.ifft(bob.sp.fft(I)*bob.sp.fft(rotate_R))
95 96
      Nm = self.convfft(I, rotate_R)
      #Nm2 = scipy.signal.convolve2d(I, rotate_R, 'valid')
97

Pedro TOME's avatar
Pedro TOME committed
98 99 100
      t0, s0 = numpy.unravel_index(Nm.argmax(), Nm.shape)
      Nmm = Nm[t0,s0]
      #Nmm = Nm.max()
101
      #mi = numpy.argwhere(Nmm == Nm)
Pedro TOME's avatar
Pedro TOME committed
102 103
      #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]))))
104

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