From 0a9a72d7c5c3de490c0c7a7f2725f05cced5c92e Mon Sep 17 00:00:00 2001 From: Laurent El Shafey <Laurent.El-Shafey@idiap.ch> Date: Wed, 20 Mar 2013 16:57:30 +0100 Subject: [PATCH] Add support to localize keypoints from an already detected faces/bounding box --- setup.py | 2 +- xbob/flandmark/__init__.py | 36 +++++++++++++++++++++++++++++++++++ xbob/flandmark/ext/ext.cpp | 39 +++++++++++++++++++++++++++++++++++--- 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index a3098ef..1ff89aa 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.7", + version="1.0.8", description="Python bindings to the flandmark keypoint localization library", license="GPLv3", author='Andre Anjos', diff --git a/xbob/flandmark/__init__.py b/xbob/flandmark/__init__.py index 488e568..8e637dc 100644 --- a/xbob/flandmark/__init__.py +++ b/xbob/flandmark/__init__.py @@ -88,3 +88,39 @@ class Localizer(_flandmark.Localizer): else: raise TypeError, "Localizer accepts images as numpy.ndarray objects with either 2 or 3 dimensions" + + def __call__(self, image, b_y, b_x, b_height, b_width): + """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. + + b_y + The top-left y-coordinate of the bounding box + + b_x + The top-left x-coordinate of the bounding box + + b_height + The height of the bounding box + + b_width + The width of the bounding box + + Returns the landmarks which are a list of tuples + (representing x,y coordinates) with the landmarks. + """ + + if image.ndim == 3: + from bob.ip import rgb_to_gray + gray = rgb_to_gray(image) + return super(Localizer, self).__call__(gray, b_y, b_x, b_height, b_width) + + elif image.ndim == 2: + return super(Localizer, self).__call__(gray, b_y, b_x, b_height, b_width) + + else: + raise TypeError, "Localizer accepts images as numpy.ndarray objects with either 2 or 3 dimensions" diff --git a/xbob/flandmark/ext/ext.cpp b/xbob/flandmark/ext/ext.cpp index c25eb2c..9fea90b 100644 --- a/xbob/flandmark/ext/ext.cpp +++ b/xbob/flandmark/ext/ext.cpp @@ -64,9 +64,9 @@ class Localizer { } /** - * Locates the landmarks from an input image + * Detect and locates the landmarks from an input image */ - tuple operator() (bob::python::const_ndarray input) { + tuple call1(bob::python::const_ndarray input) { //checks type const bob::core::array::typeinfo& type = input.type(); if ((type.dtype != bob::core::array::t_uint8) || (type.nd != 2)) { @@ -115,9 +115,41 @@ class Localizer { } return tuple(retval); + } + + + /** + * Detect and locates the landmarks from an input image + */ + object call2(bob::python::const_ndarray input, const int b_y, const int b_x, const int b_height, const int b_width) + { + //checks type + const bob::core::array::typeinfo& type = input.type(); + if ((type.dtype != bob::core::array::t_uint8) || (type.nd != 2)) { + PYTHON_ERROR(TypeError, "Input data must be a 2D numpy.array with dtype=uint8 (i.e. a gray-scaled image), but you passed %s", type.str().c_str()); + } + //converts to IplImage + boost::shared_ptr<IplImage> ipl_image(cvCreateImageHeader(cvSize(type.shape[1], type.shape[0]), IPL_DEPTH_8U, 1), std::ptr_fun(delete_image)); + ipl_image->imageData = (char*)input.bz<uint8_t,2>().data(); + + int bbox[4] = {b_x, b_y, b_x + b_width, b_y + b_height}; + { + bob::python::no_gil unlock; + flandmark_detect(ipl_image.get(), bbox, m_flandmark.get(), + m_landmarks.get()); + } + + list lmlist; ///< landmark list + + for (int i = 0; i < (2*m_flandmark->data.options.M); i += 2) { + lmlist.append(make_tuple(m_landmarks[i], m_landmarks[i+1])); + } + + return object(lmlist); } + private: //representation boost::shared_ptr<CvHaarClassifierCascade> m_cascade; @@ -131,6 +163,7 @@ BOOST_PYTHON_MODULE(_flandmark) { bob::python::setup_python("bindings to flandmark - a library for the localization of facial landmarks"); class_<Localizer>("Localizer", "A key-point localization for faces using flandmark", init<const std::string&, const std::string&>((arg("detector"), arg("localizer")), "Initializes with both an OpenCV face detector model and an flandmark model")) - .def("__call__", &Localizer::operator(), (arg("self"), arg("image")), "Locates (possibly multiple) key-points on the given input image. Returns a list of located faces (by OpenCV's model), each attached to a list of key-points.") + .def("__call__", &Localizer::call1, (arg("image")), "Locates (possibly multiple) key-points on the given input image. Returns a list of located faces (by OpenCV's model), each attached to a list of key-points.") + .def("__call__", &Localizer::call2, (arg("image"), arg("b_y"), arg("b_x"), arg("b_height"), arg("b_width")), "Locates (possibly multiple) key-points on the given input image, given a bounding box and returns them as a list.") ; } -- GitLab