Active Mask - image segmentation I'm trying to implement an active mask code derived from Active mask segmentation for the cell-volume computation and golgi-body segmentation of hela cell images, Srinivasa et al 2008.

I have found a code that will allow me to do this, however, there is one section of the code that is giving me errors and I don't know why. Here is the section of the code:

def _converge(P, R, b, max_iters_converge=1000):
    Pm = numpy.empty(P.shape, numpy.float32)  # Pre-allocate: saves time
    argmax = numpy.zeros_like(P)
    maxval = numpy.zeros(P.shape, numpy.float32)
    for i in range(max_iters_converge):
        maxval *= 0
        maxval -= 1e8
        for m in range(int(P.max()) + 1):
            Pm[:, :] = (P == m)
            Pm = ndimage.gaussian_filter(Pm, b) + R[m]  
 # Pm=ndimage.convolve(Pm,numpy.ones((2*b+1,2*b+1)))+R[m]
            argmax[maxval &lt; Pm] = m
            maxval = maxval * (argmax != m) + (argmax == m) * Pm
        if (P == argmax).all(): break
        P = argmax.copy()
    mis = defaultdict(range(1, P.max() + 1).__iter__().__next__())
    mis[0] = 0  # set 0 to 0, because it is special
    for i in range(P.size):
        P.flat[i] = mis[P.flat[i]]
    return P


The area that is giving me the most problem is the:

mis = defaultdict(range(1, P.max() + 1).__iter__().__next__())


Originally the code was written for Python 2.4 but I made some changes so that it will work on Python 3.6, but I don't really understand what the defaultdict is used for.

Here is a link to the full original source file: active mask
The defaultdict in this case is meant to return the next increasing integer each time a new element is encountered in P.flat().  But to also return the same integer each time that same element is found again. You should have encountered the error:


  TypeError: first argument must be callable or None


defaultdict expects a callable. It will call the passed in function each time there is a lookup miss, and set the dict to that value. To fix that error you need to remove the () from the __next__() to leave:

mis = defaultdict(range(1, P.max() + 1).__iter__().__next__)


However this is overly complicated for what it is doing, and can be simplified a bit by recognizing that there is no reason to have the upper limit in the range, it is just an increasing integer which can be done with itertools.count() liike:

import itertools as it
mis = defaultdict(it.count(1).__next__)