# 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 < 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  # 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__)