MiuraMatch.py 3.12 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


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

Olegs NIKISINS's avatar
Olegs NIKISINS committed
25 26
  ch : :py:class:`int`
      Optional : Maximum search displacement in y-direction. Different
27 28
      defult values based on the different features.

Olegs NIKISINS's avatar
Olegs NIKISINS committed
29 30
  cw : :py:class:`int`
      Optional : Maximum search displacement in x-direction. Different
31
      defult values based on the different features.
Pedro TOME's avatar
Pedro TOME committed
32 33
  """

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

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

        ch = ch,
        cw = cw,

        multiple_model_scoring = None,
        multiple_probe_scoring = None
    )

    self.ch = ch
    self.cw = cw

53

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

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

Pedro TOME's avatar
Pedro TOME committed
67 68 69 70 71 72 73
    # 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))
74

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

Pedro TOME's avatar
Pedro TOME committed
77 78
    [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]
79

Pedro TOME's avatar
Pedro TOME committed
80 81 82 83
    return output


  def score(self, model, probe):
Olegs NIKISINS's avatar
Olegs NIKISINS committed
84 85 86 87 88 89 90
    """
    Computes the score of the probe and the model.

    **Parameters:**

    score : :py:class:`float`
        Value between 0 and 0.5, larger value is better match
Pedro TOME's avatar
Pedro TOME committed
91 92 93
    """
    #print model.shape
    #print probe.shape
94

Pedro TOME's avatar
Pedro TOME committed
95
    I=probe.astype(numpy.float64)
96 97

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

Pedro TOME's avatar
Pedro TOME committed
100 101 102 103 104 105 106 107 108
    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)
109
      #FFT for scoring!
Pedro TOME's avatar
Pedro TOME committed
110
      #Nm=bob.sp.ifft(bob.sp.fft(I)*bob.sp.fft(rotate_R))
111 112
      Nm = self.convfft(I, rotate_R)
      #Nm2 = scipy.signal.convolve2d(I, rotate_R, 'valid')
113

Pedro TOME's avatar
Pedro TOME committed
114 115 116
      t0, s0 = numpy.unravel_index(Nm.argmax(), Nm.shape)
      Nmm = Nm[t0,s0]
      #Nmm = Nm.max()
117
      #mi = numpy.argwhere(Nmm == Nm)
Pedro TOME's avatar
Pedro TOME committed
118 119
      #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]))))
120

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