from collections import OrderedDict
import numpy as np
from ..base import (
validate_input,
connectivity_from_array,
pcloud_and_lgroup_from_ranges,
connectivity_from_range,
labeller_func,
)
[docs]@labeller_func(group_label="face_ibug_68")
def face_ibug_68_to_face_ibug_68(pcloud):
r"""
Apply the IBUG 68-point semantic labels.
The semantic labels are as follows:
- jaw
- left_eyebrow
- right_eyebrow
- nose
- left_eye
- right_eye
- mouth
References
----------
.. [1] http://www.multipie.org/
.. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
"""
from menpo.shape import LabelledPointUndirectedGraph
n_expected_points = 68
validate_input(pcloud, n_expected_points)
jaw_indices = np.arange(0, 17)
lbrow_indices = np.arange(17, 22)
rbrow_indices = np.arange(22, 27)
upper_nose_indices = np.arange(27, 31)
lower_nose_indices = np.arange(31, 36)
leye_indices = np.arange(36, 42)
reye_indices = np.arange(42, 48)
outer_mouth_indices = np.arange(48, 60)
inner_mouth_indices = np.arange(60, 68)
jaw_connectivity = connectivity_from_array(jaw_indices)
lbrow_connectivity = connectivity_from_array(lbrow_indices)
rbrow_connectivity = connectivity_from_array(rbrow_indices)
nose_connectivity = np.vstack(
[
connectivity_from_array(upper_nose_indices),
connectivity_from_array(lower_nose_indices),
]
)
leye_connectivity = connectivity_from_array(leye_indices, close_loop=True)
reye_connectivity = connectivity_from_array(reye_indices, close_loop=True)
mouth_connectivity = np.vstack(
[
connectivity_from_array(outer_mouth_indices, close_loop=True),
connectivity_from_array(inner_mouth_indices, close_loop=True),
]
)
all_connectivity = np.vstack(
[
jaw_connectivity,
lbrow_connectivity,
rbrow_connectivity,
nose_connectivity,
leye_connectivity,
reye_connectivity,
mouth_connectivity,
]
)
mapping = OrderedDict()
mapping["jaw"] = jaw_indices
mapping["left_eyebrow"] = lbrow_indices
mapping["right_eyebrow"] = rbrow_indices
mapping["nose"] = np.hstack((upper_nose_indices, lower_nose_indices))
mapping["left_eye"] = leye_indices
mapping["right_eye"] = reye_indices
mapping["mouth"] = np.hstack((outer_mouth_indices, inner_mouth_indices))
new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
pcloud.points, all_connectivity, mapping
)
return new_pcloud, mapping
[docs]@labeller_func(group_label="face_ibug_68")
def face_ibug_68_mirrored_to_face_ibug_68(pcloud):
r"""
Apply the IBUG 68-point semantic labels, on a pointcloud that has been
mirrored around the vertical axis (flipped around the Y-axis). Thus, on
the flipped image the jaw etc would be the wrong way around. This
rectifies that and returns a new PointCloud whereby all the points
are oriented correctly.
The semantic labels applied are as follows:
- jaw
- left_eyebrow
- right_eyebrow
- nose
- left_eye
- right_eye
- mouth
References
----------
.. [1] http://www.multipie.org/
.. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
"""
new_pcloud, old_map = face_ibug_68_to_face_ibug_68(pcloud, return_mapping=True)
lms_map = np.hstack(
[
old_map["jaw"][::-1],
old_map["right_eyebrow"][::-1],
old_map["left_eyebrow"][::-1],
old_map["nose"][:4],
old_map["nose"][4:][::-1],
np.roll(old_map["right_eye"][::-1], 4),
np.roll(old_map["left_eye"][::-1], 4),
np.roll(old_map["mouth"][:12][::-1], 7),
np.roll(old_map["mouth"][12:][::-1], 5),
]
)
return new_pcloud.from_vector(pcloud.points[lms_map]), old_map
[docs]@labeller_func(group_label="face_ibug_66")
def face_ibug_68_to_face_ibug_66(pcloud):
r"""
Apply the IBUG 66-point semantic labels, but ignoring the 2 points
describing the inner mouth corners).
The semantic labels applied are as follows:
- jaw
- left_eyebrow
- right_eyebrow
- nose
- left_eye
- right_eye
- mouth
References
----------
.. [1] http://www.multipie.org/
.. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
"""
from menpo.shape import LabelledPointUndirectedGraph
n_expected_points = 68
validate_input(pcloud, n_expected_points)
jaw_indices = np.arange(0, 17)
lbrow_indices = np.arange(17, 22)
rbrow_indices = np.arange(22, 27)
upper_nose_indices = np.arange(27, 31)
lower_nose_indices = np.arange(31, 36)
leye_indices = np.arange(36, 42)
reye_indices = np.arange(42, 48)
outer_mouth_indices = np.arange(48, 60)
inner_mouth_indices = np.hstack((48, np.arange(60, 63), 54, np.arange(63, 66)))
jaw_connectivity = connectivity_from_array(jaw_indices)
lbrow_connectivity = connectivity_from_array(lbrow_indices)
rbrow_connectivity = connectivity_from_array(rbrow_indices)
nose_connectivity = np.vstack(
[
connectivity_from_array(upper_nose_indices),
connectivity_from_array(lower_nose_indices),
]
)
leye_connectivity = connectivity_from_array(leye_indices, close_loop=True)
reye_connectivity = connectivity_from_array(reye_indices, close_loop=True)
mouth_connectivity = np.vstack(
[
connectivity_from_array(outer_mouth_indices, close_loop=True),
connectivity_from_array(inner_mouth_indices, close_loop=True),
]
)
all_connectivity = np.vstack(
[
jaw_connectivity,
lbrow_connectivity,
rbrow_connectivity,
nose_connectivity,
leye_connectivity,
reye_connectivity,
mouth_connectivity,
]
)
mapping = OrderedDict()
mapping["jaw"] = jaw_indices
mapping["left_eyebrow"] = lbrow_indices
mapping["right_eyebrow"] = rbrow_indices
mapping["nose"] = np.hstack([upper_nose_indices, lower_nose_indices])
mapping["left_eye"] = leye_indices
mapping["right_eye"] = reye_indices
mapping["mouth"] = np.hstack([outer_mouth_indices, inner_mouth_indices])
# Ignore the two inner mouth points
ind = np.hstack((np.arange(60), np.arange(61, 64), np.arange(65, 68)))
new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
pcloud.points[ind], all_connectivity, mapping
)
return new_pcloud, mapping
[docs]@labeller_func(group_label="face_ibug_51")
def face_ibug_68_to_face_ibug_51(pcloud):
r"""
Apply the IBUG 51-point semantic labels, but removing the annotations
corresponding to the jaw region.
The semantic labels applied are as follows:
- left_eyebrow
- right_eyebrow
- nose
- left_eye
- right_eye
- mouth
References
----------
.. [1] http://www.multipie.org/
.. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
"""
from menpo.shape import LabelledPointUndirectedGraph
n_expected_points = 68
validate_input(pcloud, n_expected_points)
lbrow_indices = np.arange(0, 5)
rbrow_indices = np.arange(5, 10)
upper_nose_indices = np.arange(10, 14)
lower_nose_indices = np.arange(14, 19)
leye_indices = np.arange(19, 25)
reye_indices = np.arange(25, 31)
outer_mouth_indices = np.arange(31, 43)
inner_mouth_indices = np.arange(43, 51)
lbrow_connectivity = connectivity_from_array(lbrow_indices)
rbrow_connectivity = connectivity_from_array(rbrow_indices)
nose_connectivity = np.vstack(
[
connectivity_from_array(upper_nose_indices),
connectivity_from_array(lower_nose_indices),
]
)
leye_connectivity = connectivity_from_array(leye_indices, close_loop=True)
reye_connectivity = connectivity_from_array(reye_indices, close_loop=True)
mouth_connectivity = np.vstack(
[
connectivity_from_array(outer_mouth_indices, close_loop=True),
connectivity_from_array(inner_mouth_indices, close_loop=True),
]
)
all_connectivity = np.vstack(
[
lbrow_connectivity,
rbrow_connectivity,
nose_connectivity,
leye_connectivity,
reye_connectivity,
mouth_connectivity,
]
)
mapping = OrderedDict()
mapping["left_eyebrow"] = lbrow_indices
mapping["right_eyebrow"] = rbrow_indices
mapping["nose"] = np.hstack([upper_nose_indices, lower_nose_indices])
mapping["left_eye"] = leye_indices
mapping["right_eye"] = reye_indices
mapping["mouth"] = np.hstack([outer_mouth_indices, inner_mouth_indices])
# Ignore the two inner mouth points
ind = np.arange(17, 68)
new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
pcloud.points[ind], all_connectivity, mapping
)
return new_pcloud, mapping
[docs]@labeller_func(group_label="face_ibug_49")
def face_ibug_49_to_face_ibug_49(pcloud):
r"""
Apply the IBUG 49-point semantic labels.
The semantic labels applied are as follows:
- left_eyebrow
- right_eyebrow
- nose
- left_eye
- right_eye
- mouth
References
----------
.. [1] http://www.multipie.org/
.. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
"""
from menpo.shape import LabelledPointUndirectedGraph
n_expected_points = 49
validate_input(pcloud, n_expected_points)
lbrow_indices = np.arange(0, 5)
rbrow_indices = np.arange(5, 10)
upper_nose_indices = np.arange(10, 14)
lower_nose_indices = np.arange(14, 19)
leye_indices = np.arange(19, 25)
reye_indices = np.arange(25, 31)
outer_mouth_indices = np.arange(31, 43)
inner_mouth_indices = np.hstack((31, np.arange(43, 46), 37, np.arange(46, 49)))
lbrow_connectivity = connectivity_from_array(lbrow_indices)
rbrow_connectivity = connectivity_from_array(rbrow_indices)
nose_connectivity = np.vstack(
[
connectivity_from_array(upper_nose_indices),
connectivity_from_array(lower_nose_indices),
]
)
leye_connectivity = connectivity_from_array(leye_indices, close_loop=True)
reye_connectivity = connectivity_from_array(reye_indices, close_loop=True)
mouth_connectivity = np.vstack(
[
connectivity_from_array(outer_mouth_indices, close_loop=True),
connectivity_from_array(inner_mouth_indices, close_loop=True),
]
)
all_connectivity = np.vstack(
[
lbrow_connectivity,
rbrow_connectivity,
nose_connectivity,
leye_connectivity,
reye_connectivity,
mouth_connectivity,
]
)
mapping = OrderedDict()
mapping["left_eyebrow"] = lbrow_indices
mapping["right_eyebrow"] = rbrow_indices
mapping["nose"] = np.hstack([upper_nose_indices, lower_nose_indices])
mapping["left_eye"] = leye_indices
mapping["right_eye"] = reye_indices
mapping["mouth"] = np.hstack([outer_mouth_indices, inner_mouth_indices])
# Ignore the two inner mouth points
new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
pcloud.points, all_connectivity, mapping
)
return new_pcloud, mapping
[docs]@labeller_func(group_label="face_ibug_49")
def face_ibug_68_to_face_ibug_49(pcloud):
r"""
Apply the IBUG 49-point semantic labels, but removing the annotations
corresponding to the jaw region and the 2 describing the inner mouth
corners.
The semantic labels applied are as follows:
- left_eyebrow
- right_eyebrow
- nose
- left_eye
- right_eye
- mouth
References
----------
.. [1] http://www.multipie.org/
.. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
"""
from menpo.shape import LabelledPointUndirectedGraph
n_expected_points = 68
validate_input(pcloud, n_expected_points)
lbrow_indices = np.arange(0, 5)
rbrow_indices = np.arange(5, 10)
upper_nose_indices = np.arange(10, 14)
lower_nose_indices = np.arange(14, 19)
leye_indices = np.arange(19, 25)
reye_indices = np.arange(25, 31)
outer_mouth_indices = np.arange(31, 43)
inner_mouth_indices = np.hstack((31, np.arange(43, 46), 37, np.arange(46, 49)))
lbrow_connectivity = connectivity_from_array(lbrow_indices)
rbrow_connectivity = connectivity_from_array(rbrow_indices)
nose_connectivity = np.vstack(
[
connectivity_from_array(upper_nose_indices),
connectivity_from_array(lower_nose_indices),
]
)
leye_connectivity = connectivity_from_array(leye_indices, close_loop=True)
reye_connectivity = connectivity_from_array(reye_indices, close_loop=True)
mouth_connectivity = np.vstack(
[
connectivity_from_array(outer_mouth_indices, close_loop=True),
connectivity_from_array(inner_mouth_indices, close_loop=True),
]
)
all_connectivity = np.vstack(
[
lbrow_connectivity,
rbrow_connectivity,
nose_connectivity,
leye_connectivity,
reye_connectivity,
mouth_connectivity,
]
)
mapping = OrderedDict()
mapping["left_eyebrow"] = lbrow_indices
mapping["right_eyebrow"] = rbrow_indices
mapping["nose"] = np.hstack([upper_nose_indices, lower_nose_indices])
mapping["left_eye"] = leye_indices
mapping["right_eye"] = reye_indices
mapping["mouth"] = np.hstack([outer_mouth_indices, inner_mouth_indices])
# Ignore the two inner mouth points
ind = np.hstack((np.arange(17, 60), np.arange(61, 64), np.arange(65, 68)))
new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
pcloud.points[ind], all_connectivity, mapping
)
return new_pcloud, mapping
[docs]@labeller_func(group_label="face_ibug_68_trimesh")
def face_ibug_68_to_face_ibug_68_trimesh(pcloud):
r"""
Apply the IBUG 68-point semantic labels, with trimesh connectivity.
The semantic labels applied are as follows:
- tri
References
----------
.. [1] http://www.multipie.org/
.. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
"""
from menpo.shape import TriMesh
n_expected_points = 68
validate_input(pcloud, n_expected_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_pcloud = TriMesh(pcloud.points, trilist=tri_list)
mapping = OrderedDict()
mapping["tri"] = np.arange(new_pcloud.n_points)
return new_pcloud, mapping
[docs]@labeller_func(group_label="face_ibug_66_trimesh")
def face_ibug_68_to_face_ibug_66_trimesh(pcloud):
r"""
Apply the IBUG 66-point semantic labels, with trimesh connectivity.
The semantic labels applied are as follows:
- tri
References
----------
.. [1] http://www.multipie.org/
.. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
"""
from menpo.shape import TriMesh
# Apply face_ibug_68_to_face_ibug_66
new_pcloud = face_ibug_68_to_face_ibug_66(pcloud)
# This is in terms of the 66 points
tri_list = np.array(
[
[47, 29, 28],
[44, 43, 23],
[38, 20, 21],
[47, 28, 42],
[40, 41, 37],
[51, 62, 61],
[37, 19, 20],
[28, 40, 39],
[38, 21, 39],
[36, 1, 0],
[48, 59, 4],
[49, 60, 48],
[13, 53, 14],
[60, 51, 61],
[51, 51, 62],
[52, 51, 33],
[49, 50, 60],
[57, 7, 8],
[64, 56, 57],
[35, 30, 29],
[52, 62, 53],
[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],
[3, 49, 48],
[31, 32, 50],
[62, 53, 54],
[48, 4, 3],
[59, 5, 4],
[58, 65, 64],
[5, 59, 58],
[58, 59, 65],
[7, 6, 58],
[64, 57, 58],
[13, 54, 53],
[7, 58, 57],
[6, 5, 58],
[63, 55, 54],
[65, 59, 48],
[31, 50, 49],
[32, 33, 50],
[30, 33, 32],
[34, 52, 33],
[35, 52, 34],
[48, 60, 65],
[64, 63, 56],
[60, 65, 61],
[65, 64, 61],
[57, 56, 9],
[8, 57, 9],
[64, 63, 61],
[9, 56, 10],
[10, 56, 11],
[11, 56, 55],
[11, 55, 12],
[56, 63, 55],
[51, 52, 62],
[55, 54, 12],
[63, 54, 62],
[61, 62, 63],
[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, 60, 51],
[27, 22, 42],
]
)
new_pcloud = TriMesh(new_pcloud.points, trilist=tri_list, copy=False)
mapping = OrderedDict()
mapping["tri"] = np.arange(new_pcloud.n_points)
return new_pcloud, mapping
[docs]@labeller_func(group_label="face_ibug_51_trimesh")
def face_ibug_68_to_face_ibug_51_trimesh(pcloud):
r"""
Apply the IBUG 51-point semantic labels, with trimesh connectivity..
The semantic labels applied are as follows:
- tri
References
----------
.. [1] http://www.multipie.org/
.. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
"""
from menpo.shape import TriMesh
# Apply face_ibug_68_to_face_ibug_51
new_pcloud = face_ibug_68_to_face_ibug_51(pcloud)
# This is in terms of the 51 points
tri_list = np.array(
[
[30, 12, 11],
[27, 26, 6],
[21, 3, 4],
[30, 11, 25],
[32, 44, 43],
[23, 24, 20],
[20, 2, 3],
[11, 23, 22],
[21, 4, 22],
[32, 43, 31],
[50, 42, 43],
[44, 34, 45],
[35, 34, 16],
[44, 50, 43],
[35, 46, 34],
[49, 39, 40],
[18, 13, 12],
[36, 35, 18],
[20, 19, 0],
[1, 20, 0],
[20, 21, 23],
[21, 20, 3],
[2, 20, 1],
[21, 22, 23],
[11, 12, 23],
[24, 19, 20],
[10, 22, 4],
[13, 15, 14],
[16, 34, 33],
[16, 13, 17],
[14, 23, 12],
[14, 24, 23],
[43, 42, 31],
[14, 15, 33],
[41, 50, 49],
[41, 42, 50],
[49, 40, 41],
[33, 44, 32],
[45, 50, 44],
[14, 33, 32],
[15, 16, 33],
[13, 16, 15],
[17, 35, 16],
[18, 35, 17],
[36, 46, 35],
[45, 46, 48],
[45, 34, 46],
[49, 48, 39],
[46, 36, 47],
[45, 49, 50],
[45, 48, 49],
[48, 46, 47],
[39, 48, 38],
[38, 47, 37],
[38, 48, 47],
[47, 36, 37],
[28, 29, 27],
[18, 17, 13],
[10, 11, 22],
[10, 25, 11],
[18, 12, 30],
[13, 14, 12],
[26, 5, 6],
[10, 4, 5],
[7, 27, 6],
[27, 30, 26],
[26, 30, 25],
[29, 18, 30],
[9, 28, 27],
[29, 30, 27],
[8, 27, 7],
[8, 9, 27],
[5, 25, 26],
[33, 34, 44],
[10, 5, 25],
]
)
new_pcloud = TriMesh(new_pcloud.points, trilist=tri_list, copy=False)
mapping = OrderedDict()
mapping["tri"] = np.arange(new_pcloud.n_points)
return new_pcloud, mapping
[docs]@labeller_func(group_label="face_ibug_49_trimesh")
def face_ibug_68_to_face_ibug_49_trimesh(pcloud):
r"""
Apply the IBUG 49-point semantic labels, with trimesh connectivity.
The semantic labels applied are as follows:
- tri
References
----------
.. [1] http://www.multipie.org/
.. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
"""
from menpo.shape import TriMesh
# Apply face_ibug_68_to_face_ibug_49
new_pcloud = face_ibug_68_to_face_ibug_49(pcloud)
# This is in terms of the 49 points
tri_list = np.array(
[
[47, 29, 28],
[44, 43, 23],
[38, 20, 21],
[47, 28, 42],
[40, 41, 37],
[51, 62, 61],
[37, 19, 20],
[28, 40, 39],
[38, 21, 39],
[36, 1, 0],
[48, 59, 4],
[49, 60, 48],
[13, 53, 14],
[60, 51, 61],
[51, 51, 62],
[52, 51, 33],
[49, 50, 60],
[57, 7, 8],
[64, 56, 57],
[35, 30, 29],
[52, 62, 53],
[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],
[3, 49, 48],
[31, 32, 50],
[62, 53, 54],
[48, 4, 3],
[59, 5, 4],
[58, 65, 64],
[5, 59, 58],
[58, 59, 65],
[7, 6, 58],
[64, 57, 58],
[13, 54, 53],
[7, 58, 57],
[6, 5, 58],
[63, 55, 54],
[65, 59, 48],
[31, 50, 49],
[32, 33, 50],
[30, 33, 32],
[34, 52, 33],
[35, 52, 34],
[48, 60, 65],
[64, 63, 56],
[60, 65, 61],
[65, 64, 61],
[57, 56, 9],
[8, 57, 9],
[64, 63, 61],
[9, 56, 10],
[10, 56, 11],
[11, 56, 55],
[11, 55, 12],
[56, 63, 55],
[51, 52, 62],
[55, 54, 12],
[63, 54, 62],
[61, 62, 63],
[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, 60, 51],
[27, 22, 42],
]
)
new_pcloud = TriMesh(new_pcloud.points, trilist=tri_list, copy=False)
mapping = OrderedDict()
mapping["tri"] = np.arange(new_pcloud.n_points)
return new_pcloud, mapping
[docs]@labeller_func(group_label="face_ibug_65")
def face_ibug_68_to_face_ibug_65(pcloud):
r"""
Apply the IBUG 68 point semantic labels, but ignore the 3 points that are
coincident for a closed mouth (bottom of the inner mouth).
The semantic labels applied are as follows:
- jaw
- left_eyebrow
- right_eyebrow
- nose
- left_eye
- right_eye
- mouth
References
----------
.. [1] http://www.multipie.org/
.. [2] http://ibug.doc.ic.ac.uk/resources/300-W/
"""
from menpo.shape import LabelledPointUndirectedGraph
# Apply face_ibug_68_to_face_ibug_68
new_pcloud, mapping = face_ibug_68_to_face_ibug_68(pcloud, return_mapping=True)
# The coincident points are considered the final 3 landmarks (bottom of
# the inner mouth points). We remove all the edges for the inner mouth
# which are the last 8.
edges = new_pcloud.edges[:-8]
# Re-add the inner mouth without the bottom 3 points
edges = np.vstack([edges, connectivity_from_range((60, 65), close_loop=True)])
# Luckily, OrderedDict maintains the original ordering despite updates
outer_mouth_indices = np.arange(48, 60)
inner_mouth_indices = np.arange(60, 65)
mapping["mouth"] = np.hstack([outer_mouth_indices, inner_mouth_indices])
new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
new_pcloud.points[:-3], edges, mapping
)
return new_pcloud, mapping
[docs]@labeller_func(group_label="face_imm_58")
def face_imm_58_to_face_imm_58(pcloud):
r"""
Apply the 58-point semantic labels from the IMM dataset.
The semantic labels applied are as follows:
- jaw
- left_eye
- right_eye
- left_eyebrow
- right_eyebrow
- mouth
- nose
References
----------
.. [1] http://www2.imm.dtu.dk/~aam/
"""
n_expected_points = 58
validate_input(pcloud, n_expected_points)
labels = OrderedDict(
[
("jaw", (0, 13, False)),
("left_eye", (13, 21, True)),
("right_eye", (21, 29, True)),
("left _eyebrow", (29, 34, False)),
("right_eyebrow", (34, 39, False)),
("mouth", (39, 47, True)),
("nose", (47, 58, False)),
]
)
return pcloud_and_lgroup_from_ranges(pcloud, labels)
[docs]@labeller_func(group_label="face_lfpw_29")
def face_lfpw_29_to_face_lfpw_29(pcloud):
r"""
Apply the 29-point semantic labels from the original LFPW dataset.
The semantic labels applied are as follows:
- chin
- left_eye
- right_eye
- left_eyebrow
- right_eyebrow
- mouth
- nose
References
----------
.. [1] http://homes.cs.washington.edu/~neeraj/databases/lfpw/
"""
from menpo.shape import LabelledPointUndirectedGraph
n_expected_points = 29
validate_input(pcloud, n_expected_points)
chin_indices = np.array([28])
outer_leye_indices = np.array([8, 12, 10, 13])
pupil_leye_indices = np.array([16])
outer_reye_indices = np.array([11, 14, 9, 15])
pupil_reye_indices = np.array([17])
lbrow_indices = np.array([0, 4, 2, 5])
rbrow_indices = np.array([3, 6, 1, 7])
outer_mouth_indices = np.array([22, 24, 23, 27])
inner_mouth_indices = np.array([22, 25, 23, 26])
nose_indices = np.array([18, 20, 19, 21])
chin_connectivity = connectivity_from_array(chin_indices, close_loop=True)
leye_connectivity = connectivity_from_array(outer_leye_indices, close_loop=True)
reye_connectivity = connectivity_from_array(outer_reye_indices, close_loop=True)
lbrow_connectivity = connectivity_from_array(lbrow_indices, close_loop=True)
rbrow_connectivity = connectivity_from_array(rbrow_indices, close_loop=True)
mouth_connectivity = np.vstack(
[
connectivity_from_array(outer_mouth_indices, close_loop=True),
connectivity_from_array(inner_mouth_indices, close_loop=True),
]
)
nose_connectivity = connectivity_from_array(nose_indices, close_loop=True)
all_connectivity = np.vstack(
[
chin_connectivity,
leye_connectivity,
reye_connectivity,
lbrow_connectivity,
rbrow_connectivity,
mouth_connectivity,
nose_connectivity,
]
)
mapping = OrderedDict()
mapping["chin"] = chin_indices
mapping["left_eye"] = np.hstack((outer_leye_indices, pupil_leye_indices))
mapping["right_eye"] = np.hstack((outer_reye_indices, pupil_reye_indices))
mapping["left_eyebrow"] = lbrow_indices
mapping["right_eyebrow"] = rbrow_indices
mapping["mouth"] = np.hstack((outer_mouth_indices, inner_mouth_indices))
mapping["nose"] = nose_indices
new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
pcloud.points, all_connectivity, mapping
)
return new_pcloud, mapping
def _build_upper_eyelid():
top_indices = np.arange(0, 7)
middle_indices = np.arange(12, 17)
upper_eyelid_indices = np.hstack((top_indices, middle_indices))
upper_eyelid_connectivity = list(zip(top_indices, top_indices[1:]))
upper_eyelid_connectivity += [(0, 12)]
upper_eyelid_connectivity += list(zip(middle_indices, middle_indices[1:]))
upper_eyelid_connectivity += [(16, 6)]
return upper_eyelid_indices, upper_eyelid_connectivity
[docs]@labeller_func(group_label="eye_ibug_open_38")
def eye_ibug_open_38_to_eye_ibug_open_38(pcloud):
r"""
Apply the IBUG 38-point open eye semantic labels.
The semantic labels applied are as follows:
- upper_eyelid
- lower_eyelid
- iris
- pupil
- sclera
"""
from menpo.shape import LabelledPointUndirectedGraph
n_expected_points = 38
validate_input(pcloud, n_expected_points)
upper_el_indices, upper_el_connectivity = _build_upper_eyelid()
iris_range = (22, 30)
pupil_range = (30, 38)
sclera_top = np.arange(12, 17)
sclera_bottom = np.arange(17, 22)
sclera_indices = np.hstack((0, sclera_top, 6, sclera_bottom))
lower_el_top = np.arange(17, 22)
lower_el_bottom = np.arange(7, 12)
lower_el_indices = np.hstack((6, lower_el_top, 0, lower_el_bottom))
iris_connectivity = connectivity_from_range(iris_range, close_loop=True)
pupil_connectivity = connectivity_from_range(pupil_range, close_loop=True)
sclera_connectivity = list(zip(sclera_top, sclera_top[1:]))
sclera_connectivity += [(0, 21)]
sclera_connectivity += list(zip(sclera_bottom, sclera_bottom[1:]))
sclera_connectivity += [(6, 17)]
lower_el_connectivity = list(zip(lower_el_top, lower_el_top[1:]))
lower_el_connectivity += [(6, 7)]
lower_el_connectivity += list(zip(lower_el_bottom, lower_el_bottom[1:]))
lower_el_connectivity += [(11, 0)]
all_connectivity = np.asarray(
upper_el_connectivity
+ lower_el_connectivity
+ iris_connectivity.tolist()
+ pupil_connectivity.tolist()
+ sclera_connectivity
)
mapping = OrderedDict()
mapping["upper_eyelid"] = upper_el_indices
mapping["lower_eyelid"] = lower_el_indices
mapping["pupil"] = np.arange(*pupil_range)
mapping["iris"] = np.arange(*iris_range)
mapping["sclera"] = sclera_indices
new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
pcloud.points, all_connectivity, mapping
)
return new_pcloud, mapping
[docs]@labeller_func(group_label="eye_ibug_close_17")
def eye_ibug_close_17_to_eye_ibug_close_17(pcloud):
r"""
Apply the IBUG 17-point close eye semantic labels.
The semantic labels applied are as follows:
- upper_eyelid
- lower_eyelid
"""
from menpo.shape import LabelledPointUndirectedGraph
n_expected_points = 17
validate_input(pcloud, n_expected_points)
upper_indices, upper_connectivity = _build_upper_eyelid()
middle_indices = np.arange(12, 17)
bottom_indices = np.arange(6, 12)
lower_indices = np.hstack((bottom_indices, 0, middle_indices))
lower_connectivity = list(zip(bottom_indices, bottom_indices[1:]))
lower_connectivity += [(0, 12)]
lower_connectivity += list(zip(middle_indices, middle_indices[1:]))
lower_connectivity += [(11, 0)]
all_connectivity = np.asarray(upper_connectivity + lower_connectivity)
mapping = OrderedDict()
mapping["upper_eyelid"] = upper_indices
mapping["lower_eyelid"] = lower_indices
new_pcloud = LabelledPointUndirectedGraph.init_from_indices_mapping(
pcloud.points, all_connectivity, mapping
)
return new_pcloud, mapping
[docs]@labeller_func(group_label="eye_ibug_open_38_trimesh")
def eye_ibug_open_38_to_eye_ibug_open_38_trimesh(pcloud):
r"""
Apply the IBUG 38-point open eye semantic labels, with trimesh connectivity.
The semantic labels applied are as follows:
- tri
"""
from menpo.shape import TriMesh
n_expected_points = 38
validate_input(pcloud, n_expected_points)
tri_list = np.array(
[
[29, 36, 28],
[22, 13, 23],
[12, 1, 2],
[29, 30, 37],
[13, 3, 14],
[13, 12, 2],
[19, 8, 9],
[25, 33, 24],
[36, 37, 33],
[24, 32, 31],
[33, 37, 31],
[35, 34, 27],
[35, 36, 33],
[3, 13, 2],
[14, 24, 23],
[33, 32, 24],
[15, 25, 14],
[25, 26, 34],
[22, 30, 29],
[31, 37, 30],
[24, 31, 23],
[32, 33, 31],
[22, 12, 13],
[0, 1, 12],
[14, 23, 13],
[31, 30, 23],
[28, 19, 20],
[21, 11, 0],
[12, 21, 0],
[20, 11, 21],
[20, 10, 11],
[21, 29, 20],
[21, 12, 22],
[30, 22, 23],
[29, 21, 22],
[27, 19, 28],
[29, 37, 36],
[29, 28, 20],
[36, 35, 28],
[20, 19, 10],
[10, 19, 9],
[28, 35, 27],
[19, 19, 8],
[17, 16, 6],
[18, 7, 8],
[25, 34, 33],
[18, 27, 17],
[18, 19, 27],
[18, 17, 7],
[27, 26, 17],
[17, 6, 7],
[14, 25, 24],
[34, 35, 33],
[17, 26, 16],
[27, 34, 26],
[3, 15, 14],
[15, 26, 25],
[4, 15, 3],
[16, 26, 15],
[16, 4, 5],
[16, 15, 4],
[16, 5, 6],
[8, 18, 19],
]
)
new_pcloud = TriMesh(pcloud.points, trilist=tri_list, copy=False)
mapping = OrderedDict()
mapping["tri"] = np.arange(new_pcloud.n_points)
return new_pcloud, mapping
[docs]@labeller_func(group_label="eye_ibug_close_17_trimesh")
def eye_ibug_close_17_to_eye_ibug_close_17_trimesh(pcloud):
r"""
Apply the IBUG 17-point close eye semantic labels, with trimesh
connectivity.
The semantic labels applied are as follows:
- tri
"""
from menpo.shape import TriMesh
n_expected_points = 17
validate_input(pcloud, n_expected_points)
tri_list = np.array(
[
[10, 11, 13],
[3, 13, 2],
[4, 14, 3],
[15, 5, 16],
[12, 11, 0],
[13, 14, 10],
[13, 12, 2],
[14, 13, 3],
[0, 1, 12],
[2, 12, 1],
[13, 11, 12],
[9, 10, 14],
[15, 9, 14],
[7, 8, 15],
[5, 6, 16],
[15, 14, 4],
[7, 15, 16],
[8, 9, 15],
[15, 4, 5],
[16, 6, 7],
]
)
new_pcloud = TriMesh(pcloud.points, trilist=tri_list, copy=False)
mapping = OrderedDict()
mapping["tri"] = np.arange(new_pcloud.n_points)
return new_pcloud, mapping
[docs]@labeller_func(group_label="tongue_ibug_19")
def tongue_ibug_19_to_tongue_ibug_19(pcloud):
r"""
Apply the IBUG 19-point tongue semantic labels.
The semantic labels applied are as follows:
- outline
- bisector
"""
n_expected_points = 19
validate_input(pcloud, n_expected_points)
labels = OrderedDict([("outline", (0, 13, False)), ("bisector", (13, 19, False))])
return pcloud_and_lgroup_from_ranges(pcloud, labels)