diff --git a/README.rst b/README.rst index 1d237a2f1dbf0fdc77e9622fa9978f131f147950..ae283f2a7ec8ea43a108a38613adfeea0f5dfd92 100644 --- a/README.rst +++ b/README.rst @@ -9,7 +9,7 @@ facial landmark detector `flandmark 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}, + 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}, @@ -49,7 +49,7 @@ Installation You can just add a dependence for ``xbob.flandmark`` on your ``setup.py`` to automatically download and have this package available at your satellite -package. This works well if Bob_ is installed centrally at your machine. +package. This works well if Bob_ is installed centrally at your machine. Otherwise, you will need to tell ``buildout`` how to build the package locally and how to find Bob_. For that, just add a custom egg recipe to your @@ -84,7 +84,7 @@ Just type:: If Bob is installed in a non-standard location, edit the file ``buildout.cfg`` to set the root to Bob's local installation path. Remember to use the **same -python interpreter** that was used to compile Bob, then execute the same steps +python interpreter** that was used to compile Bob_, then execute the same steps as above. Usage @@ -96,7 +96,18 @@ Pretty simple, just do something like:: from xbob import flandmark video = bob.io.VideoReader('myvideo.avi') - localize = flandmark.Localizer() + localizer = flandmark.Localizer() for frame in video: - print localize(frame) + print localizer(frame) + +If you already have a detected bounding box, you can plug the coordinates of the bounding box into the localizer call:: + + landmarks = localizer(image, top, left, height, width) + +In total, 8 ``landmarks`` are returned by the localizer. +For the list and the interpretation of the landmarks, please have a look `here <http://cmp.felk.cvut.cz/~uricamic/flandmark/index.php>`_. + +.. warning:: + Since version 1.1 of this package, the landmarks are returned in the Bob_-typical order, which is ``(y,x)``. + Please update your code to this new behavior. diff --git a/setup.py b/setup.py index f34c75fa8f65ac9f6fca02680891776fc127d45f..2c8089de8bca924aff094bf21cc325e93a1b2c03 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ from xbob.extension import Extension, build_ext setup( name="xbob.flandmark", - version="1.0.11", + version="1.1.0", description="Python bindings to the flandmark keypoint localization library", license="GPLv3", author='Andre Anjos', diff --git a/xbob/flandmark/ext/ext.cpp b/xbob/flandmark/ext/ext.cpp index 767ad38077e08cbb16c8aee4ccd04b551918bcb7..fb45b480b641ba4e2b034818c7ca988f691ba47e 100644 --- a/xbob/flandmark/ext/ext.cpp +++ b/xbob/flandmark/ext/ext.cpp @@ -55,7 +55,7 @@ class Localizer { * flandmark model. */ Localizer(const std::string& opencv_cascade, - const std::string& flandmark_model) : + const std::string& flandmark_model) : m_cascade((CvHaarClassifierCascade*)cvLoad(opencv_cascade.c_str(), 0, 0, 0), std::ptr_fun(delete_cascade)), m_flandmark(flandmark_init(flandmark_model.c_str()), std::ptr_fun(delete_flandmark)), m_storage(cvCreateMemStorage(0), std::ptr_fun(delete_storage)) @@ -63,7 +63,7 @@ class Localizer { if( !m_cascade ) { PYTHON_ERROR(RuntimeError, "Couldnt load Face detector '%s'", opencv_cascade.c_str()); } - + if ( !m_flandmark ) { PYTHON_ERROR(RuntimeError, "Structure model wasn't created. Corrupted file '%s'", flandmark_model.c_str()); } @@ -99,7 +99,7 @@ class Localizer { for (int iface = 0; iface < (rects ? nFaces : 0); ++iface) { CvRect* r = (CvRect*)cvGetSeqElem(rects, iface); - + dict det; det["bbox"] = make_tuple(r->x, r->y, r->width, r->height); int bbox[4] = {r->x, r->y, r->x + r->width, r->y + r->height}; @@ -119,7 +119,7 @@ class Localizer { // The first point represents the center of the bounding box used by // the flandmark library. for (int i = 0; i < (2*m_flandmark->data.options.M); i += 2) { - lmlist.append(make_tuple(m_landmarks[i], m_landmarks[i+1])); + lmlist.append(make_tuple(m_landmarks[i+1], m_landmarks[i])); } } det["landmark"] = tuple(lmlist); @@ -153,12 +153,12 @@ class Localizer { flandmark_result = flandmark_detect(ipl_image.get(), bbox, m_flandmark.get(), m_landmarks.get()); } - + list lmlist; ///< landmark list if (flandmark_result == NO_ERR) { for (int i = 0; i < (2*m_flandmark->data.options.M); i += 2) { - lmlist.append(make_tuple(m_landmarks[i], m_landmarks[i+1])); + lmlist.append(make_tuple(m_landmarks[i+1], m_landmarks[i])); } } diff --git a/xbob/flandmark/script/annotate.py b/xbob/flandmark/script/annotate.py index c565189b3fab49b1ddcae26683618c99e02e8a0b..1963e52e239639afab6eae8780e482dfabc0e5a4 100644 --- a/xbob/flandmark/script/annotate.py +++ b/xbob/flandmark/script/annotate.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: set fileencoding=utf-8 : # Andre Anjos <andre.anjos@idiap.ch> -# Fri 21 Sep 2012 10:43:12 CEST +# Fri 21 Sep 2012 10:43:12 CEST """Annotates videos, dumps annotations as text files. @@ -114,7 +114,7 @@ def main(): bbox = biggest['bbox'] landmarks = biggest['landmark'] output.write("%d %d %d %d %d " % ((k,) + bbox)) - lstr = " ".join("%d %d" % (round(p[0]), round(p[1])) for p in landmarks) + lstr = " ".join("%d %d" % (round(p[1]), round(p[0])) for p in landmarks) output.write(lstr + "\n") if args.verbose and args.output is not None: sys.stdout.write('.') @@ -125,7 +125,7 @@ def main(): if args.verbose and args.output is not None: sys.stdout.write('x') sys.stdout.flush() - + if args.verbose and args.output is not None: sys.stdout.write('\n') sys.stdout.flush()