Esempio n. 1
0
def mean_pb_hierarchy(graph, edge_weights, shape, edge_orientations=None):
    """
    Mean probability boundary hierarchy.

    The method is described in:

        P. Arbelaez, M. Maire, C. Fowlkes and J. Malik, "Contour Detection and Hierarchical Image Segmentation,"
        in IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 33, no. 5, pp. 898-916, May 2011.
        doi: 10.1109/TPAMI.2010.161

    This does not include gradient estimation.

    The returned hierarchy is defined on the gradient watershed super-pixels.

    The final sigmoid scaling of the hierarchy altitude is not performed.

    :param graph: must be a 4 adjacency graph (Concept :class:`~higra.CptGridGraph`)
    :param edge_weights: gradient value on edges
    :param shape: shape of the graph, i.e. a pair (height, width) (deduced from :class:`~higra.CptGridGraph`)
    :param edge_orientations: estimated orientation of the gradient on edges (optional)
    :return: a tree (Concept :class:`~higra.CptHierarchy`) and its node altitudes
    """

    shape = hg.normalize_shape(shape)
    if edge_orientations is not None:
        edge_weights, edge_orientations = hg.cast_to_common_type(
            edge_weights, edge_orientations)
    rag, vertex_map, edge_map, tree, altitudes = hg.cpp._mean_pb_hierarchy(
        graph, shape, edge_weights, edge_orientations)

    hg.CptRegionAdjacencyGraph.link(rag, graph, vertex_map, edge_map)
    hg.CptHierarchy.link(tree, rag)

    return tree, altitudes
Esempio n. 2
0
def oriented_watershed(graph, edge_weights, shape, edge_orientations=None):
    """
    Creates a region adjacency graph (rag) with the oriented watershed transform.

    The method is described in:

        P. Arbelaez, M. Maire, C. Fowlkes and J. Malik, "Contour Detection and Hierarchical Image Segmentation,"
        in IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 33, no. 5, pp. 898-916, May 2011.
        doi: 10.1109/TPAMI.2010.161

    If no edge orientations are provided, then the weight of a rag edge between region i and j is the mean weight of the
    edges linking a vertex of i to a vertex of j.

    This does not include gradient estimation.

    :param graph: must be a 4 adjacency graph (Concept :class:`~higra.CptGridGraph`)
    :param edge_weights: gradient value on edges
    :param shape: shape of the graph, i.e. a pair (height, width) (deduced from :class:`~higra.CptGridGraph`)
    :param edge_orientations: estimated orientation of the gradient on edges (optional)
    :return: a pair (rag, rag_edge_weights): the region adjacency graph (Concept :class:`~higra.CptRegionAdjacencyGraph`) and its estimated edge_weights
    """

    shape = hg.normalize_shape(shape)
    if edge_orientations is not None:
        edge_weights, edge_orientations = hg.cast_to_common_type(
            edge_weights, edge_orientations)
    rag, vertex_map, edge_map, rag_edge_weights = hg.cpp._oriented_watershed(
        graph, shape, edge_weights, edge_orientations)

    hg.CptRegionAdjacencyGraph.link(rag, graph, vertex_map, edge_map)

    return rag, rag_edge_weights
