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))
André Anjos's avatar
André Anjos committed
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)