From b3f6b545cb649abc38ae1743e616d98d3732e627 Mon Sep 17 00:00:00 2001 From: Vighnesh Birodkar Date: Wed, 27 Apr 2016 01:03:09 -0400 Subject: [PATCH] Added example for region boundary merging --- .../segmentation/plot_boundary_merge.py | 78 ++++++++++++++----- doc/examples/segmentation/plot_rag.py | 19 ++--- doc/examples/segmentation/plot_rag_merge.py | 9 ++- skimage/future/graph/rag.py | 12 +-- 4 files changed, 82 insertions(+), 36 deletions(-) diff --git a/doc/examples/segmentation/plot_boundary_merge.py b/doc/examples/segmentation/plot_boundary_merge.py index 5c649195..ed38f679 100644 --- a/doc/examples/segmentation/plot_boundary_merge.py +++ b/doc/examples/segmentation/plot_boundary_merge.py @@ -1,36 +1,78 @@ -from skimage import data, io, segmentation, color +""" +============================================ +Hierarchical Merging of Region Boundary RAGs +============================================ + +TODO: Description +""" + +from skimage import data, segmentation, filters, color from skimage.future import graph -import numpy as np +from matplotlib import pyplot as plt 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'] + """ + Callback to handle merging of nodes of a region boundary RAG. - weight_src = graph[src][n]['weight'] - weight_dst = graph[dst][n]['weight'] + This function computes the `"weight"` and the count `"count"` + attributes of the edge between `n` and the node formed after + merging `src` and `dst`. - 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] + Parameters + ---------- + graph : RAG + The graph under consideration. + src, dst : int + The vertices in `graph` to be merged. + n : int + A neighbor of `src` or `dst` or both. + + Returns + ------- + data : dict + A dictionary with the `"weight"` and `"count"` attributes to be + assigned for the merged node. + + """ + default = {'weight': 0.0, 'count': 0} + + count_src = graph[src].get(n, default)['count'] + count_dst = graph[dst].get(n, default)['count'] + + weight_src = graph[src].get(n, default)['weight'] + weight_dst = graph[dst].get(n, default)['weight'] + + count = count_src + count_dst + return { + 'count': count, + 'weight': (count_src*weight_src + count_dst*weight_dst)/count + } def merge_boundary(graph, src, dst): pass img = data.coffee() +edges = filters.sobel(color.rgb2gray(img)) labels = segmentation.slic(img, compactness=30, n_segments=400) -g = graph.rag_mean_color(img, labels) +g = graph.rag_boundary(labels, edges) -labels2 = graph.merge_hierarchical(labels, g, thresh=40, rag_copy=False, +graph.show_rag(labels, g, img) +plt.title('Initial RAG') + +labels2 = graph.merge_hierarchical(labels, g, thresh=0.08, rag_copy=False, in_place_merge=True, merge_func=merge_boundary, weight_func=weight_boundary) + +graph.show_rag(labels, g, img) +plt.title('RAG after hierarchical merging') + +plt.figure() +out = color.label2rgb(labels2, img, kind='avg') +plt.imshow(out) +plt.title('Final segmentation') + +plt.show() diff --git a/doc/examples/segmentation/plot_rag.py b/doc/examples/segmentation/plot_rag.py index d4f2711c..45d2afc5 100644 --- a/doc/examples/segmentation/plot_rag.py +++ b/doc/examples/segmentation/plot_rag.py @@ -23,29 +23,30 @@ import numpy as np def max_edge(g, src, dst, n): """Callback to handle merging nodes by choosing maximum weight. - Returns either the weight between (`src`, `n`) or (`dst`, `n`) - in `g` or the maximum of the two when both exist. + Returns a dictionary with `"weight"` set as either the weight between + (`src`, `n`) or (`dst`, `n`) in `graph` or the maximum of the two when + both exist. Parameters ---------- - g : RAG + graph : RAG The graph under consideration. src, dst : int - The vertices in `g` to be merged. + The verices in `graph` to be merged. n : int A neighbor of `src` or `dst` or both. Returns ------- - weight : float - The weight between (`src`, `n`) or (`dst`, `n`) in `g` or the - maximum of the two when both exist. - + data : dict + A dict with the `"weight"` attribute set the weight between + (`src`, `n`) or (`dst`, `n`) in `graph` or the maximum of the two when + both exist. """ w1 = g[n].get(src, {'weight': -np.inf})['weight'] w2 = g[n].get(dst, {'weight': -np.inf})['weight'] - return max(w1, w2) + return {'weight': max(w1, w2)} def display(g, title): diff --git a/doc/examples/segmentation/plot_rag_merge.py b/doc/examples/segmentation/plot_rag_merge.py index 37712d5b..1ff68079 100644 --- a/doc/examples/segmentation/plot_rag_merge.py +++ b/doc/examples/segmentation/plot_rag_merge.py @@ -31,13 +31,14 @@ def _weight_mean_color(graph, src, dst, n): Returns ------- - weight : float - The absolute difference of the mean color between node `dst` and `n`. + data : dict + A dictionary with the `"weight"` attribute set as the absolute + difference of the mean color between node `dst` and `n`. """ diff = graph.node[dst]['mean color'] - graph.node[n]['mean color'] diff = np.linalg.norm(diff) - return diff + return {'weight': diff} def merge_mean_color(graph, src, dst): @@ -62,7 +63,7 @@ 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, +labels2 = graph.merge_hierarchical(labels, g, thresh=35, rag_copy=False, in_place_merge=True, merge_func=merge_mean_color, weight_func=_weight_mean_color) diff --git a/skimage/future/graph/rag.py b/skimage/future/graph/rag.py index d0d26d84..b6ded5fe 100644 --- a/skimage/future/graph/rag.py +++ b/skimage/future/graph/rag.py @@ -50,8 +50,9 @@ def _edge_generator_from_csr(csr_matrix): def min_weight(graph, src, dst, n): """Callback to handle merging nodes by choosing minimum weight. - Returns either the weight between (`src`, `n`) or (`dst`, `n`) - in `graph` or the minimum of the two when both exist. + Returns a dictionary with `"weight"` set as either the weight between + (`src`, `n`) or (`dst`, `n`) in `graph` or the minimum of the two when + both exist. Parameters ---------- @@ -64,9 +65,10 @@ def min_weight(graph, src, dst, n): Returns ------- - weight : float - The weight between (`src`, `n`) or (`dst`, `n`) in `graph` or the - minimum of the two when both exist. + data : dict + A dict with the `"weight"` attribute set the weight between + (`src`, `n`) or (`dst`, `n`) in `graph` or the minimum of the two when + both exist. """