Esempio n. 3
0
def get_nd_regular_implicit_graph(shape, neighbour_list):
    """
    Creates an implicit regular graph of the given :attr:`shape` with the adjacency given as a
    :attr:`neighbour_list`.

    See the helper function :func:`~higra.mask_2_neighbours` to create a suitable :attr:`neighbour_list`.

    :Example:

    Create a 2d 4-adjacency implicit graph of size ``(13, 24)``:

    >>> graph = get_nd_regular_implicit_graph((13, 24), ((-1, 0), (0, -1), (0, 1), (1, 0)))

    Create a 3d 6-adjacency implicit graph of size ``(10, 13, 24)``:

    >>> mask = [[[0, 0, 0], [0, 1, 0], [0, 0, 0]],
    >>>         [[0, 1, 0], [1, 0, 1], [0, 1, 0]],
    >>>         [[0, 0, 0], [0, 1, 0], [0, 0, 0]]]
    >>> neighbours = mask_2_neighbours(mask)
    >>> graph = get_nd_regular_implicit_graph((10, 13, 24), neighbours)

    :param shape: a tuple of :math:`n` elements representing the dimension of the graph vertices.
    :param neighbour_list: a 2d array of :math:`k` :math:`n`-d integer vectors
    :return: an implicit regular graph
    """

    neighbour_list = np.asarray(neighbour_list)

    if not np.issubdtype(neighbour_list.dtype, np.integer):
        raise ValueError("'neighbour_list' must be of integral type.")

    if neighbour_list.ndim != 2:
        raise ValueError("'neighbour_list' must be a 2d array.")

    shape = hg.normalize_shape(shape)

    if len(shape) != neighbour_list.shape[1]:
        raise ValueError(
            "Shape size does not match provided adjacency dimension.")

    if len(shape) > 5 or len(shape) == 0:
        raise ValueError("Shape size must between 1 and 5 (included).")

    if len(shape) == 1:
        graph = hg.RegularGraph1d(shape, neighbour_list)
    elif len(shape) == 2:
        graph = hg.RegularGraph2d(shape, neighbour_list)
    elif len(shape) == 3:
        graph = hg.RegularGraph3d(shape, neighbour_list)
    elif len(shape) == 4:
        graph = hg.RegularGraph4d(shape, neighbour_list)
    elif len(shape) == 5:
        graph = hg.RegularGraph5d(shape, neighbour_list)

    hg.CptGridGraph.link(graph, shape)
    hg.set_attribute(graph, "no_border_vertex_out_degree",
                     neighbour_list.shape[0])

    return graph
Esempio n. 4
0
    def rebuild_mean_pb_hierarchy(self, rag, vertex_map, edge_map, tree,
                                  altitudes, shape):

        shape = hg.normalize_shape(shape)
        graph = hg.get_4_adjacency_graph(shape)
        hg.CptRegionAdjacencyGraph.link(rag, graph, vertex_map, edge_map)
        hg.CptHierarchy.link(tree, rag)

        return tree, altitudes
Esempio n. 5
0
def ___new__(cls, shape, neighbour_list):
    if hg.is_iterable(shape):
        shape = hg.normalize_shape(shape)
    elif str(type(shape)).find("EmbeddingGrid") != -1:
        shape = shape.shape()
    else:
        raise ValueError("Invalid shape type.")
    g = cls._make_instance(shape, neighbour_list)
    hg.CptGridGraph.link(g, shape)
    return g
Esempio n. 6
0
def get_8_adjacency_implicit_graph(shape):
    """
    Create an implicit undirected 8 adjacency graph of the given shape (edges are not stored).

    :param shape: a pair (height, width)
    :return: a graph (Concept :class:`~higra.CptGridGraph`)
    """
    shape = hg.normalize_shape(shape)
    graph = hg.cpp._get_8_adjacency_implicit_graph(shape)
    hg.CptGridGraph.link(graph, shape)
    hg.set_attribute(graph, "no_border_vertex_out_degree", 8)

    return graph
Esempio n. 7
0
def graph_4_adjacency_2_khalimsky(graph,
                                  edge_weights,
                                  shape,
                                  add_extra_border=False):
    """
    Create a contour image in the Khalimsky grid from a 4 adjacency edge-weighted graph.

    :param graph: must be a 4 adjacency 2d graph (Concept :class:`~higra.CptGridGraph`)
    :param edge_weights: edge weights of the graph
    :param shape: shape of the graph (deduced from :class:`~higra.CptGridGraph`)
    :param add_extra_border: if False result size is 2 * shape - 1 and 2 * shape + 1 otherwise
    :return: a 2d array
    """
    shape = hg.normalize_shape(shape)
    return hg.cpp._graph_4_adjacency_2_khalimsky(graph, shape, edge_weights,
                                                 add_extra_border)
