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


class LBPHistogram(Extractor):
    """Calculates a normalized LBP histogram over an image.
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
10
    These features are implemented based on [ChingovskaEffectivnes12]_.
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

    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

    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,
                 dtype=None):

        super(LBPHistogram, self).__init__(
            lbptype=lbptype,
            elbptype=elbptype,
            rad=rad,
            neighbors=neighbors,
            circ=circ,
            dtype=dtype,)

        elbps = {'regular': 'regular',
                 'transitional': 'trainsitional',
                 'direction_coded': 'direction-coded',
                 'modified': 'regular'}

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

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

        self.dtype = dtype
        self.lbp = lbp

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

        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)

        """
        assert isinstance(data, numpy.ndarray)

        # allocating the image with lbp codes
        lbpimage = numpy.ndarray(self.lbp.lbp_shape(data), 'uint16')
        self.lbp(data, lbpimage)  # calculating the lbp image
        hist = bob.ip.base.histogram(
            lbpimage, (0, self.lbp.max_label - 1), self.lbp.max_label)
        hist = hist / sum(hist)  # histogram normalization
        if self.dtype is not None:
            hist = hist.astype(self.dtype)
        return hist