From e2d60f01357d9d18ee3c34be4b7953e7dd634168 Mon Sep 17 00:00:00 2001 From: Andreas Mueller Date: Sat, 16 Jun 2012 17:28:43 +0200 Subject: [PATCH] ENH using union find from morphology module --- skimage/morphology/ccomp.pxd | 10 +++++++ skimage/segmentation/felsenzwalb.pyx | 4 --- .../{felzenszwalb.py => felzenszwalb.pyx} | 20 +++++++------- skimage/segmentation/setup.py | 27 +++++++++++++++++++ skimage/setup.py | 1 + 5 files changed, 48 insertions(+), 14 deletions(-) create mode 100644 skimage/morphology/ccomp.pxd delete mode 100644 skimage/segmentation/felsenzwalb.pyx rename skimage/segmentation/{felzenszwalb.py => felzenszwalb.pyx} (82%) create mode 100644 skimage/segmentation/setup.py diff --git a/skimage/morphology/ccomp.pxd b/skimage/morphology/ccomp.pxd new file mode 100644 index 00000000..0b431832 --- /dev/null +++ b/skimage/morphology/ccomp.pxd @@ -0,0 +1,10 @@ +"""Export fast union find in Cython""" +cimport numpy as np + +DTYPE = np.int +ctypedef np.int_t DTYPE_t + +cdef DTYPE_t find_root(np.int_t *forest, np.int_t n) +cdef set_root(np.int_t *forest, np.int_t n, np.int_t root) +cdef join_trees(np.int_t *forest, np.int_t n, np.int_t m) +cdef link_bg(np.int_t *forest, np.int_t n, np.int_t *background_node) diff --git a/skimage/segmentation/felsenzwalb.pyx b/skimage/segmentation/felsenzwalb.pyx deleted file mode 100644 index 38a95411..00000000 --- a/skimage/segmentation/felsenzwalb.pyx +++ /dev/null @@ -1,4 +0,0 @@ -# Implements Felsenzwalb's efficient graph based image segmentation. -# Author: Andreas Mueller - -def felsenzwalb(np.ndarray[dtype= diff --git a/skimage/segmentation/felzenszwalb.py b/skimage/segmentation/felzenszwalb.pyx similarity index 82% rename from skimage/segmentation/felzenszwalb.py rename to skimage/segmentation/felzenszwalb.pyx index 9dea47a6..5a0ecbac 100644 --- a/skimage/segmentation/felzenszwalb.py +++ b/skimage/segmentation/felzenszwalb.pyx @@ -1,10 +1,11 @@ import numpy as np +cimport numpy as np from collections import defaultdict import scipy #from ..util import img_as_float #from ..color import rgb2grey -from .union_find import UnionFind +from skimage.morphology.ccomp cimport find_root, join_trees from IPython.core.debugger import Tracer tracer = Tracer() @@ -37,24 +38,23 @@ def felzenszwalb_segmentation(image, k, sigma=0.8): # initialize data structures for segment size # and inner cost, then start greedy iteration over edges. edge_queue = np.argsort(costs) - segments = UnionFind() + cdef np.ndarray[np.int_t, ndim=2] segments = indices.reshape(width, height) + cdef np.int_t *segments_p = segments.data + cdef np.int_t seg_new segment_size = defaultdict(lambda: 1) # inner cost of segments cint = defaultdict(lambda: 0) for edge, cost in zip(edges[edge_queue], costs[edge_queue]): - seg0 = segments[edge[0]] - seg1 = segments[edge[1]] + seg0 = find_root(segments_p, edge[0]) + seg1 = find_root(segments_p, edge[1]) if seg0 == seg1: continue inner_cost0 = cint[seg0] + k / segment_size[seg0] inner_cost1 = cint[seg1] + k / segment_size[seg1] if cost < min(inner_cost0, inner_cost1): - seg_new = segments.union(seg0, seg1) # update size and cost + join_trees(segments_p, seg0, seg1) + seg_new = find_root(segments_p, seg0) segment_size[seg_new] = segment_size[seg0] + segment_size[seg1] cint[seg_new] = cost - out = np.zeros(width * height, dtype=np.int) - for i in xrange(width * height): - out[i] = segments[i] - out = out.reshape(width, height) - return out + return segments diff --git a/skimage/segmentation/setup.py b/skimage/segmentation/setup.py new file mode 100644 index 00000000..8f6361bf --- /dev/null +++ b/skimage/segmentation/setup.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python + +import os +from skimage._build import cython + +base_path = os.path.abspath(os.path.dirname(__file__)) + +def configuration(parent_package='', top_path=None): + from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs + + config = Configuration('segmentation', parent_package, top_path) + + cython(['felzenszwalb.pyx'], working_path=base_path) + config.add_extension('felzenszwalb', sources=['felzenszwalb.c'], + include_dirs=[get_numpy_include_dirs()]) + + return config + +if __name__ == '__main__': + from numpy.distutils.core import setup + setup(maintainer = 'scikits-image Developers', + maintainer_email = 'scikits-image@googlegroups.com', + description = 'Segmentation Algorithms', + url = 'https://github.com/scikits-image/scikits-image', + license = 'SciPy License (BSD Style)', + **(configuration(top_path='').todict()) + ) diff --git a/skimage/setup.py b/skimage/setup.py index 0afc5bc9..02c0b52d 100644 --- a/skimage/setup.py +++ b/skimage/setup.py @@ -17,6 +17,7 @@ def configuration(parent_package='', top_path=None): config.add_subpackage('morphology') config.add_subpackage('transform') config.add_subpackage('util') + config.add_subpackage('segmentation') def add_test_directories(arg, dirname, fnames): if dirname.split(os.path.sep)[-1] == 'tests':