Exemple #1
0
def attribute_contour_strength(tree, edge_weights, vertex_perimeter=None, edge_length=None, leaf_graph=None):
    """
    Strength of the contour of each node of the given tree. The strength of the contour of a node is defined as the
    mean edge weights on the contour.

    :param tree: input tree (Concept :class:`~higra.CptHierarchy`)
    :param edge_weights: edge_weights of the leaf graph
    :param vertex_perimeter: perimeter of each vertex of the leaf graph (provided by :func:`~higra.attribute_vertex_perimeter` on `leaf_graph`)
    :param edge_length: length of each edge of the leaf graph (provided by :func:`~higra.attribute_edge_length` on `leaf_graph`)
    :param leaf_graph: (deduced from :class:`~higra.CptHierarchy`)
    :return: a 1d array
    """

    if vertex_perimeter is None:
        vertex_perimeter = hg.attribute_vertex_perimeter(leaf_graph)

    if edge_length is None:
        edge_length = hg.attribute_edge_length(leaf_graph)

    perimeter = attribute_contour_length(tree, vertex_perimeter, edge_length, leaf_graph)

    # perimeter of the root may be null
    if np.isclose(perimeter[-1], 0):
        perimeter[-1] = 1

    if hg.CptRegionAdjacencyGraph.validate(leaf_graph):
        edge_weights = hg.rag_accumulate_on_edges(leaf_graph, hg.Accumulators.sum, edge_weights)

    vertex_weights_sum = hg.accumulate_graph_edges(leaf_graph, edge_weights, hg.Accumulators.sum)
    edge_weights_sum = attribute_contour_length(tree, vertex_weights_sum, edge_weights, leaf_graph)

    return edge_weights_sum / perimeter
Exemple #2
0
def attribute_frontier_length(tree, edge_length=None, leaf_graph=None):
    """
    Length of the frontier represented by each node the given partition tree.

    In a partition tree, each node represent the merging of 2 or more regions.
    The frontier of a node is then defined as the common contour between the merged regions.
    This function compute the length of these common contours as the sum of the length of edges going from one of the
    merged region to the other one.

    The result has the same dtype as the edge_length array.

    :param tree: input tree
    :param edge_length: length of the edges of the leaf graph (provided by :func:`~higra.attribute_edge_length` on `leaf_graph`)
    :param leaf_graph: graph on the leaves of the input tree (deduced from :class:`~higra.CptHierarchy`)
    :return: a 1d array
    """

    if edge_length is None:
        edge_length = hg.attribute_edge_length(leaf_graph)

    lca_map = attribute_lca_map(tree, leaf_graph)

    frontier_length = np.zeros((tree.num_vertices(),), dtype=edge_length.dtype)
    np.add.at(frontier_length, lca_map, edge_length)
    return frontier_length
Exemple #3
0
def attribute_vertex_perimeter(graph, edge_length=None):
    """
    Vertex perimeter of the given graph.
    The perimeter of a vertex is defined as the sum of the length of out-edges of the vertex.

    If the input graph has an attribute value `no_border_vertex_out_degree`, then each vertex perimeter is assumed to be
    equal to this attribute value. This is a convenient method to handle image type graphs where an outer border has to be
    considered.

    :param graph: input graph
    :param edge_length: length of the edges of the input graph (provided by :func:`~higra.attribute_edge_length` on `graph`)
    :return: a nd array
    """
    if edge_length is None:
        edge_length = hg.attribute_edge_length(graph)

    special_case_border_graph = hg.get_attribute(
        graph, "no_border_vertex_out_degree")

    if special_case_border_graph is not None:
        res = np.full((graph.num_vertices(), ),
                      special_case_border_graph,
                      dtype=np.float64)
        res = hg.delinearize_vertex_weights(res, graph)
        return res

    res = hg.accumulate_graph_edges(graph, edge_length, hg.Accumulators.sum)
    res = hg.delinearize_vertex_weights(res, graph)
    return res
Exemple #4
0
 def test_edge_length_rag(self):
     g = hg.get_4_adjacency_graph((2, 3))
     vertex_labels = np.asarray(((1, 2, 2), (3, 3, 3)))
     rag = hg.make_region_adjacency_graph_from_labelisation(
         g, vertex_labels)
     ref = np.asarray((1, 1, 2))
     res = hg.attribute_edge_length(rag)
     self.assertTrue(np.allclose(ref, res))
