LBPHistogram.py 6.1 KB
Newer Older
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
1 2 3 4
from __future__ import division
from bob.bio.base.extractor import Extractor
import bob.bio.video
import bob.ip.base
5
import numpy as np
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
6 7 8 9


class LBPHistogram(Extractor):
    """Calculates a normalized LBP histogram over an image.
10
    These features are implemented based on [CAM12]_.
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

    Parameters
    ----------
    lbptype : str
        The type of the LBP operator (regular, uniform or riu2)
    elbptype : str
        The type of extended version of LBP (regular if not extended version
        is used, otherwise transitional, direction_coded or modified)
    rad : float
        The radius of the circle on which the points are taken (for circular
        LBP)
    neighbors : int
        The number of points around the central point on which LBP is
        computed (4, 8, 16)
    circ : bool
        True if circular LBP is needed, False otherwise
27 28 29 30 31 32
    n_hor : int
        Number of blocks horizontally for spatially-enhanced LBP/MCT
        histograms. Default: 1
    n_vert
        Number of blocks vertically for spatially-enhanced LBP/MCT
        histograms. Default: 1
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

    Attributes
    ----------
    dtype : numpy.dtype
        If a ``dtype`` is specified in the contructor, it is assured that the
        resulting features have that dtype.
    lbp : bob.ip.base.LBP
        The LPB extractor object.
    """

    def __init__(self,
                 lbptype='uniform',
                 elbptype='regular',
                 rad=1,
                 neighbors=8,
                 circ=False,
49 50 51
                 dtype=None,
                 n_hor=1,
                 n_vert=1):
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
52 53 54 55 56 57 58

        super(LBPHistogram, self).__init__(
            lbptype=lbptype,
            elbptype=elbptype,
            rad=rad,
            neighbors=neighbors,
            circ=circ,
59
            dtype=dtype,
60 61
            n_hor=n_hor,
            n_vert=n_vert)
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
62

63 64 65 66 67 68
        elbps = {
            'regular': 'regular',
            'transitional': 'trainsitional',
            'direction_coded': 'direction-coded',
            'modified': 'regular'
        }
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
69 70 71 72 73 74 75 76 77

        if elbptype == 'modified':
            mct = True
        else:
            mct = False

        if lbptype == 'uniform':
            if neighbors == 16:
                lbp = bob.ip.base.LBP(
78 79 80 81 82 83
                    neighbors=16,
                    uniform=True,
                    circular=circ,
                    radius=rad,
                    to_average=mct,
                    elbp_type=elbps[elbptype])
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
84 85
            else:  # we assume neighbors==8 in this case
                lbp = bob.ip.base.LBP(
86 87 88 89 90 91
                    neighbors=8,
                    uniform=True,
                    circular=circ,
                    radius=rad,
                    to_average=mct,
                    elbp_type=elbps[elbptype])
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
92 93 94
        elif lbptype == 'riu2':
            if neighbors == 16:
                lbp = bob.ip.base.LBP(
95 96 97 98 99 100
                    neighbors=16,
                    uniform=True,
                    rotation_invariant=True,
                    radius=rad,
                    circular=circ,
                    to_average=mct,
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
101 102 103
                    elbp_type=elbps[elbptype])
            else:  # we assume neighbors==8 in this case
                lbp = bob.ip.base.LBP(
104 105 106 107 108 109
                    neighbors=8,
                    uniform=True,
                    rotation_invariant=True,
                    radius=rad,
                    circular=circ,
                    to_average=mct,
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
110 111 112 113
                    elbp_type=elbps[elbptype])
        else:  # regular LBP
            if neighbors == 16:
                lbp = bob.ip.base.LBP(
114 115 116 117
                    neighbors=16,
                    circular=circ,
                    radius=rad,
                    to_average=mct,
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
118 119 120
                    elbp_type=elbps[elbptype])
            else:  # we assume neighbors==8 in this case
                lbp = bob.ip.base.LBP(
121 122 123 124
                    neighbors=8,
                    circular=circ,
                    radius=rad,
                    to_average=mct,
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
125 126 127 128
                    elbp_type=elbps[elbptype])

        self.dtype = dtype
        self.lbp = lbp
129 130
        self.n_hor = n_hor
        self.n_vert = n_vert
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
131

132 133 134
    def comp_block_histogram(self, data):
        """
        Extracts LBP/MCT histograms from a gray-scale image/block.
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150

        Takes data of arbitrary dimensions and linearizes it into a 1D vector;
        Then, calculates the histogram.
        enforcing the data type, if desired.

        Parameters
        ----------
        data : numpy.ndarray
            The preprocessed data to be transformed into one vector.

        Returns
        -------
        1D :py:class:`numpy.ndarray`
            The extracted feature vector, of the desired ``dtype`` (if
            specified)
        """
151
        assert isinstance(data, np.ndarray)
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
152 153

        # allocating the image with lbp codes
154
        lbpimage = np.ndarray(self.lbp.lbp_shape(data), 'uint16')
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
155
        self.lbp(data, lbpimage)  # calculating the lbp image
156 157
        hist = bob.ip.base.histogram(lbpimage, (0, self.lbp.max_label - 1),
                                     self.lbp.max_label)
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
158 159 160 161
        hist = hist / sum(hist)  # histogram normalization
        if self.dtype is not None:
            hist = hist.astype(self.dtype)
        return hist
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193

    def __call__(self, data):
        """
        Extracts spatially-enhanced LBP/MCT histograms from a gray-scale image.

        Parameters
        ----------
        data : numpy.ndarray
            The preprocessed data to be transformed into one vector.

        Returns
        -------
        1D :py:class:`numpy.ndarray`
            The extracted feature vector, of the desired ``dtype`` (if
            specified)

        """

        # Make sure the data can be split into equal blocks:
        row_max = int(data.shape[0] / self.n_vert) * self.n_vert
        col_max = int(data.shape[1] / self.n_hor) * self.n_hor
        data = data[:row_max, :col_max]

        blocks = [sub_block for block in np.hsplit(data, self.n_hor) for sub_block in np.vsplit(block, self.n_vert)]

        hists = [self.comp_block_histogram(block) for block in blocks]

        hist = np.hstack(hists)

        hist = hist / len(blocks)  # histogram normalization

        return hist