예제 #1
0
def _make_seeds(dt, config):
    sigma_seeds = config.get('sigma_seeds', 2.)
    apply_nonmax_suppression = config.get('non_maximum_suppression', True)
    if apply_nonmax_suppression and nonMaximumDistanceSuppression is None:
        fu.log("non-maximum suppression was activated, but is not available")
        apply_nonmax_suppression = False

    # find local maxima of the distance transform
    max_fu = vigra.analysis.localMaxima if dt.ndim == 2 else vigra.analysis.localMaxima3D
    if sigma_seeds:
        seeds = max_fu(vu.apply_filter(dt, 'gaussianSmoothing', sigma_seeds),
                       marker=np.nan,
                       allowAtBorder=True,
                       allowPlateaus=True)
    else:
        seeds = max_fu(dt,
                       marker=np.nan,
                       allowAtBorder=True,
                       allowPlateaus=True)

    # check if we have just one plateau
    seeds = np.isnan(seeds)
    if np.sum(seeds) == seeds.size:
        return np.ones_like(seeds, dtype='uint32')

    # find seeds via connected components after max-suppression if enabled)
    if apply_nonmax_suppression:
        seeds = np.array(np.where(seeds)).transpose()
        seeds = nonMaximumDistanceSuppression(dt, seeds)
        seeds = _points_to_vol(seeds, dt.shape)
    else:
        seeds = vigra.analysis.labelMultiArrayWithBackground(
            seeds.view('uint8'))

    return seeds
예제 #2
0
def _threshold_block(block_id, blocking, ds_in, ds_out, threshold,
                     threshold_mode, channel, sigma):
    fu.log("start processing block %i" % block_id)
    block = blocking.getBlock(block_id)
    bb = vu.block_to_bb(block)

    bb = vu.block_to_bb(block)
    if channel is None:
        input_ = ds_in[bb]
    else:
        channel_ = [channel] if isinstance(channel, int) else channel
        in_shape = (len(channel_), ) + tuple(b.stop - b.start for b in bb)
        input_ = np.zeros(in_shape, dtype=ds_in.dtype)
        for chan_id, chan in enumerate(channel_):
            bb_inp = (slice(chan, chan + 1), ) + bb
            input_[chan_id] = ds_in[bb_inp].squeeze()
        input_ = np.mean(input_, axis=0)

    input_ = vu.normalize(input_)
    if sigma > 0:
        input_ = vu.apply_filter(input_, 'gaussianSmoothing', sigma)
        input_ = vu.normalize(input_)

    if threshold_mode == 'greater':
        input_ = input_ > threshold
    elif threshold_mode == 'less':
        input_ = input_ < threshold
    elif threshold_mode == 'equal':
        input_ = input_ == threshold
    else:
        raise RuntimeError("Thresholding Mode %s not supported" %
                           threshold_mode)

    ds_out[bb] = input_.astype('uint8')
    fu.log_block_success(block_id)
예제 #3
0
def _make_hmap(input_, distances, alpha, sigma_weights):
    distances = 1. - vu.normalize(distances)
    hmap = alpha * input_ + (1. - alpha) * distances
    # smooth input if sigma is given
    if sigma_weights != 0:
        hmap = vu.apply_filter(hmap, 'gaussianSmoothing', sigma_weights)
    return hmap
