Skip to content
Snippets Groups Projects
Commit 68a56f1b authored by André Anjos's avatar André Anjos :speech_balloon:
Browse files

Implemented normalized-cross-correlation algorithm

parent 46073599
No related branches found
No related tags found
1 merge request!353DFV and multiple fixes
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
import numpy
import skimage.feature
from bob.bio.base.algorithm import Algorithm
class Correlate (Algorithm):
"""Correlate probe and model without cropping
The method is based on "cross-correlation" between a model and a probe image.
The difference between this and :py:class:`MiuraMatch` is that **no**
cropping takes place on this implementation. We simply fill the excess
boundary with zeros and extract the valid correlation region between the
probe and the model using :py:func:`skimage.feature.match_template`.
"""
def __init__(self):
# call base class constructor
Algorithm.__init__(
self,
multiple_model_scoring = None,
multiple_probe_scoring = None
)
def enroll(self, enroll_features):
"""Enrolls the model by computing an average graph for each model"""
# return the generated model
return numpy.array(enroll_features)
def score(self, model, probe):
"""Computes the score between the probe and the model.
Parameters:
model (numpy.ndarray): The model of the user to test the probe agains
probe (numpy.ndarray): The probe to test
Returns:
float: Value between 0 and 0.5, larger value means a better match
"""
I=probe.astype(numpy.float64)
if len(model.shape) == 2:
model = numpy.array([model])
scores = []
# iterate over all models for a given individual
for md in model:
R = md.astype(numpy.float64)
Nm = skimage.feature.match_template(I, R)
# figures out where the maximum is on the resulting matrix
t0, s0 = numpy.unravel_index(Nm.argmax(), Nm.shape)
# this is our output
scores.append(Nm[t0,s0])
return numpy.mean(scores)
...@@ -94,8 +94,6 @@ class MiuraMatch (Algorithm): ...@@ -94,8 +94,6 @@ class MiuraMatch (Algorithm):
if len(model.shape) == 2: if len(model.shape) == 2:
model = numpy.array([model]) model = numpy.array([model])
n_models = model.shape[0]
scores = [] scores = []
# iterate over all models for a given individual # iterate over all models for a given individual
...@@ -103,7 +101,7 @@ class MiuraMatch (Algorithm): ...@@ -103,7 +101,7 @@ class MiuraMatch (Algorithm):
# erode model by (ch, cw) # erode model by (ch, cw)
R = md.astype(numpy.float64) R = md.astype(numpy.float64)
h, w = R.shape h, w = R.shape #same as I
crop_R = R[self.ch:h-self.ch, self.cw:w-self.cw] crop_R = R[self.ch:h-self.ch, self.cw:w-self.cw]
# correlates using scipy - fastest option available iff the self.ch and # correlates using scipy - fastest option available iff the self.ch and
...@@ -127,6 +125,6 @@ class MiuraMatch (Algorithm): ...@@ -127,6 +125,6 @@ class MiuraMatch (Algorithm):
# normalizes the output by the number of pixels lit on the input # normalizes the output by the number of pixels lit on the input
# matrices, taking into consideration the surface that produced the # matrices, taking into consideration the surface that produced the
# result (i.e., the eroded model and part of the probe) # result (i.e., the eroded model and part of the probe)
scores.append(Nmm/(sum(sum(crop_R)) + sum(sum(I[t0:t0+h-2*self.ch, s0:s0+w-2*self.cw])))) scores.append(Nmm/(crop_R.sum() + I[t0:t0+h-2*self.ch, s0:s0+w-2*self.cw].sum()))
return numpy.mean(scores) return numpy.mean(scores)
from .MiuraMatch import MiuraMatch from .MiuraMatch import MiuraMatch
from .Correlate import Correlate
from .HammingDistance import HammingDistance
# gets sphinx autodoc done right - don't remove it # gets sphinx autodoc done right - don't remove it
def __appropriate__(*args):
"""Says object was actually declared here, an not on the import module.
Parameters:
*args: An iterable of objects to modify
Resolves `Sphinx referencing issues
<https://github.com/sphinx-doc/sphinx/issues/3048>`
"""
for obj in args: obj.__module__ = __name__
__appropriate__(
MiuraMatch,
Correlate,
HammingDistance,
)
__all__ = [_ for _ in dir() if not _.startswith('_')] __all__ = [_ for _ in dir() if not _.startswith('_')]
...@@ -343,6 +343,25 @@ def test_miura_match(): ...@@ -343,6 +343,25 @@ def test_miura_match():
assert numpy.isclose(score_imp, 0.172906739278421) assert numpy.isclose(score_imp, 0.172906739278421)
def test_correlate():
#Match Ratio method against Matlab reference
template_filename = F(('algorithms', '0001_2_1_120509-135338.mat'))
probe_gen_filename = F(('algorithms', '0001_2_2_120509-135558.mat'))
probe_imp_filename = F(('algorithms', '0003_2_1_120509-141255.mat'))
template_vein = bob.io.base.load(template_filename)
probe_gen_vein = bob.io.base.load(probe_gen_filename)
probe_imp_vein = bob.io.base.load(probe_imp_filename)
from ..algorithm.Correlate import Correlate
C = Correlate()
score_gen = C.score(template_vein, probe_gen_vein)
# we don't check here - no templates
def test_assert_points(): def test_assert_points():
# Tests that point assertion works as expected # Tests that point assertion works as expected
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment