-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Allow channels to be at front in generic detector * Normalise to normalize in test * Add thin wrapper around bob.ip.facedetect Training is not supported at the moment and it is not a conda dependency due to only existing on conda-forge at the moment. * Expose bob at top level * Slice off dead greyscale channel for channels_at_back=False * Handle no results (returns None) * Skip bob if bob missing As will be on CI * Actually ImportError rather than Menpo error * Remove appveyor in favour of jenkins * Update docs for bob [ci skip]
- Loading branch information
Patrick Snape
committed
Jun 21, 2016
1 parent
72462fd
commit 33939ee
Showing
13 changed files
with
358 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
.. _menpodetect-bob-BobDetector: | ||
|
||
.. currentmodule:: menpodetect.bob | ||
|
||
BobDetector | ||
=========== | ||
.. autoclass:: BobDetector | ||
:members: | ||
:inherited-members: | ||
:show-inheritance: | ||
|
||
.. automethod:: __call__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
.. _api-bob-index: | ||
|
||
:mod:`menpodetect.bob` | ||
====================== | ||
This module contains a wrapper of the detector provided by the Bob [1]_ [2]_ [3]_ | ||
project. The detector implements a boosted cascade of LBP features. | ||
|
||
Detection | ||
--------- | ||
|
||
.. toctree:: | ||
:maxdepth: 1 | ||
|
||
BobDetector | ||
load_bob_frontal_face_detector | ||
|
||
|
||
References | ||
---------- | ||
.. [1] https://pythonhosted.org/bob.ip.facedetect/ | ||
.. [2] http://idiap.github.io/bob/ | ||
.. [3] Anjos, A., El-Shafey, L., Wallace, R., Günther, M., McCool, C. and Marcel, S. | ||
Bob: a free signal processing and machine learning toolbox for researchers. | ||
ACM-MM |
7 changes: 7 additions & 0 deletions
7
docs/source/api/menpodetect/bob/load_bob_frontal_face_detector.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.. _menpodetect-bob-load_bob_frontal_face_detector: | ||
|
||
.. currentmodule:: menpodetect.bob | ||
|
||
load_bob_frontal_face_detector | ||
============================== | ||
.. autofunction:: load_bob_frontal_face_detector |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from menpo.base import MenpoMissingDependencyError | ||
|
||
|
||
try: | ||
from .detect import load_bob_frontal_face_detector, BobDetector | ||
except MenpoMissingDependencyError: | ||
pass | ||
|
||
# Remove from scope | ||
del MenpoMissingDependencyError |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import bob.ip.facedetect | ||
from menpo.shape import bounding_box | ||
|
||
|
||
def bb_to_pointgraph(bb): | ||
r""" | ||
Convert a `bob.ip.facedetect.BoundingBox` to a | ||
`menpo.shape.PointDirectedGraph`. | ||
This enforces a particular point ordering. | ||
Parameters | ||
---------- | ||
bb : `bob.ip.facedetect.BoundingBox` | ||
The bounding box to convert. | ||
Returns | ||
------- | ||
bounding_box : `menpo.shape.PointDirectedGraph` | ||
A menpo PointDirectedGraph giving the bounding box. | ||
""" | ||
return bounding_box(bb.topleft_f, bb.bottomright_f) | ||
|
||
|
||
def pointgraph_to_bb(pg): | ||
r""" | ||
Convert a `menpo.shape.PointCloud` to a `bob.ip.facedetect.BoundingBox`. | ||
Parameters | ||
---------- | ||
pg : `menpo.shape.PointDirectedGraph` | ||
The Menpo PointDirectedGraph to convert into a rect. No check is done | ||
to see if the PointDirectedGraph actually is a rectangle. | ||
Returns | ||
------- | ||
bounding_box : `bob.ip.facedetect.BoundingBox` | ||
A bob BoundingBox. | ||
""" | ||
return bob.ip.facedetect.BoundingBox(pg.bounds()[0], pg.range()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
from __future__ import division | ||
from functools import partial | ||
from pathlib import Path | ||
|
||
from menpo.base import MenpoMissingDependencyError | ||
|
||
try: | ||
import bob.ip.facedetect | ||
from bob.ip.facedetect.detector.cascade import Cascade | ||
except ImportError: | ||
raise MenpoMissingDependencyError('bob.ip.facedetect') | ||
|
||
from menpodetect.detect import detect | ||
from menpodetect.compatibility import STRING_TYPES | ||
from .conversion import bb_to_pointgraph | ||
|
||
|
||
class _bob_detect(object): | ||
r""" | ||
A utility callable that allows the caching of a bob detector. | ||
This callable is important for presenting the correct parameters to the | ||
user. It also marshalls the return type of the detector back to | ||
`menpo.shape.PointDirectedGraph`. | ||
Parameters | ||
---------- | ||
model : `Path` or `str` or `bob.ip.facedetect.detector.cascade.Cascade` | ||
Either a path to a `bob.ip.facedetect.detector.cascade.Cascade` or a | ||
`bob.ip.facedetect.detector.cascade.Cascade` itself. | ||
Raises | ||
------ | ||
ValueError | ||
If a path was provided and it does not exist. | ||
""" | ||
def __init__(self, model): | ||
if isinstance(model, STRING_TYPES) or isinstance(model, Path): | ||
m_path = Path(model) | ||
if not Path(m_path).exists(): | ||
raise ValueError('Model {} does not exist.'.format(m_path)) | ||
model = Cascade(cascade_file=str(m_path)) | ||
self._bob_model = model | ||
|
||
def __call__(self, uint8_image, threshold=20, minimum_overlap=0.2): | ||
r""" | ||
Perform a detection using the cached bob detector. | ||
Parameters | ||
---------- | ||
uint8_image : `ndarray` | ||
An RGB (3 Channels) or Greyscale (1 Channel) numpy array of uint8 | ||
with **channels at the front**. | ||
threshold : `float`, optional | ||
The threshold of the quality of detected faces. | ||
Detections with a quality lower than this value will not be | ||
considered. Higher thresholds will not detect all faces, while lower | ||
thresholds will generate false detections. | ||
``minimum_overlap`` : `float` ``[0, 1]`` | ||
Computes the best detection using the given minimum overlap. | ||
Returns | ||
------ | ||
bounding_boxes : `list` of `menpo.shape.PointDirectedGraph` | ||
The detected objects. | ||
""" | ||
result = bob.ip.facedetect.detect_all_faces( | ||
uint8_image, cascade=self._bob_model, threshold=threshold, | ||
minimum_overlap=minimum_overlap) | ||
if result is None: | ||
bbs = [] | ||
else: | ||
bbs, confidences = result | ||
return [bb_to_pointgraph(b) for b in bbs] | ||
|
||
|
||
class BobDetector(object): | ||
r""" | ||
A Bob cascade detector. | ||
Wraps a bob cascade detector inside the menpodetect framework and provides | ||
a clean interface to expose the bob arguments. | ||
""" | ||
def __init__(self, model): | ||
self._detector = _bob_detect(model) | ||
|
||
def __call__(self, image, greyscale=False, image_diagonal=None, | ||
group_prefix='bob', threshold=20, minimum_overlap=0.2): | ||
r""" | ||
Perform a detection using the cached bob detector. | ||
The detections will also be attached to the image as landmarks. | ||
Parameters | ||
---------- | ||
image : `menpo.image.Image` | ||
A Menpo image to detect. The bounding boxes of the detected objects | ||
will be attached to this image. | ||
greyscale : `bool`, optional | ||
Convert the image to greyscale or not. | ||
image_diagonal : `int`, optional | ||
The total size of the diagonal of the image that should be used for | ||
detection. This is useful for scaling images up and down for | ||
detection. | ||
group_prefix : `str`, optional | ||
The prefix string to be appended to each each landmark group that is | ||
stored on the image. Each detection will be stored as group_prefix_# | ||
where # is a count starting from 0. | ||
threshold : `float`, optional | ||
The threshold of the quality of detected faces. | ||
Detections with a quality lower than this value will not be | ||
considered. Higher thresholds will not detect all faces, while lower | ||
thresholds will generate false detections. | ||
``minimum_overlap`` : `float` ``[0, 1]`` | ||
Computes the best detection using the given minimum overlap. | ||
Returns | ||
------ | ||
bounding_boxes : `list` of `menpo.shape.PointDirectedGraph` | ||
The detected objects. | ||
""" | ||
detect_partial = partial(self._detector, threshold=threshold, | ||
minimum_overlap=minimum_overlap) | ||
return detect(detect_partial, image, greyscale=greyscale, | ||
image_diagonal=image_diagonal, group_prefix=group_prefix, | ||
channels_at_back=False) | ||
|
||
|
||
def load_bob_frontal_face_detector(): | ||
r""" | ||
Load the bob frontal face detector. | ||
Returns | ||
------- | ||
detector : `BobDetector` | ||
The frontal face detector. | ||
""" | ||
return BobDetector(bob.ip.facedetect.default_cascade()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.