Commit 331df584 authored by André Anjos's avatar André Anjos 💬

[extractors] Porting and cleanup

parent ebc2f696
#!/usr/bin/env python
# Pedro Tome <Pedro.Tome@idiap.ch>
import configurations
import tools
import preprocessing
import features
import tests
import script
#import utils
# vim: set fileencoding=utf-8 :
def get_config():
"""Returns a string containing the configuration information.
"""
import pkg_resources
packages = pkg_resources.require(__name__)
this = packages[0]
deps = packages[1:]
retval = "%s: %s (%s)\n" % (this.key, this.version, this.location)
retval += " - python dependencies:\n"
for d in deps: retval += " - %s: %s (%s)\n" % (d.key, d.version, d.location)
return retval.strip()
import bob.extension
return bob.extension.get_config(__name__)
# gets sphinx autodoc done right - don't remove it
__all__ = [_ for _ in dir() if not _.startswith('_')]
......@@ -5,18 +5,14 @@
import bob.ip.base
import bob.io.base
import numpy
import math
#from math import pi
#from mumpy import sqrt
import scipy.signal
from facereclib.features.Extractor import Extractor
from .. import utils
#from facereclib.utils import histogram
from bob.bio.base.features.Extractor import Extractor
class LocalBinaryPatterns (Extractor):
"""LBP feature extractor, paramters fixed based on
L. Mirmohamadsadeghi and A. Drygajlo. Palm vein recognition uisng local texture patterns, IET Biometrics, pp. 1-9, 2013.
"""LBP feature extractor
Parameters fixed based on L. Mirmohamadsadeghi and A. Drygajlo. Palm vein
recognition uisng local texture patterns, IET Biometrics, pp. 1-9, 2013.
"""
def __init__(
......@@ -34,9 +30,8 @@ class LocalBinaryPatterns (Extractor):
lbp_add_average = False,
# histogram options
sparse_histogram = False,
split_histogram = None
):
split_histogram = None,
):
# call base class constructor
Extractor.__init__(
......@@ -53,15 +48,15 @@ class LocalBinaryPatterns (Extractor):
lbp_compare_to_average = lbp_compare_to_average,
lbp_add_average = lbp_add_average,
sparse_histogram = sparse_histogram,
split_histogram = split_histogram
)
split_histogram = split_histogram,
)
# block parameters
self.m_block_size = block_size if isinstance(block_size, (tuple, list)) else (block_size, block_size)
self.m_block_overlap = block_overlap if isinstance(block_overlap, (tuple, list)) else (block_overlap, block_overlap)
if self.m_block_size[0] < self.m_block_overlap[0] or self.m_block_size[1] < self.m_block_overlap[1]:
raise ValueError("The overlap is bigger than the block size. This won't work. Please check your setup!")
self.m_lbp = bob.ip.base.LBP(
neighbors = lbp_neighbor_count,
radius = float(lbp_radius),
......@@ -70,76 +65,78 @@ class LocalBinaryPatterns (Extractor):
add_average_bit = lbp_add_average,
uniform = lbp_uniform,
rotation_invariant = lbp_rotation_invariant,
border_handling = 'wrap'
)
border_handling = 'wrap',
)
self.m_split = split_histogram
self.m_sparse = sparse_histogram
if self.m_sparse and self.m_split:
raise ValueError("Sparse histograms cannot be split! Check your setup!")
raise ValueError("Sparse histograms cannot be split! Check your setup.")
def __fill__(self, lbphs_array, lbphs_blocks, j):
"""Copies the given array into the given blocks"""
# fill array in the desired shape
#For debugging
#import ipdb; ipdb.set_trace()
#For debugging
#import ipdb; ipdb.set_trace()
for b in range(self.m_n_blocks):
lbphs_array[b * self.m_n_bins : (b+1) * self.m_n_bins] = lbphs_blocks[b][:]
def lbp_features(self, finger_image, mask):
"""Computes and returns the LBP features for the given input fingervein image"""
# For debugging
#import ipdb; ipdb.set_trace()
"""Computes and returns the LBP features for the given input fingervein
image"""
# For debugging
#import ipdb; ipdb.set_trace()
finger_image = finger_image.astype(numpy.float64)
finger_mask = numpy.zeros(mask.shape)
finger_mask[mask == True] = 1
finger_mask[mask == True] = 1
# Mask the vein image with the finger region
finger_image = finger_image*finger_mask
finger_image = finger_image*finger_mask
# Computes LBP histograms
abs_blocks = bob.ip.base.lbphs(finger_image, self.m_lbp, self.m_block_size, self.m_block_overlap)
# Converts to Blitz array (of different dimensionalities)
self.m_n_bins = abs_blocks.shape[1]
self.m_n_blocks = abs_blocks.shape[0]
shape = self.m_n_bins * self.m_n_blocks
# create new array
# create new array
lbphs_array = numpy.zeros(shape, 'float64')
#For debugging
#import ipdb; ipdb.set_trace()
#For debugging
#import ipdb; ipdb.set_trace()
# fill the array with the absolute values of the Gabor wavelet transform
self.__fill__(lbphs_array, abs_blocks, 0)
# return the concatenated list of all histograms
return lbphs_array
def __call__(self, image):
def __call__(self, image):
"""Reads the input image, extract the features based on LBP of the fingervein image, and writes the resulting template"""
#For debugging
#For debugging
finger_image = image[0] #Normalized image with histogram equalization
finger_mask = image[1]
return self.lbp_features(finger_image, finger_mask)
finger_mask = image[1]
return self.lbp_features(finger_image, finger_mask)
def save_feature(self, feature, feature_file):
f = bob.io.base.HDF5File(feature_file, 'w')
f.set('feature', feature)
def read_feature(self, feature_file):
f = bob.io.base.HDF5File(feature_file, 'r')
image = f.read('feature')
return (image)
\ No newline at end of file
return image
......@@ -2,25 +2,26 @@
# vim: set fileencoding=utf-8 :
# Pedro Tome <Pedro.Tome@idiap.ch>
import math
import numpy
import bob.core
import bob.io.base
import numpy
import math
#from math import pi
#from mumpy import sqrt
import scipy.signal
from facereclib.features.Extractor import Extractor
from bob.bio.base.features.Extractor import Extractor
from .. import utils
class MaximumCurvature (Extractor):
"""MiuraMax feature extractor based on
N. Miura, A. Nagasaka, and T. Miyatake, Extraction of Finger-Vein Pattern Using Maximum Curvature Points in Image Profiles.
Proceedings on IAPR conference on machine vision applications, 9 (2005), pp. 347--350
"""MiuraMax feature extractor
Based on N. Miura, A. Nagasaka, and T. Miyatake, Extraction of Finger-Vein
Pattern Using Maximum Curvature Points in Image Profiles. Proceedings on IAPR
conference on machine vision applications, 9 (2005), pp. 347--350
"""
def __init__(
self,
sigma = 5, #Sigma used for determining derivatives
......@@ -33,65 +34,66 @@ class MaximumCurvature (Extractor):
sigma = sigma,
gpu = gpu
)
# block parameters
self.sigma = sigma
self.gpu = gpu
def maximum_curvature(self, image, mask):
"""Computes and returns the Maximum Curvature features for the given input fingervein image"""
def maximum_curvature(self, image, mask):
"""Computes and returns the Maximum Curvature features for the given input
fingervein image"""
if image.dtype != numpy.uint8:
image = bob.core.convert(image,numpy.uint8,(0,255),(0,1))
#No es necesario pasarlo a uint8, en matlab lo dejan en float64. Comprobar si varian los resultados en vera database y ajustar.
finger_mask = numpy.zeros(mask.shape)
finger_mask[mask == True] = 1
finger_mask[mask == True] = 1
winsize = numpy.ceil(4*self.sigma)
x = numpy.arange(-winsize, winsize+1)
y = numpy.arange(-winsize, winsize+1)
X, Y = numpy.meshgrid(x, y)
h = (1/(2*math.pi*self.sigma**2))*numpy.exp(-(X**2 + Y**2)/(2*self.sigma**2))
hx = (-X/(self.sigma**2))*h
hxx = ((X**2 - self.sigma**2)/(self.sigma**4))*h
hy = hx.T
hyy = hxx.T
hxy = ((X*Y)/(self.sigma**4))*h
# Do the actual filtering
fx = utils.imfilter(image, hx, self.gpu, conv=False)
fxx = utils.imfilter(image, hxx, self.gpu, conv=False)
fy = utils.imfilter(image, hy, self.gpu, conv=False)
fyy = utils.imfilter(image, hyy, self.gpu, conv=False)
fxy = utils.imfilter(image, hxy, self.gpu, conv=False)
f1 = 0.5*numpy.sqrt(2)*(fx + fy) # \ #
f2 = 0.5*numpy.sqrt(2)*(fx - fy) # / #
f11 = 0.5*fxx + fxy + 0.5*fyy # \\ #
f22 = 0.5*fxx - fxy + 0.5*fyy # // #
img_h, img_w = image.shape #Image height and width
# Calculate curvatures
k = numpy.zeros((img_h, img_w, 4))
k[:,:,0] = (fxx/((1 + fx**2)**(3/2)))*finger_mask # hor #
k[:,:,1] = (fyy/((1 + fy**2)**(3/2)))*finger_mask # ver #
k[:,:,2] = (f11/((1 + f1**2)**(3/2)))*finger_mask # \ #
k[:,:,3] = (f22/((1 + f2**2)**(3/2)))*finger_mask # / #
# Scores
Vt = numpy.zeros(image.shape)
Wr = 0
# Horizontal direction
bla = k[:,:,0] > 0
for y in range(0,img_h):
for x in range(0,img_w):
for y in range(0,img_h):
for x in range(0,img_w):
if (bla[y,x]):
Wr = Wr + 1
if ( Wr > 0 and (x == (img_w-1) or not bla[y,x]) ):
......@@ -100,23 +102,23 @@ class MaximumCurvature (Extractor):
pos_end = x
else:
pos_end = x - 1
pos_start = pos_end - Wr + 1 # Start pos of concave
pos_start = pos_end - Wr + 1 # Start pos of concave
if (pos_start == pos_end):
I=numpy.argmax(k[y,pos_start,0])
else:
else:
I=numpy.argmax(k[y,pos_start:pos_end+1,0])
pos_max = pos_start + I
Scr = k[y,pos_max,0]*Wr
Vt[y,pos_max] = Vt[y,pos_max] + Scr
Wr = 0
Wr = 0
# Vertical direction
bla = k[:,:,1] > 0
for x in range(0,img_w):
for y in range(0,img_h):
for x in range(0,img_w):
for y in range(0,img_h):
if (bla[y,x]):
Wr = Wr + 1
if ( Wr > 0 and (y == (img_h-1) or not bla[y,x]) ):
......@@ -124,20 +126,20 @@ class MaximumCurvature (Extractor):
# Reached edge of image
pos_end = y
else:
pos_end = y - 1
pos_end = y - 1
pos_start = pos_end - Wr + 1 # Start pos of concave
if (pos_start == pos_end):
I=numpy.argmax(k[pos_start,x,1])
else:
I=numpy.argmax(k[pos_start:pos_end+1,x,1])
pos_max = pos_start + I
pos_max = pos_start + I
Scr = k[pos_max,x,1]*Wr
Vt[pos_max,x] = Vt[pos_max,x] + Scr
Wr = 0
# Direction: \ #
bla = k[:,:,2] > 0
for start in range(0,img_w+img_h-1):
......@@ -149,11 +151,11 @@ class MaximumCurvature (Extractor):
x = 0
y = start - img_w + 1
done = False
while (not done):
if(bla[y,x]):
Wr = Wr + 1
if ( Wr > 0 and (y == img_h-1 or x == img_w-1 or not bla[y,x]) ):
if (y == img_h-1 or x == img_w-1):
# Reached edge of image
......@@ -162,10 +164,10 @@ class MaximumCurvature (Extractor):
else:
pos_x_end = x - 1
pos_y_end = y - 1
pos_x_start = pos_x_end - Wr + 1
pos_y_start = pos_y_end - Wr + 1
if (pos_y_start == pos_y_end and pos_x_start == pos_x_end):
d = k[pos_y_start, pos_x_start, 2]
elif (pos_y_start == pos_y_end):
......@@ -174,23 +176,23 @@ class MaximumCurvature (Extractor):
d = numpy.diag(k[pos_y_start:pos_y_end+1, pos_x_start, 2])
else:
d = numpy.diag(k[pos_y_start:pos_y_end+1, pos_x_start:pos_x_end+1, 2])
I = numpy.argmax(d)
pos_x_max = pos_x_start + I
pos_y_max = pos_y_start + I
I = numpy.argmax(d)
pos_x_max = pos_x_start + I
pos_y_max = pos_y_start + I
Scr = k[pos_y_max,pos_x_max,2]*Wr
Vt[pos_y_max,pos_x_max] = Vt[pos_y_max,pos_x_max] + Scr
Wr = 0
if((x == img_w-1) or (y == img_h-1)):
done = True
else:
x = x + 1
y = y + 1
# Direction: /
bla = k[:,:,3] > 0
for start in range(0,img_w+img_h-1):
......@@ -202,7 +204,7 @@ class MaximumCurvature (Extractor):
x = 0
y = img_w+img_h-start-1
done = False
while (not done):
if(bla[y,x]):
Wr = Wr + 1
......@@ -214,10 +216,10 @@ class MaximumCurvature (Extractor):
else:
pos_x_end = x - 1
pos_y_end = y + 1
pos_x_start = pos_x_end - Wr + 1
pos_y_start = pos_y_end + Wr - 1
if (pos_y_start == pos_y_end and pos_x_start == pos_x_end):
d = k[pos_y_end, pos_x_start, 3]
elif (pos_y_start == pos_y_end):
......@@ -226,19 +228,19 @@ class MaximumCurvature (Extractor):
d = numpy.diag(numpy.flipud(k[pos_y_end:pos_y_start+1, pos_x_start, 3]))
else:
d = numpy.diag(numpy.flipud(k[pos_y_end:pos_y_start+1, pos_x_start:pos_x_end+1, 3]))
I = numpy.argmax(d)
pos_x_max = pos_x_start + I
pos_y_max = pos_y_start - I
I = numpy.argmax(d)
pos_x_max = pos_x_start + I
pos_y_max = pos_y_start - I
Scr = k[pos_y_max,pos_x_max,3]*Wr
Vt[pos_y_max,pos_x_max] = Vt[pos_y_max,pos_x_max] + Scr
Wr = 0
if((x == img_w-1) or (y == 0)):
done = True
else:
x = x + 1
y = y - 1
y = y - 1
## Connection of vein centres
Cd = numpy.zeros((img_h, img_w, 4))
......@@ -248,34 +250,31 @@ class MaximumCurvature (Extractor):
Cd[y,x,1] = min(numpy.amax(Vt[y+1:y+3,x]), numpy.amax(Vt[y-2:y,x])) # Vert #
Cd[y,x,2] = min(numpy.amax(Vt[y-2:y,x-2:x]), numpy.amax(Vt[y+1:y+3,x+1:x+3])) # \ #
Cd[y,x,3] = min(numpy.amax(Vt[y+1:y+3,x-2:x]), numpy.amax(Vt[y-2:y,x+1:x+3])) # / #
#Veins
img_veins = numpy.amax(Cd,axis=2)
# Binarise the vein image
md = numpy.median(img_veins[img_veins>0])
img_veins_bin = img_veins > md
return img_veins_bin.astype(numpy.float64)
def __call__(self, image):
def __call__(self, image):
"""Reads the input image, extract the features based on Maximum Curvature of the fingervein image, and writes the resulting template"""
finger_image = image[0] #Normalized image with or without histogram equalization
finger_mask = image[1]
return self.maximum_curvature(finger_image, finger_mask)
finger_mask = image[1]
return self.maximum_curvature(finger_image, finger_mask)
def save_feature(self, feature, feature_file):
f = bob.io.base.HDF5File(feature_file, 'w')
f.set('feature', feature)
def read_feature(self, feature_file):
f = bob.io.base.HDF5File(feature_file, 'r')
image = f.read('feature')
return (image)
\ No newline at end of file
return image
......@@ -2,48 +2,44 @@
# vim: set fileencoding=utf-8 :
# Pedro Tome <Pedro.Tome@idiap.ch>
import bob.core
import numpy
import bob.io.base
import numpy
from facereclib.features.Extractor import Extractor
from bob.bio.base.features.Extractor import Extractor
class NormalisedCrossCorrelation (Extractor):
"""Normalised Cross-Correlation feature extractor based on
M. Kono, H. Ueki, and S.Umemura. Near-infrared finger vein patterns for personal
identification. Appl. Opt. 41(35):7429-7436, 2002
"""Normalised Cross-Correlation feature extractor
Based on M. Kono, H. Ueki, and S.Umemura. Near-infrared finger vein patterns
for personal identification. Appl. Opt. 41(35):7429-7436, 2002
"""
def __init__(
self,
):
# call base class constructor
Extractor.__init__(
self,
)
# block parameters
def __call__(self, image, mask):
"""Reads the input image, extract the features based on Normalised Cross-Correlation of the fingervein image, and writes the resulting template"""
def __init__(self):
Extractor.__init__(self)
def __call__(self, image, mask):
"""Reads the input image, extract the features based on Normalised
Cross-Correlation of the fingervein image, and writes the resulting
template"""
finger_image = image #Normalized image with histogram equalization
finger_mask = mask
image_vein = finger_image*finger_mask
#TODO
return image_vein.astype(numpy.float64)
finger_mask = mask
image_vein = finger_image*finger_mask
#TODO
return image_vein.astype(numpy.float64)
def save_feature(self, feature, feature_file):
f = bob.io.base.HDF5File(feature_file, 'w')
f.set('feature', feature)
def read_feature(self, feature_file):
f = bob.io.base.HDF5File(feature_file, 'r')
image = f.read('feature')
......
......@@ -4,48 +4,46 @@
import bob.io.base
import numpy
import math
#from math import pi
#from mumpy import sqrt
import scipy.signal
from facereclib.features.Extractor import Extractor
from .. import utils
from bob.bio.base.features.Extractor import Extractor
class MaximumCurvature (Extractor):
"""MiuraMax feature extractor based on
J.H. Choi, W. Song, T. Kim, S.R. Lee and H.C. Kim, Finger vein extraction using gradient normalization and principal curvature.
Proceedings on Image Processing: Machine Vision Applications II, SPIE 7251, (2009)
"""MiuraMax feature extractor
Based on J.H. Choi, W. Song, T. Kim, S.R. Lee and H.C. Kim, Finger vein
extraction using gradient normalization and principal curvature. Proceedings
on Image Processing: Machine Vision Applications II, SPIE 7251, (2009)
"""
def __init__(
self,
sigma = 2, # Gaussian standard deviation applied
threshold = 1.3, # Percentage of maximum used for hard thresholding
gpu = False
):
threshold = 1.3, # Percentage of maximum used for hard thresholding
gpu = False,
):
# call base class constructor
Extractor.__init__(
self,
sigma = sigma,
threshold = threshold,
gpu = gpu
)
gpu = gpu,
)
# block parameters
self.sigma = sigma
self.threshold = threshold
self.gpu = gpu
def principal_curvature(self, image, mask):
"""Computes and returns the Maximum Curvature features for the given input fingervein image"""
def principal_curvature(self, image, mask):
"""Computes and returns the Maximum Curvature features for the given input
fingervein image"""
finger_mask = numpy.zeros(mask.shape)
finger_mask[mask == True] = 1
finger_mask[mask == True] = 1
sigma = numpy.sqrt(self.sigma**2/2)
gx = ut_gauss(img,sigma,1,0)
......@@ -55,9 +53,9 @@ class MaximumCurvature (Extractor):
# Apply threshold
gamma = (self.threshold/100)*max(max(Gmag))
indices = find(Gmag < gamma)
gx[indices] = 0
gy[indices] = 0
......@@ -65,7 +63,7 @@ class MaximumCurvature (Extractor):
Gmag( find(Gmag == 0) ) = 1 # Avoid dividing by zero