Changed prototype of weight_func

This commit is contained in:
Vighnesh Birodkar
2014-06-26 00:11:49 +05:30
parent bd9ab8f0fd
commit b1f59fceee
4 changed files with 65 additions and 62 deletions
+1 -3
View File
@@ -9,9 +9,7 @@ difference in mean color. We then join regions with similar mean color.
"""
from skimage import graph
from skimage import segmentation
from skimage import data, io
from skimage import graph, data, io, segmentation, color
from matplotlib import pyplot as plt
from skimage import color
+5 -5
View File
@@ -5,13 +5,13 @@ import numpy as np
def threshold_cut(labels, rag, thresh):
"""Combine regions seperated by weight less than threshold.
Given an image's labels and its RAG, outputs new labels by
Given an image's labels and its RAG, output new labels by
combining regions whose nodes are seperated by a weight less
than the given threshold.
Parameters
----------
labels : (width, height) or (width, height, 3) ndarray
labels : ndarray
The array of labels.
rag : RAG
The region adjacency graph.
@@ -21,12 +21,12 @@ def threshold_cut(labels, rag, thresh):
Returns
-------
out : (width, height, 3) or (width, height, depth, 3) ndarray
out : ndarray
The new labelled array.
Examples
--------
>>> from skimage import data,graph,segmentation
>>> from skimage import data, graph, segmentation
>>> img = data.lena()
>>> labels = segmentation.slic(img)
>>> rag = graph.rag_meancolor(img, labels)
@@ -46,7 +46,7 @@ def threshold_cut(labels, rag, thresh):
comps = nx.connected_components(rag)
map_array = np.arange(labels.max() + 1, dtype=np.int)
map_array = np.arange(labels.max() + 1, dtype=labels.dtype)
for i, nodes in enumerate(comps):
for node in nodes:
for label in rag.node[node]['labels']:
+46 -49
View File
@@ -7,56 +7,50 @@ from scipy import ndimage as nd
class RAG(nx.Graph):
"""
The class for holding the Region Adjacency Graph (RAG).
Each region is a contiguous set of pixels in an image, usually
sharing some common property. Adjacent regions have an edge
between their corresponding nodes.
The Region Adjacency Graph (RAG) of an image.
"""
def merge_nodes(self, i, j, function=None, extra_arguments=[],
def merge_nodes(self, src, dst, weight_func=None, extra_arguments=[],
extra_keywords={}):
"""Merge node `i` into `j`.
"""Merge two nodes.
The new combined node is adjacent to all the neighbors of `i`
and `j`. In case of conflicting edges the given function is
The new combined node is adjacent to all the neighbors of `src`
and `dst`. In case of conflicting edges the given function is
called.
Parameters
----------
i, j : int
Nodes to be merged. The resulting node will have ID `j`.
function : callable, optional
Function to decide which edge weight to keep when a node is
adjacent to both `i` and `j`. The arguments passed to the
function are, the tuples represnting both the conflicting edges
and the graph.The default behaviour is that the edge with higher
weight is kept.
weight_func : callable, optional
Function to decide edge weight between existing nodes and the new
node.The arguments passed to the function are, the graph, `src`,
`dst` and the existing node whose edge weight need to be updated.
extra_arguments : sequence, optional
The sequence of extra positional arguments passed to
`function`
`weight_func`
extra_keywords :
The dict of keyword arguments passed to the `function`.
The dict of keyword arguments passed to the `weight_func`.
"""
for x in self.neighbors(i):
if x == j:
for neighbor in self.neighbors(src):
if neighbor == dst:
continue
w1 = self.get_edge_data(x, i)['weight']
w2 = -1
if self.has_edge(x, j):
w2 = self.get_edge_data(x, j)['weight']
w = w1
if w2 > 0:
if not function:
w = max(w1, w2)
w1 = self.get_edge_data(neighbor, src)['weight']
w2 = None
if self.has_edge(neighbor, dst):
w2 = self.get_edge_data(neighbor, dst)['weight']
if not weight_func:
if w2 is None:
w = w1
else:
w = function((i, x), (j, x), self,
*extra_arguments, **extra_keywords)
self.add_edge(x, j, weight=w)
w = min(w1, w2)
else:
w = weight_func(self, src, dst, neighbor,
*extra_arguments, **extra_keywords)
self.add_edge(neighbor, dst, weight=w)
self.node[j]['labels'] += self.node[i]['labels']
self.remove_node(i)
self.node[dst]['labels'] += self.node[src]['labels']
self.remove_node(src)
def _add_edge_filter(values, g):
@@ -86,24 +80,27 @@ def _add_edge_filter(values, g):
def rag_meancolor(image, labels, connectivity=2):
"""Compute the Region Adjacency Graph of a color image using
difference in mean color of regions as edge weights.
"""Compute the Region Adjacency Graph using mean colors.
Given an image and its segmentation, this method constructs the
corresponsing Region Adjacency Graph (RAG). Each node in the RAG
represents a contiguous pixels with in `img` the same label in
`arr`.
`arr`. The weight between two adjacent regions is the difference
int their mean color.
Parameters
----------
image : ndarray
Input image.
labels : ndarray
The array with labels. This should have one dimention lesser than
`image`
The array with labels. This should have one dimention less than
`image`. If `image` has dimensions `(M,N,3)` `labels` should have
dimensions `(M, N)`.
connectivity : float, optional
Pixels with a squared distance less than `connectivity`from each other
are considered adjacent.
Pixels with a squared distance less than `connectivity` from each other
are considered adjacent. It can range from 1 to `labels.ndim`. It's
behaviour is the same as `connectivity` parameter in
`scipy.ndimage.filters.generate_binary_structure`.
Returns
-------
@@ -126,28 +123,28 @@ def rag_meancolor(image, labels, connectivity=2):
"""
g = RAG()
# The footprint is constructed in such a way that the first
# element in the array being passed to _add_edge_filter is
# the central value.
fp = nd.generate_binary_structure(labels.ndim, connectivity)
for d in range(fp.ndim):
fp = fp.swapaxes(0, d)
fp[0, ...] = 0
fp = fp.swapaxes(0, d)
# The footprint is constructed in such a way that the first
# element in the array being passed to _add_edge_filter is
# the central value.
for i in range(labels.max() + 1):
g.add_node(
i, {'labels': [i], 'pixel count': 0, 'total color':
np.array([0, 0, 0], dtype=np.double)})
filters.generic_filter(
labels,
function=_add_edge_filter,
footprint=fp,
mode='nearest',
output=np.zeros(labels.shape, dtype=np.uint8),
extra_arguments=(g,))
for n in g:
g.node[n].update({'labels': [n],
'pixel count': 0,
'total color': np.array([0, 0, 0], dtype=np.double)})
for index in np.ndindex(labels.shape):
current = labels[index]
g.node[current]['pixel count'] += 1
+13 -5
View File
@@ -3,10 +3,18 @@ from skimage import graph
import random
def _min_edge(e1, e2, g):
w1 = g.edge[e1[0]][e1[1]]['weight']
w2 = g.edge[e2[0]][e2[1]]['weight']
return min(w1, w2)
def _max_edge(g, src, dst, neighbor):
try:
w1 = g.edge[src][neighbor]['weight']
except KeyError:
w1 = None
try:
w2 = g.edge[dst][neighbor]['weight']
except KeyError:
w2 = None
return max(w1, w2)
def test_rag_merge():
@@ -27,7 +35,7 @@ def test_rag_merge():
y = random.choice(g.nodes())
while x == y:
y = random.choice(g.nodes())
g.merge_nodes(x, y, _min_edge)
g.merge_nodes(x, y, _max_edge)
idx = g.nodes()[0]
assert sorted(g.node[idx]['labels']) == list(range(10))