LBPHistogram.py 4.76 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.
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

    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,
51 52
            dtype=dtype,
        )
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
53

54 55 56 57 58 59
        elbps = {
            'regular': 'regular',
            'transitional': 'trainsitional',
            'direction_coded': 'direction-coded',
            'modified': 'regular'
        }
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
60 61 62 63 64 65 66 67 68

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

        if lbptype == 'uniform':
            if neighbors == 16:
                lbp = bob.ip.base.LBP(
69 70 71 72 73 74
                    neighbors=16,
                    uniform=True,
                    circular=circ,
                    radius=rad,
                    to_average=mct,
                    elbp_type=elbps[elbptype])
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
75 76
            else:  # we assume neighbors==8 in this case
                lbp = bob.ip.base.LBP(
77 78 79 80 81 82
                    neighbors=8,
                    uniform=True,
                    circular=circ,
                    radius=rad,
                    to_average=mct,
                    elbp_type=elbps[elbptype])
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
83 84 85
        elif lbptype == 'riu2':
            if neighbors == 16:
                lbp = bob.ip.base.LBP(
86 87 88 89 90 91
                    neighbors=16,
                    uniform=True,
                    rotation_invariant=True,
                    radius=rad,
                    circular=circ,
                    to_average=mct,
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
92 93 94
                    elbp_type=elbps[elbptype])
            else:  # we assume neighbors==8 in this case
                lbp = bob.ip.base.LBP(
95 96 97 98 99 100
                    neighbors=8,
                    uniform=True,
                    rotation_invariant=True,
                    radius=rad,
                    circular=circ,
                    to_average=mct,
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
101 102 103 104
                    elbp_type=elbps[elbptype])
        else:  # regular LBP
            if neighbors == 16:
                lbp = bob.ip.base.LBP(
105 106 107 108
                    neighbors=16,
                    circular=circ,
                    radius=rad,
                    to_average=mct,
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
109 110 111
                    elbp_type=elbps[elbptype])
            else:  # we assume neighbors==8 in this case
                lbp = bob.ip.base.LBP(
112 113 114 115
                    neighbors=8,
                    circular=circ,
                    radius=rad,
                    to_average=mct,
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
                    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
145 146
        hist = bob.ip.base.histogram(lbpimage, (0, self.lbp.max_label - 1),
                                     self.lbp.max_label)
Amir MOHAMMADI's avatar
Amir MOHAMMADI committed
147 148 149 150
        hist = hist / sum(hist)  # histogram normalization
        if self.dtype is not None:
            hist = hist.astype(self.dtype)
        return hist