예제 #4
0
def _apply_watershed(input_, dt, offset, config, mask=None):
    apply_2d = config.get('apply_ws_2d', True)
    sigma_seeds = config.get('sigma_seeds', 2.)
    sigma_weights = config.get('sigma_weights', 2.)
    size_filter = config.get('size_filter', 25)
    alpha = config.get('alpha', 0.2)

    # apply the watersheds in 2d
    if apply_2d:
        ws = np.zeros_like(input_, dtype='uint64')
        for z in range(ws.shape[0]):
            # compute seeds for this slice
            dtz = vu.apply_filter(dt[z], 'gaussianSmoothing',
                                  sigma_seeds) if sigma_seeds != 0 else dt[z]
            seeds = vigra.analysis.localMaxima(dtz, marker=np.nan,
                                               allowAtBorder=True, allowPlateaus=True)
            seeds = vigra.analysis.labelImageWithBackground(np.isnan(seeds).view('uint8'))
            # run watershed for this slice
            hmap = _make_hmap(input_[z], dtz, alpha, sigma_weights)
            wsz, max_id = vu.watershed(hmap, seeds=seeds, size_filter=size_filter)
            # mask seeds if we have a mask
            if mask is None:
                wsz += offset
            else:
                wsz[mask[z]] = 0
                inv_mask = np.logical_not(mask[z])
                # NOTE we might have no pixels in the mask for this slice
                max_id = int(wsz[inv_mask].max()) if inv_mask.sum() > 0 else 0
                wsz[inv_mask] += offset
            ws[z] = wsz
            offset += max_id

    # apply the watersheds in 3d
    else:
        if sigma_seeds != 0:
            dt = vu.apply_filter(dt, 'gaussianSmoothing', sigma_seeds)
        seeds = vigra.analysis.localMaxima3D(dt, marker=np.nan,
                                             allowAtBorder=True, allowPlateaus=True)
        seeds = vigra.analysis.labelVolumeWithBackground(np.isnan(seeds).view('uint8'))
        hmap = _make_hmap(input_, dt, alpha, sigma_weights)
        ws, max_id = vu.watershed(hmap, seeds, size_filter=size_filter)
        ws += offset
        # check if we have a mask
        if mask is not None:
            ws[mask] = 0
    return ws
def _apply_filter(blocking, block_id, ds_in, ds_out,
                  halo, filter_name, sigma, apply_in_2d):
    fu.log("start processing block %i" % block_id)
    block = blocking.getBlockWithHalo(block_id, halo)
    bb_in = vu.block_to_bb(block.outerBlock)
    input_ = vu.normalize(ds_in[bb_in])
    response = vu.apply_filter(input_, filter_name, sigma, apply_in_2d)
    bb_out = vu.block_to_bb(block.innerBlock)
    inner_bb = vu.block_to_bb(block.innerBlockLocal)
    ds_out[bb_out] = response[inner_bb]
    fu.log_block_success(block_id)
예제 #6
0
def _cc_block_with_mask(block_id, blocking,
                        ds_in, ds_out, threshold,
                        threshold_mode, mask,
                        channel, sigma):
    fu.log("start processing block %i" % block_id)
    block = blocking.getBlock(block_id)
    bb = vu.block_to_bb(block)

    # get the mask and check if we have any pixels
    in_mask = mask[bb].astype('bool')
    if np.sum(in_mask) == 0:
        fu.log_block_success(block_id)
        return 0

    bb = vu.block_to_bb(block)
    if channel is None:
        input_ = ds_in[bb]
    else:
        channel_ = [channel] if isinstance(channel, int) else channel
        in_shape = (len(channel_),) + tuple(b.stop - b.start for b in bb)
        input_ = np.zeros(in_shape, dtype=ds_in.dtype)
        for chan_id, chan in enumerate(channel_):
            bb_inp = (slice(chan, chan + 1),) + bb
            input_[chan_id] = ds_in[bb_inp].squeeze()
        input_ = np.mean(input_, axis=0)

    input_ = vu.normalize(input_)
    if sigma > 0:
        input_ = vu.apply_filter(input_, 'gaussianSmoothing', sigma)
        input_ = vu.normalize(input_)

    if threshold_mode == 'greater':
        input_ = input_ > threshold
    elif threshold_mode == 'less':
        input_ = input_ < threshold
    elif threshold_mode == 'equal':
        input_ = input_ == threshold
    else:
        raise RuntimeError("Thresholding Mode %s not supported" % threshold_mode)

    input_[np.logical_not(in_mask)] = 0
    if np.sum(input_) == 0:
        fu.log_block_success(block_id)
        return 0

    components = label(input_)
    ds_out[bb] = components
    fu.log_block_success(block_id)
    return int(components.max()) + 1
예제 #7
0
def _accumulate_filter(input_, graph, labels, bb_local, filter_name, sigma,
                       ignore_label, with_size, apply_in_2d):
    response = vu.apply_filter(input_,
                               filter_name,
                               sigma,
                               apply_in_2d=apply_in_2d)[bb_local]
    if response.ndim == 4:
        n_chan = response.shape[-1]
        assert response.shape[:-1] == labels.shape
        return np.concatenate([
            ndist.accumulateInput(graph, response[..., c], labels,
                                  ignore_label, with_size and c == n_chan - 1,
                                  response[..., c].min(), response[...,
                                                                   c].max())
            for c in range(n_chan)
        ],
                              axis=1)
    else:
        assert response.shape == labels.shape
        return ndist.accumulateInput(graph, response, labels, ignore_label,
                                     with_size, response.min(), response.max())
