def ljson_importer(filepath, asset=None, **kwargs): r""" Importer for the Menpo JSON format. This is an n-dimensional landmark type for both images and meshes that encodes semantic labels in the format. Landmark set label: JSON Landmark labels: decided by file Parameters ---------- filepath : `Path` Absolute filepath of the file. asset : `object`, optional An optional asset that may help with loading. This is unused for this implementation. \**kwargs : `dict`, optional Any other keyword arguments. Returns ------- landmarks : :map:`LandmarkGroup` The landmarks including appropriate labels if available. """ with open(str(filepath), 'r') as f: # lms_dict is now a dict rep of the JSON lms_dict = json.load(f, object_pairs_hook=OrderedDict) v = lms_dict.get('version') parser = _ljson_parser_for_version.get(v) if parser is None: raise ValueError("{} has unknown version {} must be " "1, or 2".format(self.filepath, v)) return LandmarkGroup(*parser(lms_dict))
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, copy.deepcopy(landmark_group.lms), {'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
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 = copy.deepcopy(landmark_group.lms) 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
def ibug_close_eye_points(landmark_group): """ Apply the ibug's "standard" close eye semantic labels to the landmarks in the given landmark group. The group label will be 'ibug_close_eye_points'. The semantic labels applied are as follows: - upper eyelid - lower eyelid Parameters ---------- landmark_group : :map:`LandmarkGroup` The landmark group to apply semantic labels to. Returns ------- group_label : `str` The group label: 'ibug_close_eye_points' landmark_group : :map:`LandmarkGroup` New landmark group. Raises ------ :class:`menpo.landmark.exceptions.LabellingError` If the given landmark group contains less than 17 points """ from menpo.shape import PointGraph group_label = 'ibug_close_eye_points' n_expected_points = 17 n_points = landmark_group.lms.n_points _validate_input(landmark_group, n_expected_points, group_label) 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 = zip(bottom_indices, bottom_indices[1:]) lower_connectivity += [(0, 12)] lower_connectivity += zip(middle_indices, middle_indices[1:]) lower_connectivity += [(11, 0)] total_connectivity = np.asarray(upper_connectivity + lower_connectivity) new_landmark_group = LandmarkGroup( PointGraph(landmark_group.lms.points, total_connectivity), OrderedDict([('all', np.ones(n_points, dtype=np.bool))])) new_landmark_group['upper_eyelid'] = upper_indices new_landmark_group['lower_eyelid'] = lower_indices del new_landmark_group['all'] # Remove pointless all group return group_label, new_landmark_group
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 = copy.deepcopy(landmark_group.lms) 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
def ibug_close_eye_trimesh(landmark_group): """ Apply the ibug's "standard" close eye semantic labels to the landmarks in the given landmark group. The group label will be 'ibug_close_eye_trimesh'. The semantic labels applied are as follows: - tri Parameters ---------- landmark_group : :map:`LandmarkGroup` The landmark group to apply semantic labels to. Returns ------- group_label : `str` The group label: 'ibug_close_eye_trimesh' landmark_group : :map:`LandmarkGroup` New landmark group. Raises ------ :class:`menpo.landmark.exceptions.LabellingError` If the given landmark group contains less than 38 points """ from menpo.shape import TriMesh group_label = 'ibug_close_eye_trimesh' n_expected_points = 17 n_points = landmark_group.lms.n_points _validate_input(landmark_group, n_expected_points, group_label) 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_landmark_group = LandmarkGroup( TriMesh(landmark_group.lms.points, tri_list, copy=False), OrderedDict([('tri', np.ones(n_points, dtype=np.bool))])) return group_label, new_landmark_group
def _relabel_group_from_dict(pointcloud, labels_to_ranges): """ Label the given pointcloud according to the given ordered dictionary of labels to ranges. This assumes that you can semantically label the group by using ranges in to the existing points e.g :: labels_to_ranges = {'chin': (0, 17, False)} The third element of the range tuple is whether the range is a closed loop or not. For example, for an eye landmark this would be ``True``, as you do want to create a closed loop for an eye. Parameters ---------- pointcloud : :map:`PointCloud` The pointcloud to apply semantic labels to. labels_to_ranges : `OrderedDict` Ordered dictionary of string labels to range tuples. Returns ------- landmark_group: :map:`LandmarkGroup` New landmark group Raises ------ :class:`menpo.landmark.exceptions.LabellingError` If the given pointcloud contains less than ``n_expected_points`` points. """ from menpo.shape import PointGraph n_points = pointcloud.n_points masks = OrderedDict() adjacency_lists = [] for label, tup in labels_to_ranges.items(): range_tuple = tup[:-1] close_loop = tup[-1] adjacency_lists.append(_connectivity_from_range( range_tuple, close_loop=close_loop)) masks[label] = _mask_from_range(range_tuple, n_points) adjacency_array = np.vstack(adjacency_lists) new_landmark_group = LandmarkGroup( PointGraph(pointcloud.points, adjacency_array), masks) return new_landmark_group
def wrapper(x, return_mapping=False): from menpo.shape import PointCloud # Accepts LandmarkGroup, PointCloud or ndarray if isinstance(x, np.ndarray): x = PointCloud(x, copy=False) if isinstance(x, PointCloud): new_pcloud, mapping = labelling_method(x) # This parameter is only provided for internal use so that # other labellers can piggyback off one another if return_mapping: return new_pcloud, mapping else: return new_pcloud if isinstance(x, LandmarkGroup): new_pcloud, mapping = labelling_method(x.lms) return LandmarkGroup.init_from_indices_mapping( new_pcloud, mapping)
def wrapper(x, return_mapping=False): from menpo.shape import PointCloud # Accepts LandmarkGroup, PointCloud or ndarray if isinstance(x, np.ndarray): x = PointCloud(x, copy=False) if isinstance(x, PointCloud): new_pcloud, mapping = labelling_method(x) # This parameter is only provided for internal use so that # other labellers can piggyback off one another if return_mapping: return new_pcloud, mapping else: return new_pcloud if isinstance(x, LandmarkGroup): new_pcloud, mapping = labelling_method(x.lms) return LandmarkGroup.init_from_indices_mapping(new_pcloud, mapping)
def build(self, asset=None): """ Overrides the :meth:`build <menpo.io.base.Importer.build>` method. Parse the landmark format and return the label and landmark dictionary. Parameters ---------- asset : object, optional The asset that the landmarks are being built for. Can be used to adjust landmarks as necessary (e.g. rescaling image landmarks from 0-1 to image.shape) Returns ------- landmark_group : string The landmark group parsed from the file. Every point will be labelled. """ self._parse_format(asset=asset) return LandmarkGroup(self.pointcloud, self.labels_to_masks)
def lm2_importer(filepath, asset=None, **kwargs): r""" Importer for the LM2 file format from the bosphorus dataset. This is a 2D landmark type and so it is assumed it only applies to images. Landmark set label: LM2 Landmark labels: +------------------------+ | label | +========================+ | outer_left_eyebrow | | middle_left_eyebrow | | inner_left_eyebrow | | inner_right_eyebrow | | middle_right_eyebrow | | outer_right_eyebrow | | outer_left_eye_corner | | inner_left_eye_corner | | inner_right_eye_corner | | outer_right_eye_corner | | nose_saddle_left | | nose_saddle_right | | left_nose_peak | | nose_tip | | right_nose_peak | | left_mouth_corner | | upper_lip_outer_middle | | right_mouth_corner | | upper_lip_inner_middle | | lower_lip_inner_middle | | lower_lip_outer_middle | | chin_middle | +------------------------+ Parameters ---------- filepath : `Path` Absolute filepath of the file. asset : `object`, optional An optional asset that may help with loading. This is unused for this implementation. \**kwargs : `dict`, optional Any other keyword arguments. Returns ------- landmarks : :map:`LandmarkGroup` The landmarks including appropriate labels if available. """ with open(str(filepath), 'r') as f: landmarks = f.read() # Remove comments and blank lines landmark_text = [ l for l in landmarks.splitlines() if (l.rstrip() and '#' not in l) ] # First line says how many landmarks there are: 22 Landmarks # So pop it off the front num_points = int(landmark_text.pop(0).split()[0]) labels = [] # The next set of lines defines the labels labels_str = landmark_text.pop(0) if not labels_str == 'Labels:': raise ValueError("LM2 landmarks are incorrectly formatted. " "Expected a list of labels beginning with " "'Labels:' but found '{0}'".format(labels_str)) for i in range(num_points): # Lowercase, remove spaces and replace with underscores l = landmark_text.pop(0) l = '_'.join(l.lower().split()) labels.append(l) # The next set of lines defines the coordinates coords_str = landmark_text.pop(0) if not coords_str == '2D Image coordinates:': raise ValueError("LM2 landmarks are incorrectly formatted. " "Expected a list of coordinates beginning with " "'2D Image coordinates:' " "but found '{0}'".format(coords_str)) xs = [] ys = [] for i in range(num_points): p = landmark_text.pop(0).split() xs.append(float(p[0])) ys.append(float(p[1])) xs = np.array(xs, dtype=np.float).reshape((-1, 1)) ys = np.array(ys, dtype=np.float).reshape((-1, 1)) # Flip the x and y pointcloud = PointCloud(np.hstack([ys, xs]), copy=False) # Create the mask whereby there is one landmark per label # (identity matrix) masks = np.eye(num_points).astype(np.bool) masks = np.vsplit(masks, num_points) masks = [np.squeeze(m) for m in masks] labels_to_masks = OrderedDict(zip(labels, masks)) return LandmarkGroup(pointcloud, labels_to_masks)
def asf_importer(filepath, asset=None, image_origin=True, **kwargs): r""" Abstract base class for an importer for the ASF file format. Currently **does not support the connectivity specified in the format**. Implementations of this class should override the :meth:`_build_points` which determines the ordering of axes. For example, for images, the `x` and `y` axes are flipped such that the first axis is `y` (height in the image domain). Landmark set label: ASF Landmark labels: +---------+ | label | +=========+ | all | +---------+ Parameters ---------- filepath : `Path` Absolute filepath of the file. asset : `object`, optional An optional asset that may help with loading. This is unused for this implementation. image_origin : `bool`, optional If ``True``, assume that the landmarks exist within an image and thus the origin is the image origin. \**kwargs : `dict`, optional Any other keyword arguments. Returns ------- landmarks : :map:`LandmarkGroup` The landmarks including appropriate labels if available. References ---------- .. [1] http://www2.imm.dtu.dk/~aam/datasets/datasets.html """ with open(str(filepath), 'r') as f: landmarks = f.read() # Remove comments and blank lines landmarks = [ l for l in landmarks.splitlines() if (l.rstrip() and not '#' in l) ] # Pop the front of the list for the number of landmarks count = int(landmarks.pop(0)) # Pop the last element of the list for the image_name image_name = landmarks.pop() xs = np.empty([count, 1]) ys = np.empty([count, 1]) connectivity = np.empty([count, 2], dtype=np.int) for i in range(count): # Though unpacked, they are still all strings # Only unpack the first 7 (path_num, path_type, xpos, ypos, point_num, connects_from, connects_to) = landmarks[i].split()[:7] xs[i, ...] = float(xpos) ys[i, ...] = float(ypos) connectivity[i, ...] = [int(connects_from), int(connects_to)] if image_origin: points = np.hstack([ys, xs]) else: points = np.hstack([xs, ys]) if asset is not None: # we've been given an asset. As ASF files are normalized, # fix that here points = Scale(np.array(asset.shape)).apply(points) # TODO: Use connectivity and create a graph type instead of PointCloud # edges = scaled_points[connectivity] return LandmarkGroup( PointCloud(points, copy=False), OrderedDict([('all', np.ones(points.shape[0], dtype=np.bool))]))
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(copy.deepcopy(landmark_group.lms.points), tri_list), {'all': np.ones(n_points, dtype=np.bool)}) return new_landmark_group
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 = copy.deepcopy(landmark_group.lms) 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
def ibug_open_eye_points(landmark_group): """ Apply the ibug's "standard" open eye semantic labels to the landmarks in the given landmark group. The group label will be 'ibug_open_eye_points'. The semantic labels applied are as follows: - upper eyelid - lower eyelid - iris - pupil - sclera Parameters ---------- landmark_group : :map:`LandmarkGroup` The landmark group to apply semantic labels to. Returns ------- group_label : `str` The group label: 'ibug_open_eye_points' landmark_group : :map:`LandmarkGroup` New landmark group. Raises ------ :class:`menpo.landmark.exceptions.LabellingError` If the given landmark group contains less than 38 points """ from menpo.shape import PointGraph group_label = 'ibug_open_eye_points' n_expected_points = 38 n_points = landmark_group.lms.n_points _validate_input(landmark_group, n_expected_points, group_label) 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 = zip(sclera_top, sclera_top[1:]) sclera_connectivity += [(0, 21)] sclera_connectivity += zip(sclera_bottom, sclera_bottom[1:]) sclera_connectivity += [(6, 17)] lower_el_connectivity = zip(lower_el_top, lower_el_top[1:]) lower_el_connectivity += [(6, 7)] lower_el_connectivity += zip(lower_el_bottom, lower_el_bottom[1:]) lower_el_connectivity += [(11, 0)] total_connectivity = np.asarray(upper_el_connectivity + lower_el_connectivity + iris_connectivity.tolist() + pupil_connectivity.tolist() + sclera_connectivity) new_landmark_group = LandmarkGroup( PointGraph(landmark_group.lms.points, total_connectivity), OrderedDict([('all', np.ones(n_points, dtype=np.bool))])) new_landmark_group['upper_eyelid'] = upper_el_indices new_landmark_group['lower_eyelid'] = lower_el_indices new_landmark_group['pupil'] = np.arange(*pupil_range) new_landmark_group['iris'] = np.arange(*iris_range) new_landmark_group['sclera'] = sclera_indices del new_landmark_group['all'] # Remove pointless all group return group_label, new_landmark_group
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 group label will be 'ibug_68_trimesh'. The semantic labels applied are as follows: - tri Parameters ---------- landmark_group : :map:`LandmarkGroup` The landmark group to apply semantic labels to. Returns ------- group_label : `str` The group label: 'ibug_68_trimesh' landmark_group : :map:`LandmarkGroup` New landmark group. 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_expected_points = 68 n_points = landmark_group.lms.n_points _validate_input(landmark_group, n_expected_points, group_label) 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( TriMesh(landmark_group.lms.points, tri_list, copy=False), OrderedDict([('tri', np.ones(n_points, dtype=np.bool))])) return group_label, new_landmark_group
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, copy.deepcopy(landmark_group.lms), {'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
def pts_importer(filepath, asset=None, image_origin=True, **kwargs): r""" Importer for the PTS file format. Assumes version 1 of the format. Implementations of this class should override the :meth:`_build_points` which determines the ordering of axes. For example, for images, the `x` and `y` axes are flipped such that the first axis is `y` (height in the image domain). Note that PTS has a very loose format definition. Here we make the assumption (as is common) that PTS landmarks are 1-based. That is, landmarks on a 480x480 image are in the range [1-480]. As Menpo is consistently 0-based, we *subtract 1* off each landmark value automatically. If you want to use PTS landmarks that are 0-based, you will have to manually add one back on to landmarks post importing. Landmark set label: PTS Landmark labels: +---------+ | label | +=========+ | all | +---------+ Parameters ---------- filepath : `Path` Absolute filepath of the file. asset : `object`, optional An optional asset that may help with loading. This is unused for this implementation. image_origin : `bool`, optional If ``True``, assume that the landmarks exist within an image and thus the origin is the image origin. \**kwargs : `dict`, optional Any other keyword arguments. Returns ------- landmarks : :map:`LandmarkGroup` The landmarks including appropriate labels if available. """ f = open(str(filepath), 'r') for line in f: if line.split()[0] == '{': break xs = [] ys = [] for line in f: if line.split()[0] != '}': xpos, ypos = line.split()[0:2] xs.append(xpos) ys.append(ypos) xs = np.array(xs, dtype=np.float).reshape((-1, 1)) ys = np.array(ys, dtype=np.float).reshape((-1, 1)) # PTS landmarks are 1-based, need to convert to 0-based (subtract 1) if image_origin: points = np.hstack([ys - 1, xs - 1]) else: points = np.hstack([xs - 1, ys - 1]) return LandmarkGroup( PointCloud(points, copy=False), OrderedDict([('all', np.ones(points.shape[0], dtype=np.bool))]))
def ibug_open_eye_trimesh(landmark_group): """ Apply the ibug's "standard" open eye semantic labels to the landmarks in the given landmark group. The group label will be 'ibug_open_eye_trimesh'. The semantic labels applied are as follows: - tri Parameters ---------- landmark_group : :map:`LandmarkGroup` The landmark group to apply semantic labels to. Returns ------- group_label : `str` The group label: 'ibug_open_eye_trimesh' landmark_group : :map:`LandmarkGroup` New landmark group. Raises ------ :class:`menpo.landmark.exceptions.LabellingError` If the given landmark group contains less than 38 points """ from menpo.shape import TriMesh group_label = 'ibug_open_eye_trimesh' n_expected_points = 38 n_points = landmark_group.lms.n_points _validate_input(landmark_group, n_expected_points, group_label) 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_landmark_group = LandmarkGroup( TriMesh(landmark_group.lms.points, tri_list, copy=False), OrderedDict([('tri', np.ones(n_points, dtype=np.bool))])) return group_label, new_landmark_group