LocalBinaryPatterns.py 4.4 KB
Newer Older
Pedro TOME's avatar
Pedro TOME committed
1 2
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
3 4

import numpy
Pedro TOME's avatar
Pedro TOME committed
5 6 7

import bob.ip.base
import bob.io.base
8

9
from bob.bio.base.extractor import Extractor
10

Pedro TOME's avatar
Pedro TOME committed
11 12

class LocalBinaryPatterns (Extractor):
13 14 15 16
  """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.
Pedro TOME's avatar
Pedro TOME committed
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
  """

  def __init__(
      self,
      # Block setup
      block_size = 59,    # one or two parameters for block size
      block_overlap = 15, # one or two parameters for block overlap
      # LBP parameters
      lbp_radius = 7,
      lbp_neighbor_count = 16,
      lbp_uniform = True,
      lbp_circular = True,
      lbp_rotation_invariant = False,
      lbp_compare_to_average = False,
      lbp_add_average = False,
      # histogram options
      sparse_histogram = False,
34 35
      split_histogram = None,
      ):
Pedro TOME's avatar
Pedro TOME committed
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

    # call base class constructor
    Extractor.__init__(
        self,
        # Block setup
        block_size = block_size,
        block_overlap = block_overlap,
        #LBP parameters
        lbp_radius = lbp_radius,
        lbp_neighbor_count = lbp_neighbor_count,
        lbp_uniform = lbp_uniform,
        lbp_circular = lbp_circular,
        lbp_rotation_invariant = lbp_rotation_invariant,
        lbp_compare_to_average = lbp_compare_to_average,
        lbp_add_average = lbp_add_average,
        sparse_histogram = sparse_histogram,
52 53 54
        split_histogram = split_histogram,
        )

Pedro TOME's avatar
Pedro TOME committed
55 56 57 58 59
    # 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!")
60

Pedro TOME's avatar
Pedro TOME committed
61 62 63 64 65 66 67 68
    self.m_lbp = bob.ip.base.LBP(
        neighbors = lbp_neighbor_count,
        radius = float(lbp_radius),
        circular = lbp_circular,
        to_average = lbp_compare_to_average,
        add_average_bit = lbp_add_average,
        uniform = lbp_uniform,
        rotation_invariant = lbp_rotation_invariant,
69 70
        border_handling = 'wrap',
        )
Pedro TOME's avatar
Pedro TOME committed
71 72 73 74 75


    self.m_split = split_histogram
    self.m_sparse = sparse_histogram
    if self.m_sparse and self.m_split:
76
      raise ValueError("Sparse histograms cannot be split! Check your setup.")
Pedro TOME's avatar
Pedro TOME committed
77 78 79 80


  def __fill__(self, lbphs_array, lbphs_blocks, j):
    """Copies the given array into the given blocks"""
81

Pedro TOME's avatar
Pedro TOME committed
82
    # fill array in the desired shape
83 84
    #For debugging
    #import ipdb; ipdb.set_trace()
Pedro TOME's avatar
Pedro TOME committed
85 86
    for b in range(self.m_n_blocks):
      lbphs_array[b * self.m_n_bins : (b+1) * self.m_n_bins] = lbphs_blocks[b][:]
87

Pedro TOME's avatar
Pedro TOME committed
88 89

  def lbp_features(self, finger_image, mask):
90 91 92 93 94 95
    """Computes and returns the LBP features for the given input fingervein
    image"""

    # For debugging
    #import ipdb; ipdb.set_trace()

Pedro TOME's avatar
Pedro TOME committed
96 97 98
    finger_image = finger_image.astype(numpy.float64)

    finger_mask = numpy.zeros(mask.shape)
99 100
    finger_mask[mask == True] = 1

Pedro TOME's avatar
Pedro TOME committed
101
    # Mask the vein image with the finger region
102 103
    finger_image = finger_image*finger_mask

Pedro TOME's avatar
Pedro TOME committed
104 105 106 107 108 109
    # 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]
110

Pedro TOME's avatar
Pedro TOME committed
111
    shape = self.m_n_bins * self.m_n_blocks
112 113

    # create new array
Pedro TOME's avatar
Pedro TOME committed
114
    lbphs_array = numpy.zeros(shape, 'float64')
115 116 117 118

    #For debugging
    #import ipdb; ipdb.set_trace()

Pedro TOME's avatar
Pedro TOME committed
119 120
    # fill the array with the absolute values of the Gabor wavelet transform
    self.__fill__(lbphs_array, abs_blocks, 0)
121

Pedro TOME's avatar
Pedro TOME committed
122 123
    # return the concatenated list of all histograms
    return lbphs_array
124 125 126


  def __call__(self, image):
Pedro TOME's avatar
Pedro TOME committed
127
    """Reads the input image, extract the features based on LBP of the fingervein image, and writes the resulting template"""
128 129
    #For debugging

Pedro TOME's avatar
Pedro TOME committed
130
    finger_image = image[0]    #Normalized image with histogram equalization
131 132 133 134 135
    finger_mask = image[1]

    return self.lbp_features(finger_image, finger_mask)


Pedro TOME's avatar
Pedro TOME committed
136 137 138
  def save_feature(self, feature, feature_file):
    f = bob.io.base.HDF5File(feature_file, 'w')
    f.set('feature', feature)
139

Pedro TOME's avatar
Pedro TOME committed
140 141 142
  def read_feature(self, feature_file):
    f = bob.io.base.HDF5File(feature_file, 'r')
    image = f.read('feature')
143
    return image