Esempio n. 8
0
def khalimsky_2_graph_4_adjacency(khalimsky, extra_border=False):
    """
    Create a 4 adjacency edge-weighted graph from a contour image in the Khalimsky grid.

    :param khalimsky: a 2d array
    :param extra_border: if False the shape of the Khalimsky image  is 2 * shape - 1 and 2 * shape + 1 otherwise, where shape is the shape of the resulting grid graph
    :return: a graph (Concept :class:`~higra.CptGridGraph`) and its edge weights
    """

    graph, embedding, edge_weights = hg.cpp._khalimsky_2_graph_4_adjacency(
        khalimsky, extra_border)

    hg.CptGridGraph.link(graph, hg.normalize_shape(embedding.shape()))
    hg.set_attribute(graph, "no_border_vertex_out_degree", 4)

    return graph, edge_weights
Esempio n. 9
0
def get_4_adjacency_implicit_graph(shape):
    """
    Create an implicit undirected 4 adjacency graph of the given shape (edges are not stored).

    :param shape: a pair (height, width)
    :return: a graph (Concept :class:`~higra.CptGridGraph`)
    """
    shape = hg.normalize_shape(shape)
    if len(shape) != 2:
        raise ValueError("Shape must be a 1d array of size 2.")

    neighbours = np.array(((-1, 0), (0, -1), (0, 1), (1, 0)), dtype=np.int64)
    graph = hg.RegularGraph2d(shape, neighbours)

    hg.CptGridGraph.link(graph, shape)
    hg.set_attribute(graph, "no_border_vertex_out_degree", 4)

    return graph
Esempio n. 10
0
def multiscale_mean_pb_hierarchy(graph,
                                 fine_edge_weights,
                                 others_edge_weights,
                                 shape,
                                 edge_orientations=None):
    """
    Multiscale mean probability boundary hierarchy.

    The method is described in:

        J. Pont-Tuset, P. Arbeláez, J. Barron, F. Marques, and J. Malik
        Multiscale Combinatorial Grouping for Image Segmentation and Object Proposal Generation
        IEEE Transactions on Pattern Analysis and Machine Intelligence (TPAMI), vol. 39, no. 1, pp. 128 - 140, 2017.

    and in:

        K.K. Maninis, J. Pont-Tuset, P. Arbeláez and L. Van Gool
        Convolutional Oriented Boundaries: From Image Segmentation to High-Level Tasks
        IEEE Transactions on Pattern Analysis and Machine Intelligence (TPAMI), vol. 40, no. 4, pp. 819 - 833, 2018.

    This does not include gradient estimation.

    The returned hierarchy is defined on the gradient watershed super-pixels.

    The final sigmoid scaling of the hierarchy altitude is not performed.

    :param graph: must be a 4 adjacency graph (Concept :class:`~higra.CptGridGraph`)
    :param fine_edge_weights: edge weights of the finest gradient
    :param others_edge_weights: tuple of gradient value on edges
    :param shape: shape of the graph, i.e. a pair (height, width) (deduced from :class:`~higra.CptGridGraph`)
    :param edge_orientations: estimated orientation of the gradient on edges (optional)
    :return: a tree (Concept :class:`~higra.CptHierarchy`) and its node altitudes
    """
    shape = hg.normalize_shape(shape)
    tree_fine, altitudes_fine = hg.mean_pb_hierarchy(
        graph,
        fine_edge_weights,
        shape=shape,
        edge_orientations=edge_orientations)
    saliency_fine = hg.saliency(tree_fine, altitudes_fine)
    super_vertex_fine = hg.labelisation_hierarchy_supervertices(
        tree_fine, altitudes_fine)

    other_hierarchies = []
    for edge_weights in others_edge_weights:
        tree_coarse, altitudes_coarse = hg.mean_pb_hierarchy(
            graph,
            edge_weights,
            shape=shape,
            edge_orientations=edge_orientations)
        other_hierarchies.append((tree_coarse, altitudes_coarse))

    aligned_saliencies = hg.align_hierarchies(graph, super_vertex_fine,
                                              other_hierarchies)

    for saliency in aligned_saliencies:
        saliency_fine += saliency

    saliency_fine *= (1.0 / (1 + len(others_edge_weights)))

    return hg.mean_pb_hierarchy(graph, saliency_fine, shape=shape)