import numpy as np
from menpo.landmark.base import LandmarkGroup
from menpo.landmark.exceptions import LabellingError
[docs]def imm_58_points(landmark_group):
"""
Apply the 58 point semantic labels from the
IMM dataset to the landmarks in the given landmark group.
The label applied to this new manager will be 'imm_58_points'.
The semantic labels applied are as follows:
- chin
- leye
- reye
- leyebrow
- reyebrow
- mouth
- nose
Parameters
----------
landmark_group: :class:`menpo.landmark.base.LandmarkGroup`
The landmark group to apply semantic labels to.
Returns
-------
landmark_group: :class:`menpo.landmark.base.LandmarkGroup`
New landmark group with group label 'imm_58_points'
Raises
------
:class:`menpo.landmark.exceptions.LabellingError`
If the given landmark group contains less than 58 points
References
-----------
.. [1] http://www2.imm.dtu.dk/~aam/
"""
group_label = 'imm_58_points'
n_points = landmark_group.lms.n_points
if n_points != 58:
raise LabellingError("{0} mark-up expects exactly 58 "
"points. However, the given landmark group only "
"has {1} points".format(group_label, n_points))
new_landmark_group = LandmarkGroup(
landmark_group._target, group_label,
landmark_group.lms.copy(),
{'all': np.ones(n_points, dtype=np.bool)})
new_landmark_group['chin'] = np.arange(13)
new_landmark_group['leye'] = np.arange(13, 21)
new_landmark_group['reye'] = np.arange(21, 29)
new_landmark_group['leyebrow'] = np.arange(29, 34)
new_landmark_group['reyebrow'] = np.arange(34, 39)
new_landmark_group['mouth'] = np.arange(39, 47)
new_landmark_group['nose'] = np.arange(47, 58)
return new_landmark_group
[docs]def ibug_68_points(landmark_group):
"""
Apply the ibug's "standard" 68 point semantic labels (based on the
original semantic labels of multiPIE) to the landmark group.
The group label will be 'ibug_68_points'.
The semantic labels applied are as follows:
- chin
- leye
- reye
- leyebrow
- reyebrow
- mouth
- nose
Parameters
----------
landmark_group: :class:`menpo.landmark.base.LandmarkGroup`
The landmark group to apply semantic labels to.
Returns
-------
landmark_group : :class:`menpo.landmark.base.LandmarkGroup`
New landmark group with group label 'ibug_68_points'. The pointcloud
is also copied.
Raises
------
:class:`menpo.landmark.exceptions.LabellingError`
If the given landmark group contains less than 68 points
References
----------
.. [1] http://www.multipie.org/
"""
# TODO: This should probably be some sort of graph that maintains the
# connectivity defined by ibug (and thus not a PointCloud)
group_label = 'ibug_68_points'
n_points = landmark_group.lms.n_points
if n_points != 68:
raise LabellingError("{0} mark-up expects exactly 68 "
"points. However, the given landmark group only "
"has {1} points".format(group_label, n_points))
new_landmark_group = LandmarkGroup(
landmark_group._target, group_label,
landmark_group.lms.copy(),
{'all': np.ones(n_points, dtype=np.bool)})
new_landmark_group['chin'] = np.arange(17)
new_landmark_group['leye'] = np.arange(36, 42)
new_landmark_group['reye'] = np.arange(42, 48)
new_landmark_group['leyebrow'] = np.arange(17, 22)
new_landmark_group['reyebrow'] = np.arange(22, 27)
new_landmark_group['mouth'] = np.arange(48, 68)
new_landmark_group['nose'] = np.arange(27, 36)
return new_landmark_group
[docs]def ibug_68_contour(landmark_group):
"""
Apply the ibug's "standard" 68 point semantic labels (based on the
original semantic labels of multiPIE) to the landmarks in
the given landmark manager.
The label applied to this new group will be 'ibug_68_contour'.
The semantic labels applied are as follows:
- contour
Parameters
----------
landmark_group: :class:`menpo.landmark.base.LandmarkGroup`
The landmark group to apply semantic labels to.
Returns
-------
landmark_group : :class:`menpo.landmark.base.LandmarkGroup`
New landmark group with label 'ibug_68_contour'
Raises
------
:class:`menpo.landmark.exceptions.LabellingError`
If the given landmark set contains less than 68 points
References
----------
.. [1] http://www.multipie.org/
"""
# TODO: This should probably be some sort of graph that maintains the
# connectivity defined by ibug (and thus not a PointCloud)
group_label = 'ibug_68_contour'
n_points = landmark_group.lms.n_points
if n_points != 68:
raise LabellingError("{0} mark-up expects exactly 68 "
"points. However, the given landmark group only "
"has {1} points".format(group_label, n_points))
new_landmarks = landmark_group.lms.copy()
ind = np.hstack((np.arange(17), np.arange(16, 21),
np.arange(21, 26), np.arange(1)))
new_landmarks.points = new_landmarks.points[ind]
new_landmark_group = LandmarkGroup(
landmark_group._target, group_label, new_landmarks,
{'all': np.ones(new_landmarks.n_points, dtype=np.bool)})
return new_landmark_group
[docs]def ibug_68_trimesh(landmark_group):
"""
Apply the ibug's "standard" 68 point semantic labels (based on the
original semantic labels of multiPIE) to the landmarks in
the given landmark group.
The label applied to this new group will be 'ibug_68_trimesh'.
The semantic labels applied are as follows:
- tri
Parameters
----------
landmark_group: :class:`menpo.landmark.base.LandmarkGroup`
The landmark group to apply semantic labels to.
Returns
-------
landmark_group : :class:`menpo.landmark.base.LandmarkGroup`
New landmark manager with label 'ibug_68_trimesh'
Raises
------
:class:`menpo.landmark.exceptions.LabellingError`
If the given landmark group contains less than 68 points
References
----------
.. [1] http://www.multipie.org/
"""
from menpo.shape import TriMesh
group_label = 'ibug_68_trimesh'
n_points = landmark_group.lms.n_points
if n_points != 68:
raise LabellingError("{0} mark-up expects exactly 68 "
"points. However, the given landmark group only "
"has {1} points".format(group_label, n_points))
tri_list = np.array([[47, 29, 28], [44, 43, 23], [38, 20, 21], [47, 28,42],
[49, 61, 60], [40, 41, 37], [37, 19, 20], [28, 40, 39],
[38, 21, 39], [36, 1, 0], [48, 59, 4], [49, 60, 48],
[67, 59, 60], [13, 53, 14], [61, 51, 62], [57, 8, 7],
[52, 51, 33], [61, 67, 60], [52, 63, 51], [66, 56, 57],
[35, 30, 29], [53, 52, 35], [37, 36, 17], [18, 37, 17],
[37, 38, 40], [38, 37, 20], [19, 37, 18], [38, 39, 40],
[28, 29, 40], [41, 36, 37], [27, 39, 21], [41, 31, 1],
[30, 32, 31], [33, 51, 50], [33, 30, 34], [31, 40, 29],
[36, 0, 17], [31, 2, 1], [31, 41, 40], [ 1, 36, 41],
[31, 49, 2], [ 2, 49, 3], [60, 59, 48], [ 3, 49, 48],
[31, 32, 50], [48, 4, 3], [59, 5, 4], [58, 67, 66],
[ 5, 59, 58], [58, 59, 67], [ 7, 6, 58], [66, 57, 58],
[13, 54, 53], [ 7, 58, 57], [ 6, 5, 58], [50, 61, 49],
[62, 67, 61], [31, 50, 49], [32, 33, 50], [30, 33, 32],
[34, 52, 33], [35, 52, 34], [53, 63, 52], [62, 63, 65],
[62, 51, 63], [66, 65, 56], [63, 53, 64], [62, 66, 67],
[62, 65, 66], [57, 56, 9], [65, 63, 64], [ 8, 57, 9],
[ 9, 56, 10], [10, 56, 11], [11, 56, 55], [11, 55, 12],
[56, 65, 55], [55, 64, 54], [55, 65, 64], [55, 54, 12],
[64, 53, 54], [12, 54, 13], [45, 46, 44], [35, 34, 30],
[14, 53, 35], [15, 46, 45], [27, 28, 39], [27, 42, 28],
[35, 29, 47], [30, 31, 29], [15, 35, 46], [15, 14, 35],
[43, 22, 23], [27, 21, 22], [24, 44, 23], [44, 47, 43],
[43, 47, 42], [46, 35, 47], [26, 45, 44], [46, 47, 44],
[25, 44, 24], [25, 26, 44], [16, 15, 45], [16, 45, 26],
[22, 42, 43], [50, 51, 61], [27, 22, 42]])
new_landmark_group = LandmarkGroup(
landmark_group._target, group_label,
TriMesh(landmark_group.lms.points, tri_list),
{'all': np.ones(n_points, dtype=np.bool)})
return new_landmark_group
# TODO: ibug_68_all? imports points, contour and trimesh?
[docs]def ibug_68_closed_mouth(landmark_group):
"""
Apply the ibug's "standard" 68 point semantic labels (based on the
original semantic labels of multiPIE) to the landmarks in
the given landmark group - but ignore the 3 points that are coincident for
a closed mouth. Therefore, there only 65 points are returned.
The label applied to this new group will be 'ibug_68_closed_mouth'.
The semantic labels applied are as follows:
- tri
Parameters
----------
landmark_group: :class:`menpo.landmark.base.LandmarkGroup`
The landmark group to apply semantic labels to.
Returns
-------
landmark_group : :class:`menpo.landmark.base.LandmarkGroup`
New landmark manager with label 'ibug_68_closed_mouth'
Raises
------
:class:`menpo.landmark.exceptions.LabellingError`
If the given landmark group contains less than 65 points
References
----------
.. [1] http://www.multipie.org/
"""
group_label = 'ibug_68_closed_mouth'
n_points = landmark_group.lms.n_points
if landmark_group.lms.n_points != 68:
raise LabellingError("{0} mark-up expects exactly 68 "
"points. However, the given landmark group only "
"has {1} points".format(group_label, n_points))
# Ignore the 3 coincident points (the last 3 points)
new_landmarks = landmark_group.lms.copy()
new_landmarks.points = new_landmarks.points[:-3]
new_landmark_group = LandmarkGroup(
landmark_group._target, group_label, new_landmarks,
{'all': np.ones(new_landmarks.n_points, dtype=np.bool)})
new_landmark_group['chin'] = np.arange(17)
new_landmark_group['leye'] = np.arange(36, 42)
new_landmark_group['reye'] = np.arange(42, 48)
new_landmark_group['leyebrow'] = np.arange(17, 22)
new_landmark_group['reyebrow'] = np.arange(22, 27)
new_landmark_group['mouth'] = np.arange(48, 65)
new_landmark_group['nose'] = np.arange(27, 36)
return new_landmark_group
[docs]def ibug_66_points(landmark_group):
"""
Apply the ibug's "standard" 66 point semantic labels (based on the
original semantic labels of multiPIE but ignoring the 2 points
describing the inner mouth corners) to the landmark group.
The group label will be 'ibug_66_points'.
The semantic labels applied are as follows:
- chin
- leye
- reye
- leyebrow
- reyebrow
- mouth
- nose
Parameters
----------
landmark_group: :class:`menpo.landmark.base.LandmarkGroup`
The landmark group to apply semantic labels to.
Returns
-------
landmark_group : :class:`menpo.landmark.base.LandmarkGroup`
New landmark group with group label 'ibug_66_points'. The pointcloud
is also copied.
Raises
------
:class:`menpo.landmark.exceptions.LabellingError`
If the given landmark group contains less than 68 points
References
----------
.. [1] http://www.multipie.org/
"""
group_label = 'ibug_66_points'
n_points = landmark_group.lms.n_points
if landmark_group.lms.n_points != 68:
raise LabellingError("{0} mark-up expects exactly 68 "
"points. However, the given landmark group only "
"has {1} points".format(group_label, n_points))
# Ignore the 2 inner mouth corners
new_landmarks = landmark_group.lms.copy()
ind = np.hstack((np.arange(0, 60), np.arange(61, 64),
np.arange(65, 68)))
new_landmarks.points = new_landmarks.points[ind]
new_landmark_group = LandmarkGroup(
landmark_group._target, group_label, new_landmarks,
{'all': np.ones(new_landmarks.n_points, dtype=np.bool)})
new_landmark_group['chin'] = np.arange(17)
new_landmark_group['leye'] = np.arange(36, 42)
new_landmark_group['reye'] = np.arange(42, 48)
new_landmark_group['leyebrow'] = np.arange(17, 22)
new_landmark_group['reyebrow'] = np.arange(22, 27)
new_landmark_group['mouth'] = np.arange(48, 66)
new_landmark_group['nose'] = np.arange(27, 36)
return new_landmark_group
[docs]def ibug_51_points(landmark_group):
"""
Apply the ibug's "standard" 51 point semantic labels (based on the
original semantic labels of multiPIE but removing the annotations
corresponding to the chin region) to the landmark group.
The group label will be 'ibug_51_points'.
The semantic labels applied are as follows:
- leye
- reye
- leyebrow
- reyebrow
- mouth
- nose
Parameters
----------
landmark_group: :class:`menpo.landmark.base.LandmarkGroup`
The landmark group to apply semantic labels to.
Returns
-------
landmark_group : :class:`menpo.landmark.base.LandmarkGroup`
New landmark group with group label 'ibug_51_points'. The pointcloud
is also copied.
Raises
------
:class:`menpo.landmark.exceptions.LabellingError`
If the given landmark group contains less than 68 points
References
----------
.. [1] http://www.multipie.org/
"""
group_label = 'ibug_51_points'
n_points = landmark_group.lms.n_points
if landmark_group.lms.n_points != 68:
raise LabellingError("{0} mark-up expects exactly 68 "
"points. However, the given landmark group only "
"has {1} points".format(group_label, n_points))
# Ignore the chin region
new_landmarks = landmark_group.lms.copy()
ind = np.arange(17, 68)
new_landmarks.points = new_landmarks.points[ind]
new_landmark_group = LandmarkGroup(
landmark_group._target, group_label, new_landmarks,
{'all': np.ones(new_landmarks.n_points, dtype=np.bool)})
new_landmark_group['leye'] = np.arange(19, 25)
new_landmark_group['reye'] = np.arange(25, 31)
new_landmark_group['leyebrow'] = np.arange(0, 5)
new_landmark_group['reyebrow'] = np.arange(5, 10)
new_landmark_group['mouth'] = np.arange(31, 51)
new_landmark_group['nose'] = np.arange(10, 19)
return new_landmark_group
[docs]def ibug_49_points(landmark_group):
"""
Apply the ibug's "standard" 49 point semantic labels (based on the
original semantic labels of multiPIE but removing the annotations
corresponding to the chin region and the 2 describing the inner mouth
corners) to the landmark group.
The group label will be 'ibug_49_points'.
The semantic labels applied are as follows:
- leye
- reye
- leyebrow
- reyebrow
- mouth
- nose
Parameters
----------
landmark_group: :class:`menpo.landmark.base.LandmarkGroup`
The landmark group to apply semantic labels to.
Returns
-------
landmark_group : :class:`menpo.landmark.base.LandmarkGroup`
New landmark group with group label 'ibug_49_points'. The pointcloud
is also copied.
Raises
------
:class:`menpo.landmark.exceptions.LabellingError`
If the given landmark group contains less than 68 points
References
----------
.. [1] http://www.multipie.org/
"""
group_label = 'ibug_49_points'
n_points = landmark_group.lms.n_points
if landmark_group.lms.n_points != 68:
raise LabellingError("{0} mark-up expects exactly 68 "
"points. However, the given landmark group only "
"has {1} points".format(group_label, n_points))
# Ignore the chin region and the 2 inner mouth corners
new_landmarks = landmark_group.lms.copy()
ind = np.hstack((np.arange(17, 60), np.arange(61, 64),
np.arange(65, 68)))
new_landmarks.points = new_landmarks.points[ind]
new_landmark_group = LandmarkGroup(
landmark_group._target, group_label, new_landmarks,
{'all': np.ones(new_landmarks.n_points, dtype=np.bool)})
new_landmark_group['leye'] = np.arange(19, 25)
new_landmark_group['reye'] = np.arange(25, 31)
new_landmark_group['leyebrow'] = np.arange(0, 5)
new_landmark_group['reyebrow'] = np.arange(5, 10)
new_landmark_group['mouth'] = np.arange(31, 49)
new_landmark_group['nose'] = np.arange(10, 19)
return new_landmark_group
[docs]def labeller(landmarkable, group_label, label_func):
"""
Takes a landmarkable object and a group label indicating which
set of landmarks should have semantic meaning attached to them.
The labelling function will add a new landmark group to each object that
have been semantically annotated.
Parameters
----------
landmarkable: :class:`menpo.landmark.base.Landmarkable`
Landmarkable object
group_label: string
The group label of the landmark group to apply semantic labels to.
label_func: func
A labelling function taken from this module. `func` should take a
:class:`menpo.landmark.base.LandmarkGroup` and
return a new LandmarkGroup with semantic labels applied.
Returns
-------
landmarkable : :class:`menpo.landmark.base.Landmarkable`
landmarkable with label (this is just for convenience,
the object will actually be modified in place)
"""
group = label_func(landmarkable.landmarks[group_label])
landmarkable.landmarks[group.group_label] = group
return landmarkable