diff --git a/bob/pad/face/__init__.py b/bob/pad/face/__init__.py
index b6752da37f696e801b2ca764c26cd66fbbd34b91..1d16bcbc879c7c6054b3c555e01c7e710eae801e 100644
--- a/bob/pad/face/__init__.py
+++ b/bob/pad/face/__init__.py
@@ -1,11 +1,12 @@
-from . import script
+from . import algorithm, extractor, preprocessor
+
 
 def get_config():
-  """Returns a string containing the configuration information.
-  """
+    """Returns a string containing the configuration information.
+    """
 
-  import bob.extension
-  return bob.extension.get_config(__name__)
+    import bob.extension
+    return bob.extension.get_config(__name__)
 
 
 # gets sphinx autodoc done right - don't remove it
diff --git a/bob/pad/face/script/__init__.py b/bob/pad/face/algorithm/__init__.py
similarity index 100%
rename from bob/pad/face/script/__init__.py
rename to bob/pad/face/algorithm/__init__.py
diff --git a/bob/pad/face/extractor/LBPHistogram.py b/bob/pad/face/extractor/LBPHistogram.py
new file mode 100644
index 0000000000000000000000000000000000000000..2c8762f2f96df23ab36536c60f0b532177f4456a
--- /dev/null
+++ b/bob/pad/face/extractor/LBPHistogram.py
@@ -0,0 +1,139 @@
+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.
+    These features are implemented based on the chingovska_effectiveness_2012_.
+
+    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.
+
+
+    .. _chingovska_effectiveness_2012:
+        I. Chingovska, A. Anjos, and S. Marcel, ``On the effectiveness of
+        local binary patterns in face anti-spoofing,'' in Biometrics Special
+        Interest Group (BIOSIG), 2012 BIOSIG-Proceedings of the International
+        Conference of the, 2012, pp. 1-7.
+    """
+
+    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(
+                    neighbors=16, circular=circ, radius=rad, to_average=mct,
+                    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
+
+    # re-define unused functions, just so that they do not get documented
+    def train(*args, **kwargs):
+        raise NotImplementedError()
+
+    def load(*args, **kwargs):
+        pass
diff --git a/bob/pad/face/extractor/__init__.py b/bob/pad/face/extractor/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..4a9104dbdf19213a0c6f9395faa7cd7708647024
--- /dev/null
+++ b/bob/pad/face/extractor/__init__.py
@@ -0,0 +1,25 @@
+from .LBPHistogram import LBPHistogram
+
+
+def __appropriate__(*args):
+    """Says object was actually declared here, and not in the import module.
+    Fixing sphinx warnings of not being able to find classes, when path is
+    shortened.
+
+    Parameters
+    ----------
+    *args
+        The objects that you want sphinx to beleive that are defined here.
+
+    Resolves `Sphinx referencing issues <https//github.com/sphinx-
+    doc/sphinx/issues/3048>`
+    """
+
+    for obj in args:
+        obj.__module__ = __name__
+
+
+__appropriate__(
+    LBPHistogram,
+)
+__all__ = [_ for _ in dir() if not _.startswith('_')]
diff --git a/bob/pad/face/preprocessor/__init__.py b/bob/pad/face/preprocessor/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/bob/pad/face/script/version.py b/bob/pad/face/script/version.py
deleted file mode 100644
index 63c9f37e5a4bb75eed114bbd3bdea8a966b0830f..0000000000000000000000000000000000000000
--- a/bob/pad/face/script/version.py
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/env python
-# vim: set fileencoding=utf-8 :
-
-"""Prints the version of bob and exits
-"""
-
-def main():
-  """Main routine, called by the script that gets the configuration of bob.blitz"""
-
-  import bob.blitz
-  print (bob.blitz.get_config())
-  return 0
-
diff --git a/bob/pad/face/test.py b/bob/pad/face/test.py
deleted file mode 100644
index ecba98835a9d37087d0cc27b0f5e4a275f698f14..0000000000000000000000000000000000000000
--- a/bob/pad/face/test.py
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env python
-# vim: set fileencoding=utf-8 :
-
-"""Test Units
-"""
-
-def test_version():
-  from .script import version
-  assert version.main() == 0
diff --git a/bob/pad/face/test/__init__.py b/bob/pad/face/test/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/bob/pad/face/test/data/lbp.hdf5 b/bob/pad/face/test/data/lbp.hdf5
new file mode 100644
index 0000000000000000000000000000000000000000..1de8c04a36164a5722b90f39c6d35c22b0d8d661
Binary files /dev/null and b/bob/pad/face/test/data/lbp.hdf5 differ
diff --git a/bob/pad/face/test/test.py b/bob/pad/face/test/test.py
new file mode 100644
index 0000000000000000000000000000000000000000..153e404b6ca1ec529f431c45a050d48ce50fdf21
--- /dev/null
+++ b/bob/pad/face/test/test.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+# vim: set fileencoding=utf-8 :
+
+"""Test Units
+"""
+import numpy as np
+from bob.io.base.test_utils import datafile
+from bob.io.base import load
+import bob.io.image  # for image loading functionality
+from bob.ip.color import rgb_to_gray
+from ..extractor import LBPHistogram
+
+
+def test_lbp_histogram():
+    lbp = LBPHistogram()
+    img = load(datafile('testimage.jpg', 'bob.bio.face.test'))
+    img = rgb_to_gray(img)
+    features = lbp(img)
+    reference = load(datafile('lbp.hdf5', 'bob.pad.face.test'))
+    assert np.allclose(features, reference)
diff --git a/doc/extra-intersphinx.txt b/doc/extra-intersphinx.txt
new file mode 100644
index 0000000000000000000000000000000000000000..676c4b7fd7e64d84246b0eaeabdf3fae5a8a095f
--- /dev/null
+++ b/doc/extra-intersphinx.txt
@@ -0,0 +1 @@
+bob.bio.base
diff --git a/doc/guide.rst b/doc/guide.rst
new file mode 100644
index 0000000000000000000000000000000000000000..e115bff942d3a1d0986d247572d8d933edb4a95b
--- /dev/null
+++ b/doc/guide.rst
@@ -0,0 +1,16 @@
+.. py:currentmodule:: bob.pad.face
+
+.. testsetup:: *
+
+   from __future__ import print_function
+   import pkg_resources
+
+============================================================
+ Presentation Attack Detection in Face Biometrics in Python
+============================================================
+
+MFCC Extraction
+---------------
+
+Two funct
+
diff --git a/doc/index.rst b/doc/index.rst
index 1594aab463522836e0c3d0be7771f747111abec8..a09a2bfc71f23cccbea445209de1298c8f18912a 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -1,6 +1,4 @@
 .. vim: set fileencoding=utf-8 :
-.. Andre Anjos <andre.anjos@idiap.ch>
-.. Mon 13 Aug 2012 12:36:40 CEST
 
 .. _bob.pad.face:
 
@@ -8,10 +6,15 @@
  Presentation Attack Detection in Face Biometrics
 ==================================================
 
+.. todolist::
 
 Package Documentation
 ---------------------
 
-.. automodule:: bob.pad.face
+.. toctree::
+   :maxdepth: 2
+
+   guide
+   py_api
 
 
diff --git a/doc/py_api.rst b/doc/py_api.rst
new file mode 100644
index 0000000000000000000000000000000000000000..8f040ca2c3d24debdb31d7a249d6fa1aed3f6bab
--- /dev/null
+++ b/doc/py_api.rst
@@ -0,0 +1,40 @@
+.. vim: set fileencoding=utf-8 :
+
+===================================
+ Tools implemented in bob.pad.face
+===================================
+
+Summary
+-------
+
+Databases
+~~~~~~~~~
+
+Image Preprocessors
+~~~~~~~~~~~~~~~~~~~
+
+Video Preprocessors
+~~~~~~~~~~~~~~~~~~~
+
+Image Extractors
+~~~~~~~~~~~~~~~~
+
+Image Extractors
+~~~~~~~~~~~~~~~~
+
+.. autosummary::
+
+	bob.pad.face.extractor.LBPHistogram
+
+Video Extractors
+~~~~~~~~~~~~~~~~
+
+
+
+.. automodule:: bob.pad.face
+
+Image Extractors
+----------------
+
+.. automodule:: bob.pad.face.extractor
+
diff --git a/requirements.txt b/requirements.txt
index 3a07e533330b1efa6ead83e0789a76db08ff86c6..2daa4cd6696ddb812d78afa8888da245a3d56e06 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1 +1,5 @@
+bob.extension
+bob.io.base
+bob.bio.face
+bob.bio.video
 bob.pad.base