예제 #8
0
def _apply_watershed_with_seeds(input_, dt, offset,
                                initial_seeds, config, mask=None):
    apply_2d = config.get('apply_ws_2d', True)
    sigma_seeds = config.get('sigma_seeds', 2.)
    size_filter = config.get('size_filter', 25)
    sigma_weights = config.get('sigma_weights', 2.)
    alpha = config.get('alpha', 0.2)

    # apply the watersheds in 2d
    if apply_2d:
        ws = np.zeros_like(input_, dtype='uint64')
        for z in range(ws.shape[0]):

            # smooth the distance transform if specified
            dtz = vu.apply_filter(dt[z], 'gaussianSmoothing',
                                  sigma_seeds) if sigma_seeds != 0 else dt[z]

            # get the initial seeds for this slice
            # and a mask for the inital seeds
            initial_seeds_z = initial_seeds[z]
            initial_seed_mask = initial_seeds_z != 0
            # don't place maxima at initial seeds
            dtz[initial_seed_mask] = 0

            seeds = vigra.analysis.localMaxima(dtz, marker=np.nan,
                                               allowAtBorder=True, allowPlateaus=True)
            seeds = vigra.analysis.labelImageWithBackground(np.isnan(seeds).view('uint8'))
            # remove seeds in mask
            if mask is not None:
                seeds[mask[z]] = 0

            # add offset to seeds
            seeds[seeds != 0] += offset
            # add initial seeds
            seeds[initial_seed_mask] = initial_seeds_z[initial_seed_mask]

            # we need to remap the seeds consecutively, because vigra
            # watersheds can only handle uint32 seeds, and we WILL overflow uint32
            seeds, _, old_to_new = vigra.analysis.relabelConsecutive(seeds,
                                                                     start_label=1,
                                                                     keep_zeros=True)
            new_to_old = {new: old for old, new in old_to_new.items()}

            # run watershed
            hmap = _make_hmap(input_[z], dtz, alpha, sigma_weights)
            wsz, max_id = vu.watershed(hmap, seeds=seeds, size_filter=size_filter,
                                       exclude=initial_seeds_z)
            # mask the result if we have a mask
            if mask is not None:
                wsz[mask[z]] = 0
                inv_mask = np.logical_not(mask[z])
                # NOTE we might not have any pixels in mask for 2d slice
                max_id = int(wsz[inv_mask].max()) if inv_mask.sum() > 0 else 0

            # increase the offset
            offset += max_id
            # map back to original ids
            wsz = nt.takeDict(new_to_old, wsz)
            ws[z] = wsz
        #
        return ws

    # apply the watersheds in 3d
    else:
        if sigma_seeds != 0:
            dt = vu.apply_filter(dt, 'gaussianSmoothing', sigma_seeds)

        # find seeds
        seeds = vigra.analysis.localMaxima3D(dt, marker=np.nan,
                                             allowAtBorder=True, allowPlateaus=True)
        seeds = vigra.analysis.labelVolumeWithBackground(np.isnan(seeds).view('uint8'))
        # remove seeds in mask
        if mask is not None:
            seeds[mask] = 0
        seeds[seeds != 0] += offset

        # add the initial seeds
        initial_seed_mask = initial_seeds != 0
        seeds[initial_seed_mask] = initial_seeds[initial_seed_mask]

        # we need to remap the seeds consecutively, because vigra
        # watersheds can only handle uint32 seeds, and we WILL overflow uint32
        seeds, _, old_to_new = vigra.analysis.relabelConsecutive(seeds,
                                                                 start_label=1,
                                                                 keep_zeros=True)
        new_to_old = {new: old for old, new in old_to_new.items()}

        # run watershed
        initial_seed_ids = np.unique(initial_seeds[initial_seed_mask])
        hmap = _make_hmap(input_, dt, alpha, sigma_weights)
        ws, max_id = vu.watershed(hmap, seeds=seeds, size_filter=size_filter,
                                  exclude=initial_seed_ids)
        ws = nt.takeDict(new_to_old, ws)
        if mask is not None:
            ws[mask] = 0
        return ws