From 47c73ab74471418f42562edcbbd9060aad3e2ec1 Mon Sep 17 00:00:00 2001
From: Andre Anjos <andre.anjos@idiap.ch>
Date: Fri, 21 Sep 2012 10:40:00 +0200
Subject: [PATCH] Better package standardization

---
 MANIFEST.in           |  2 +
 README.rst            | 70 +++++++++++++++++++++++++++++++++
 flandmark/__init__.py | 91 ++++++++++++++++++++++++++++++++++++++++++-
 flandmark/ext/ext.cpp |  2 +-
 flandmark/test.py     |  5 +--
 setup.py              | 37 +++++++++++++++++-
 6 files changed, 200 insertions(+), 7 deletions(-)
 create mode 100644 MANIFEST.in
 create mode 100644 README.rst

diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..d361b96
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,2 @@
+include README.rst *.cfg bootstrap.py
+recursive-include flandmark *.sql3 *.cpp *.h *.xml *.dat
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..37720e0
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,70 @@
+==============================
+ Python Bindings to flandmark
+==============================
+
+This package is a simple Boost.Python wrapper to the (rather quick) open-source
+facial landmark detector `flandmark
+<http://cmp.felk.cvut.cz/~uricamic/flandmark/index.php>`_. If you use this
+package, the author asks you to cite the following paper::
+
+  @InProceedings{Uricar-Franc-Hlavac-VISAPP-2012,
+    author =      {U{\\v{r}}i{\\v{c}}{\\'{a}}{\\v{r}}, Michal and Franc, Vojt{\\v{e}}ch and Hlav{\\'{a}}{\\v{c}}, V{\\'{a}}clav},
+    title =       {Detector of Facial Landmarks Learned by the Structured Output {SVM}},
+    year =        {2012},
+    pages =       {547-556},
+    booktitle =   {VISAPP '12: Proceedings of the 7th International Conference on Computer Vision Theory and Applications},
+    editor =      {Csurka, Gabriela and Braz, Jos{\'{e}}},
+    publisher =   {SciTePress --- Science and Technology Publications},
+    address =     {Portugal},
+    volume =      {1},
+    isbn =        {978-989-8565-03-7},
+    book_pages =  {747},
+    month =       {February},
+    day =         {24-26},
+    venue =       {Rome, Italy},
+    keywords =    {Facial Landmark Detection, Structured Output Classification, Support Vector Machines, Deformable Part Models},
+    prestige =    {important},
+    authorship =  {50-40-10},
+    status =      {published},
+    project =     {FP7-ICT-247525 HUMAVIPS, PERG04-GA-2008-239455 SEMISOL, 
+      Czech Ministry of Education project 1M0567},
+    www = {http://www.visapp.visigrapp.org},
+  }
+
+Installation
+------------
+
+To install these bindings, you will need the open-source library `Bob
+<http://www.idiap.ch/software/bob/>`_ installed somewhere. At least version 1.1
+of Bob is required. If you have compiled Bob yourself and installed it on a
+non-standard location, you will need to note down the path leading to the root
+of that installation.
+
+Just type::
+
+  $ python bootstrap.py
+  $ ./bin/buildout
+
+If Bob is installed in a non-standard location, remember to use the **same
+python interpreter** that was used to compile Bob (replace ``<bob-root>`` with
+the root of your local installation of Bob)::
+
+  $ <bob-root>/bin/python bootstrap.py
+  $ PKG_CONFIG_PATH=<bob-root>/lib/pkgconfig ./bin/buildout
+
+The `PKG_CONFIG_PATH` variable will help ``buildout`` find the correct include
+and link paths to your non-stock Bob installation.
+
+Usage
+-----
+
+Pretty simple, just do something like::
+
+  import bob
+  import flandmark
+
+  video = bob.io.VideoReader('myvideo.avi')
+  localize = flandmark.Localizer()
+
+  for i, frame in enumerate(video):
+    print localize(frame)
diff --git a/flandmark/__init__.py b/flandmark/__init__.py
index 6766446..3ad5d7b 100644
--- a/flandmark/__init__.py
+++ b/flandmark/__init__.py
@@ -1 +1,90 @@
-from ._flandmark import *
+from . import _flandmark
+
+from pkg_resources import resource_filename
+
+def __filename__(f):
+  """Returns the test file on the "data" subdirectory"""
+  return resource_filename(__name__, f)
+
+class Localizer(_flandmark.Localizer):
+  """A fast and effective facial landmark localization framework based on
+  flandmark
+  
+  Consult http://cmp.felk.cvut.cz/~uricamic/flandmark/index.php for more
+  information.
+  """
+
+  def __init__(self, detection_model=resource_filename(__name__, 
+    'haarcascade_frontalface_alt.xml'), 
+    localization_model=resource_filename(__name__,
+      'flandmark_model.dat')):
+    """Builds a new facial localization model.
+
+    Raises RuntimeError's if the models either don't exist or can't be loaded.
+
+    Keyword parameters:
+
+    detection_model
+      An OpenCV (xml) detection model file for a CvHaarClassifierCascade. If not
+      specified, use a default installed with the package.
+
+    localization_model
+      A flandmark localization model file. If not specified, use a default
+      installed with the package. The default model provides the following
+      keypoints, in this order:
+
+      [0]
+        Face center
+
+      [1]
+        Canthus-rl (inner corner of the right eye). Note: The "right eye" means
+        the right eye at face w.r.t. itself - that is the left eye in the image.
+
+      [2]
+        Canthus-lr (inner corder of the left eye)
+
+      [3]
+        Mouth-corner-r (right corner of the mouth)
+
+      [4]
+        Mouth-corner-l (left corner of the mouth)
+
+      [5]
+        Canthus-rr (outer corner of the right eye)
+
+      [6]
+        Canthus-ll (outer corner of the left eye)
+
+      [7]
+        Nose
+    """
+    super(Localizer, self).__init__(detection_model, localization_model)
+
+  def __call__(self, image):
+    """Localizes facial keypoints on all faces detected at the input image.
+
+    Keyword parameters:
+
+    image
+      Either a gray-scale or colored image where to run the detection and
+      localization.
+
+    Returns a tuple composed of dictionaries. Each dictionary in the list has
+    two entries: ``bbox`` and ``landmark``. The ``bbox`` entry corresponds to
+    the OpenCV cascade face detected, whereas the ``landmark`` contains a list
+    of tuples (representing x,y coordinates) with the landmarks.
+
+    If no faces are detected on the input image, than the returned tuple is
+    empty.
+    """
+
+    if image.ndim == 3:
+      from bob.ip import rgb_to_gray
+      gray = rgb_to_gray(image)
+      return super(Localizer, self).__call__(gray)
+
+    elif image.ndim == 2:
+      return super(Localizer, self).__call__(gray)
+
+    else:
+      raise TypeError, "Localizer accepts images as numpy.ndarray objects with either 2 or 3 dimensions"
diff --git a/flandmark/ext/ext.cpp b/flandmark/ext/ext.cpp
index 2c14351..a768e26 100644
--- a/flandmark/ext/ext.cpp
+++ b/flandmark/ext/ext.cpp
@@ -106,7 +106,7 @@ class Localizer {
 
         // The first point represents the center of the bounding box used by
         // the flandmark library.
-        for (int i = 2; i < (2*m_flandmark->data.options.M); i += 2) {
+        for (int i = 0; i < (2*m_flandmark->data.options.M); i += 2) {
           lmlist.append(make_tuple(m_landmarks[i], m_landmarks[i+1]));
         }
         det["landmark"] = lmlist;
diff --git a/flandmark/test.py b/flandmark/test.py
index 501958d..81f7840 100644
--- a/flandmark/test.py
+++ b/flandmark/test.py
@@ -30,8 +30,8 @@ class FlandmarkTest(unittest.TestCase):
 
     v = bob.io.VideoReader(INPUT_VIDEO)
 
-    for i, f in enumerate(v):
-      self.assertTrue(op(bob.ip.rgb_to_gray(f)))
+    for f in v:
+      self.assertTrue(op(f))
 
   def xtest02_broken(self):
 
@@ -39,6 +39,5 @@ class FlandmarkTest(unittest.TestCase):
         "flandmark/flandmark_model.dat")
 
     for i, f in enumerate(bob.io.VideoReader(INPUT_VIDEO)):
-      v = bob.ip.rgb_to_gray(f)
       print v
       self.assertTrue(op(v))
diff --git a/setup.py b/setup.py
index 55da9ad..c7f9cb9 100644
--- a/setup.py
+++ b/setup.py
@@ -8,7 +8,7 @@
 
 import sys
 import subprocess
-from distutils.core import setup
+from setuptools import setup, find_packages
 from distutils.extension import Extension
 
 def pkgconfig(package):
@@ -82,8 +82,30 @@ def setup_bob_extension(ext_name, sources):
       )
 
 setup(
+
     name="flandmark",
     version="1.0.6",
+    description="",
+    license="GPLv3",
+    author='Andre Anjos',
+    author_email='andre.anjos@idiap.ch',
+    long_description=open('README.rst').read(),
+
+    packages=find_packages(),
+    include_package_data=True,
+    zip_safe=False,
+
+    install_requires=[
+      'setuptools',
+      'bob',
+      ],
+
+    entry_points = {
+      'console_scripts': [
+        'annotate.py = flandmark.script.annotate:main',
+        ],
+      },
+
     ext_modules=[
       setup_bob_extension("flandmark._flandmark",
         [
@@ -91,4 +113,15 @@ setup(
           "flandmark/ext/liblbp.cpp",
           "flandmark/ext/ext.cpp",
         ])
-      ])
+      ],
+
+    classifiers = [
+      'Development Status :: 4 - Beta',
+      'Intended Audience :: Developers',
+      'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
+      'Natural Language :: English',
+      'Programming Language :: Python',
+      'Topic :: Scientific/Engineering :: Artificial Intelligence',
+      ],
+    
+    )
-- 
GitLab