Python Packages for Graph Cuts on Images

Posted on Út 23 července 2013 in misc

A graph for a small image of 512x512 pixels has 261144 nodes and 523264 edges in the 4-connected pixels case. Graphs in this scale require a fast construction interface. I reviewed a few python packages mainly from this perspective. The comparison is by no means exhaustive and fair!

Based on Kolmogorov min-cut / max-flow C++ library

PyMaxflow

pymaxflow

  • https://github.com/Rhoana/pymaxflow
  • Cython based python interface
  • supports batch addition of edges from numpy arrays
    • edges are added one by one on the cython part of the interface, but it seems to be fast enough
  • shortcomings:
    • not documented (but the package is so simple that it is not a big deal)
    • no algorithms for multi-label segmentation

Example of batch node and edge addition:

im = ...
g = pymaxflow.PyGraph()   
g.add_node(im.size)

# linear indices of pixels arranged in image like matrix
indices = np.arange(im.shape[0]*im.shape[1]).reshape(im.shape[0:2]).astype(np.int32)
# compute differences between neighbouring pixels
diffs = np.abs(im[:, 1:] - im[:, :-1]).ravel() + eps
# indices of the neighbouring pixels
e1 = indices[:, :-1].ravel()
e2 = indices[:, 1:].ravel()
g.add_edge_vectorized(e1, e2, diffs, diffs)

API:

class PyGraph:
    __cinit__(self, int node_num_max, int edge_num_max)
    add_node(self, int num=1)
    add_edge(self, int i, int j, float cap, float rev_cap)
    add_tweights(self, int i, float cap_source, float cap_sink)
    maxflow(self)
    what_segment(self, int i)
    add_edge_vectorized(self,
                        np.ndarray[dtype=np.int32_t, ndim=1, negative_indices=False] i,
                        np.ndarray[dtype=np.int32_t, ndim=1, negative_indices=False] j,
                        np.ndarray[dtype=np.float32_t, ndim=1, negative_indices=False] cap,
                        np.ndarray[dtype=np.float32_t, ndim=1, negative_indices=False] rev_cap)
    add_tweights_vectorized(self,
                            np.ndarray[dtype=np.int32_t, ndim=1, negative_indices=False] i,
                            np.ndarray[dtype=np.float32_t, ndim=1, negative_indices=False] cap_source,
                            np.ndarray[dtype=np.float32_t, ndim=1, negative_indices=False] cap_sink)
    what_segment_vectorized(self)

pygco

pygraphcut

  • http://tfinley.net/software/pygraphcut/
  • Python C API based interface
  • shortcomings:
    • not actively developed
    • no public repository
    • no batch addition of nodes and edges
    • Python C API is hard to maintain
  • I have not tested this package.

Packages Based on Other Max-flow Implementations

graph-tool library

  • http://projects.skewed.de/graph-tool/
  • perfectly documented and feature rich general graph algorithms package
  • based on Boost Graph library
  • GPL license
  • various max-flow algorithms including Kolmogorov’s
  • shortcomings:
    • no batch addition of nodes and edges - this shortcoming should be fixed now, see comment (22.10.2014)

One by one addition of nodes and edges implemented in Python is extremely slow for graphs in a scale suitable for images. In my experience ~100x slower than the pymaxflow package due to the graph construction.

MedPy

Conclusions

I picked the pymaxflow package for my purposes. It’s just simple but quick wrapper for the Kolmogorov min-cut / max-flow C++ library. The wrapper fairly minimalistic and is written in Cython that makes the bindings easy to understand and modify.