def hierarchy_to_optimal_MumfordShah_energy_cut_hierarchy(tree, vertex_weights, leaf_graph, approximation_piecewise_linear_function=10): """ Transform the given hierarchy into an optimal energy cut hierarchy using the piecewise constant Mumford-Shah energy (see function :func:`~higra.hierarchy_to_optimal_energy_cut_hierarchy`). In this context: - the data fidelity energy assumes a piecewise constant model in each node and is given by the variance of the vertex values inside the node (see function :func:`~higra.attribute_gaussian_region_weights_model`) multiplied by its area, - the regularity energy is given by the length of the contour of the node (see function :func:`~higra.attribute_contour_length`). :param tree: input tree (Concept :class:`~higra.CptHierarchy`) :param vertex_weights: vertex weights of the leaf graph of the input tree :param leaf_graph: leaf graph of the input tree (deduced from :class:`~higra.CptHierarchy`) :param approximation_piecewise_linear_function: Maximum number of pieces used in the approximated piecewise linear model for the energy function (default 10). :return: a tree (Concept :class:`~higra.CptHierarchy`) and its node altitudes """ area = hg.attribute_area(tree, leaf_graph=leaf_graph) _, variance = hg.attribute_gaussian_region_weights_model(tree, vertex_weights, leaf_graph) perimeter = hg.attribute_contour_length(tree, leaf_graph=leaf_graph) if variance.ndim > 1: variance = np.trace(variance, axis1=1, axis2=2) return hierarchy_to_optimal_energy_cut_hierarchy(tree, variance * area, perimeter, int(approximation_piecewise_linear_function))
def attribute_piecewise_constant_Mumford_Shah_energy(tree, vertex_weights, gamma, leaf_graph): """ Piecewise constant Mumford-Shah energy of each node of the input tree. The energy of a node is equal to its data fidelity energy plus gamma times its regularization energy. For the piecewise constant Mumford-Shah model: - the data fidelity energy assumes a piecewise constant model in each node and is given by the variance of the vertex values inside the node (see function :func:`~higra.attribute_gaussian_region_weights_model`) multiplied by its area, - the regularity energy is given by the length of the contour of the node (see function :func:`~higra.attribute_contour_length`). :param tree: input tree (Concept :class:`~higra.CptHierarchy`) :param vertex_weights: vertex weights of the leaf graph of the input tree :param gamma: weighting of the regularization term (should be a positive value) :param leaf_graph: leaf graph of the input tree (deduced from :class:`~higra.CptHierarchy`) :return: a 1d array measuring the energy of each node the input tree """ area = hg.attribute_area(tree, leaf_graph=leaf_graph) _, variance = hg.attribute_gaussian_region_weights_model( tree, vertex_weights, leaf_graph) perimeter = hg.attribute_contour_length(tree, leaf_graph=leaf_graph) if variance.ndim > 1: variance = np.trace(variance, axis1=1, axis2=2) return variance * area + gamma * perimeter
def test_attribute_gaussian_region_weights_model_scalar(self): tree, altitudes = TestAttributes.get_test_tree() vertex_list = hg.attribute_vertex_list(tree) np.random.seed(42) vertex_weights = np.random.rand(tree.num_leaves()) mean, variance = hg.attribute_gaussian_region_weights_model(tree, vertex_weights) for i in tree.leaves_to_root_iterator(): m = np.mean(vertex_weights[vertex_list[i]]) v = np.var(vertex_weights[vertex_list[i]]) self.assertTrue(np.isclose(m, mean[i])) self.assertTrue(np.isclose(v, variance[i]))
def test_attribute_gaussian_region_weights_model_vectorial(self): tree, altitudes = TestAttributes.get_test_tree() vertex_list = hg.attribute_vertex_list(tree) np.random.seed(42) vertex_weights = np.random.rand(tree.num_leaves(), 3) mean, variance = hg.attribute_gaussian_region_weights_model(tree, vertex_weights) for i in tree.leaves_to_root_iterator(include_leaves=True): m = np.mean(vertex_weights[vertex_list[i]], 0) self.assertTrue(np.allclose(m, mean[i, :])) # numpy wrongly interprets a single observation with several variables as # multiple observations of a single variables if i >= tree.num_leaves(): v = np.cov(vertex_weights[vertex_list[i]], rowvar=False, bias=True) self.assertTrue(np.allclose(v, variance[i, ...])) else: v = np.zeros_like(variance[i, ...]) self.assertTrue(np.allclose(v, variance[i, ...]))