def build_shape_model(shapes, max_components=None): r""" Builds a shape model given a set of shapes. Parameters ---------- shapes: list of :map:`PointCloud` The set of shapes from which to build the model. max_components: None or int or float Specifies the number of components of the trained shape model. If int, it specifies the exact number of components to be retained. If float, it specifies the percentage of variance to be retained. If None, all the available components are kept (100% of variance). Returns ------- shape_model: :class:`menpo.model.pca` The PCA shape model. """ # centralize shapes centered_shapes = [Translation(-s.centre()).apply(s) for s in shapes] # align centralized shape using Procrustes Analysis gpa = GeneralizedProcrustesAnalysis(centered_shapes) aligned_shapes = [s.aligned_source() for s in gpa.transforms] # build shape model shape_model = PCAModel(aligned_shapes) if max_components is not None: # trim shape model if required shape_model.trim_components(max_components) return shape_model
def test_procrustes_no_target(): # square src_1 = PointCloud(np.array([[1.0, 1.0], [1.0, -1.0], [-1.0, -1.0], [-1.0, 1.0]])) # rhombus src_2 = PointCloud(np.array([[2.0, 0.0], [4.0, 2.0], [6.0, 0.0], [4.0, -2.0]])) # trapezoid src_3 = PointCloud(np.array([[-0.5, -1.5], [2.5, -1.5], [2.8, -2.5], [-0.2, -2.5]])) gpa = GeneralizedProcrustesAnalysis([src_1, src_2, src_3], allow_mirror=True) aligned_1 = gpa.transforms[0].apply(gpa.sources[0]) aligned_2 = gpa.transforms[1].apply(gpa.sources[1]) aligned_3 = gpa.transforms[2].apply(gpa.sources[2]) assert(gpa.converged is True) assert(gpa.n_iterations == 5) assert(gpa.n_sources == 3) assert(np.round(gpa.initial_target_scale * 100) == 195.) assert(np.round(gpa.mean_alignment_error() * 10) == 4.) assert_allclose(np.around(aligned_1.points, decimals=1), np.around(aligned_2.points, decimals=1)) res_3 = np.array([[0.7, -0.3], [2.6, -0.4], [2.7, -1.0], [0.9, -0.9]]) assert_allclose(np.around(aligned_3.points, decimals=1), res_3) assert_allclose(gpa.target.points, gpa.mean_aligned_shape().points)
def test_procrustes_with_target(): # square src_1 = PointCloud(np.array([[1.0, 1.0], [1.0, -1.0], [-1.0, -1.0], [-1.0, 1.0]])) # trapezoid src_2 = PointCloud(np.array([[-0.5, -1.5], [2.5, -1.5], [2.8, -2.5], [-0.2, -2.5]])) # rhombus as target src_trg = PointCloud(np.array([[2.0, 0.0], [4.0, 2.0], [6.0, 0.0], [4.0, -2.0]])) gpa = GeneralizedProcrustesAnalysis([src_1, src_2], target=src_trg, allow_mirror=True) aligned_1 = gpa.transforms[0].apply(gpa.sources[0]) aligned_2 = gpa.transforms[1].apply(gpa.sources[1]) assert(gpa.converged is True) assert(gpa.n_iterations == 2) assert(gpa.n_sources == 2) assert(gpa.initial_target_scale == 4.) assert(np.round(gpa.mean_alignment_error() * 100) == 93.) assert_allclose(np.around(aligned_1.points, decimals=1), np.around(src_trg.points, decimals=1)) res_2 = np.array([[2.0, -0.9], [4.9, 1.6], [6.0, 0.9], [3.1, -1.6]]) assert_allclose(np.around(aligned_2.points, decimals=1), res_2) mean = np.array([[2.0, -0.5], [4.5, 1.8], [6.0, 0.5], [3.5, -1.8]]) assert_allclose(np.around(gpa.mean_aligned_shape().points, decimals=1), mean)
def align_shapes(shapes): r""" """ # centralize shapes centered_shapes = [Translation(-s.centre()).apply(s) for s in shapes] # align centralized shape using Procrustes Analysis gpa = GeneralizedProcrustesAnalysis(centered_shapes) return [s.aligned_source() for s in gpa.transforms]
def align_shapes(shapes): r""" Function that aligns a set of shapes by applying Generalized Procrustes Analysis. Parameters ---------- shapes : `list` of `menpo.shape.PointCloud` The input shapes. Returns ------- aligned_shapes : `list` of `menpo.shape.PointCloud` The list of aligned shapes. """ # centralize shapes centered_shapes = [Translation(-s.centre()).apply(s) for s in shapes] # align centralized shape using Procrustes Analysis gpa = GeneralizedProcrustesAnalysis(centered_shapes) return [s.aligned_source() for s in gpa.transforms]