def binary_partition_tree_MumfordShah_energy(graph,
                                             vertex_values,
                                             vertex_area=None,
                                             vertex_perimeter=None,
                                             edge_length=None,
                                             squared_vertex_values=None):
    """
    Binary partition tree according to the Mumford-Shah energy with a constant piecewise model.

    The distance between two regions is equal to the apparition scale of the merged region.

    See:

        Laurent Guigues, Jean Pierre Cocquerez, Hervé Le Men.
        `Scale-sets Image Analysis. International <https://hal.archives-ouvertes.fr/hal-00705364/file/ijcv_scale-setV11.pdf>`_
        Journal of Computer Vision, Springer Verlag, 2006, 68 (3), pp.289-317


    :param graph: input graph
    :param vertex_values: Sum of values inside each vertex of the input graph (1d array for scalar value or 2d array for
        vectorial values, e.g. RGB pixel values)
    :param vertex_area: area of the vertices of the input graph (provided by :func:`~higra.attribute_vertex_area` on `graph`)
    :param vertex_perimeter: perimeter of the vertices of the input graph (provided by :func:`~higra.attribute_vertex_perimeter` on `graph`)
    :param edge_length: length of the frontier represented by the edges of the input graph
        (provided by :func:`~higra.attribute_edge_length` on `graph`)
    :param squared_vertex_values: Sum of squared values inside each vertex of the input graph (1d array for scalar
        value or 2d array for vectorial values, e.g. RGB pixel values).
        If this argument is not provided, it will default to `vertex_values * vertex_values` which is only correct if a
        vertex contains a single value.
    :return: a tree (Concept :class:`~higra.CptHierarchy`) and its node altitudes
    """
    if vertex_area is None:
        vertex_area = hg.attribute_vertex_area(graph)

    if edge_length is None:
        edge_length = hg.attribute_edge_length(graph)

    if vertex_perimeter is None:
        vertex_perimeter = hg.attribute_vertex_perimeter(graph, edge_length)

    vertex_values = hg.linearize_vertex_weights(vertex_values, graph)
    vertex_area = hg.linearize_vertex_weights(vertex_area, graph)
    vertex_perimeter = hg.linearize_vertex_weights(vertex_perimeter, graph)

    if squared_vertex_values is None:
        squared_vertex_values = vertex_values * vertex_values

    tree, altitudes = hg.cpp._binary_partition_tree_MumfordShah_energy(
        graph,
        vertex_perimeter,
        vertex_area,
        vertex_values,
        squared_vertex_values,
        edge_length)

    hg.CptHierarchy.link(tree, graph)

    return tree, altitudes
Exemple #6
0
def attribute_contour_length(tree,
                             vertex_perimeter=None,
                             edge_length=None,
                             leaf_graph=None):
    """
    Length of the contour (perimeter) of each node of the given tree.

    :param tree: input tree (Concept :class:`~higra.CptHierarchy`)
    :param vertex_perimeter: perimeter of each vertex of the leaf graph (provided by :func:`~higra.attribute_vertex_perimeter` on `leaf_graph`)
    :param edge_length: length of each edge of the leaf graph (provided by :func:`~higra.attribute_edge_length` on `leaf_graph`)
    :param leaf_graph: (deduced from :class:`~higra.CptHierarchy`)
    :return: a 1d array
    """

    if vertex_perimeter is None:
        vertex_perimeter = hg.attribute_vertex_perimeter(leaf_graph)

    if edge_length is None:
        edge_length = hg.attribute_edge_length(leaf_graph)

    if leaf_graph is not None:
        vertex_perimeter = hg.linearize_vertex_weights(vertex_perimeter,
                                                       leaf_graph)

    frontier_length = hg.attribute_frontier_length(tree, edge_length,
                                                   leaf_graph)
    perimeter = hg.accumulate_and_add_sequential(tree, -2 * frontier_length,
                                                 vertex_perimeter,
                                                 hg.Accumulators.sum)

    # hg.cpp._attribute_contour_length_component_tree is more efficient than the partition tree
    # algorithm but it does not work for tree of shapes left in original space (the problem is that
    # two children of a node may become adjacent when the interpolated pixels are removed).

    # if tree.category() == hg.TreeCategory.PartitionTree:
    #     frontier_length = hg.attribute_frontier_length(tree, edge_length, leaf_graph)
    #     perimeter = hg.accumulate_and_add_sequential(tree, -2 * frontier_length, vertex_perimeter,
    #                                                  hg.Accumulators.sum)
    # elif tree.category() == hg.TreeCategory.ComponentTree:
    #     perimeter = hg.cpp._attribute_contour_length_component_tree(tree, leaf_graph, vertex_perimeter,
    #                                                                 edge_length)

    return perimeter
Exemple #7
0
 def test_edge_length(self):
     g = hg.get_4_adjacency_graph((2, 3))
     ref = np.asarray((1, 1, 1, 1, 1, 1, 1))
     res = hg.attribute_edge_length(g)
     self.assertTrue(np.allclose(ref, res))