diff --git a/doc/examples/segmentation/plot_boundary_merge.py b/doc/examples/segmentation/plot_boundary_merge.py new file mode 100644 index 00000000..5c649195 --- /dev/null +++ b/doc/examples/segmentation/plot_boundary_merge.py @@ -0,0 +1,36 @@ +from skimage import data, io, segmentation, color +from skimage.future import graph +import numpy as np + + +def weight_boundary(graph, src, dst, n): + if graph.has_edge(src, n) and graph.has_edge(dst, n): + count_src = graph[src][n]['count'] + count_dst = graph[dst][n]['count'] + + weight_src = graph[src][n]['weight'] + weight_dst = graph[dst][n]['weight'] + + count = count_src + count_dst + return { + 'count': count, + 'weight': (count_src*weight_src + count_dst*weight_dst)/count + } + + elif graph.has_edge(src, n): + return graph[src][n] + elif graph.has_edge(dst, n): + return graph[dst][n] + + +def merge_boundary(graph, src, dst): + pass + +img = data.coffee() +labels = segmentation.slic(img, compactness=30, n_segments=400) +g = graph.rag_mean_color(img, labels) + +labels2 = graph.merge_hierarchical(labels, g, thresh=40, rag_copy=False, + in_place_merge=True, + merge_func=merge_boundary, + weight_func=weight_boundary) diff --git a/skimage/future/graph/rag.py b/skimage/future/graph/rag.py index 480ef4eb..d0d26d84 100644 --- a/skimage/future/graph/rag.py +++ b/skimage/future/graph/rag.py @@ -74,7 +74,7 @@ def min_weight(graph, src, dst, n): default = {'weight': np.inf} w1 = graph[n].get(src, default)['weight'] w2 = graph[n].get(dst, default)['weight'] - return min(w1, w2) + return {'weight': min(w1, w2)} def _add_edge_filter(values, graph): @@ -171,12 +171,12 @@ class RAG(nx.Graph): src, dst : int Nodes to be merged. weight_func : callable, optional - Function to decide edge weight of edges incident on the new node. - For each neighbor `n` for `src and `dst`, `weight_func` will be - called as follows: `weight_func(src, dst, n, *extra_arguments, + Function to decide the attributes of edges incident on the new + node. For each neighbor `n` for `src and `dst`, `weight_func` will + be called as follows: `weight_func(src, dst, n, *extra_arguments, **extra_keywords)`. `src`, `dst` and `n` are IDs of vertices in the - RAG object which is in turn a subclass of - `networkx.Graph`. + RAG object which is in turn a subclass of `networkx.Graph`. It is + expected to return a dict of attributes of the resulting edge. in_place : bool, optional If set to `True`, the merged node has the id `dst`, else merged node has a new id which is returned. @@ -207,9 +207,9 @@ class RAG(nx.Graph): self.add_node(new) for neighbor in neighbors: - w = weight_func(self, src, new, neighbor, *extra_arguments, - **extra_keywords) - self.add_edge(neighbor, new, weight=w) + data = weight_func(self, src, new, neighbor, *extra_arguments, + **extra_keywords) + self.add_edge(neighbor, new, attr_dict=data) self.node[new]['labels'] = (self.node[src]['labels'] + self.node[dst]['labels']) diff --git a/skimage/future/graph/tests/test_rag.py b/skimage/future/graph/tests/test_rag.py index 4b2e4cff..dadbe5ce 100644 --- a/skimage/future/graph/tests/test_rag.py +++ b/skimage/future/graph/tests/test_rag.py @@ -10,7 +10,7 @@ def max_edge(g, src, dst, n): default = {'weight': -np.inf} w1 = g[n].get(src, default)['weight'] w2 = g[n].get(dst, default)['weight'] - return max(w1, w2) + return {'weight': max(w1, w2)} @skipif(not is_installed('networkx')) @@ -113,7 +113,7 @@ def test_rag_error(): def _weight_mean_color(graph, src, dst, n): diff = graph.node[dst]['mean color'] - graph.node[n]['mean color'] diff = np.linalg.norm(diff) - return diff + return {'weight': diff} def _pre_merge_mean_color(graph, src, dst):