Beispiel #1
0
    def execute(self, slot, subindex, roi, result):
        assert slot is self.Superpixels, "Unknown or unconnected output slot: {}".format(
            slot)
        channel_index = self.ChannelSelection.value

        pmap_roi = roi.copy()
        pmap_roi.start[-1] = channel_index
        pmap_roi.stop[-1] = channel_index + 1

        # TODO: We could be sneaky and use the result array as a temporary here...
        pmap = self.Input(pmap_roi.start, pmap_roi.stop).wait()

        if self.debug_results:
            self.debug_results.clear()
        wsDtSegmentation(pmap[..., 0],
                         self.Pmin.value,
                         self.MinMembraneSize.value,
                         self.MinSegmentSize.value,
                         self.SigmaMinima.value,
                         self.SigmaWeights.value,
                         self.GroupSeeds.value,
                         self.PreserveMembranePmaps.value,
                         out_debug_image_dict=self.debug_results,
                         out=result[..., 0])

        self.watershed_completed()
    def test_out_param(self):
        pmap = self._gen_input_data(2)

        debug_results = {}
        preallocated = np.random.randint(0, 100, pmap.shape).astype(np.uint32)
        ws_output = wsDtSegmentation(pmap,
                                     0.5,
                                     0,
                                     10,
                                     0.1,
                                     0.1,
                                     groupSeeds=False,
                                     out_debug_image_dict=debug_results,
                                     out=preallocated)
        assert ws_output is preallocated
        seeds = debug_results['seeds'][:]
        assert seeds.max() == 4
        assert ws_output.max() == 4

        # Also with groupSeeds=True
        preallocated = np.random.randint(0, 100, pmap.shape).astype(np.uint32)
        ws_output = wsDtSegmentation(pmap,
                                     0.5,
                                     0,
                                     10,
                                     0.1,
                                     0.1,
                                     groupSeeds=True,
                                     out_debug_image_dict=debug_results,
                                     out=preallocated)
        assert ws_output is preallocated
        assert seeds.max() == 4
        assert ws_output.max() == 4
Beispiel #3
0
    def execute(self, slot, subindex, roi, result):
        assert slot is self.Superpixels, "Unknown or unconnected output slot: {}".format( slot )
        channel_index = self.ChannelSelection.value

        pmap_roi = roi.copy()
        pmap_roi.start[-1] = channel_index
        pmap_roi.stop[-1] = channel_index+1

        # TODO: We could be sneaky and use the result array as a temporary here...
        pmap = self.Input(pmap_roi.start, pmap_roi.stop).wait()

        if self.debug_results:
            self.debug_results.clear()
        wsDtSegmentation( pmap[...,0],
                          self.Pmin.value,
                          self.MinMembraneSize.value,
                          self.MinSegmentSize.value,
                          self.SigmaMinima.value,
                          self.SigmaWeights.value,
                          self.GroupSeeds.value,
                          self.PreserveMembranePmaps.value,
                          out_debug_image_dict=self.debug_results,
                          out=result[...,0] )
        
        self.watershed_completed()
    def test_simple_2D(self):
        pmap = self._gen_input_data(2)

        debug_results = {}
        ws_output = wsDtSegmentation(pmap,
                                     0.5,
                                     0,
                                     10,
                                     0.1,
                                     0.1,
                                     groupSeeds=False,
                                     out_debug_image_dict=debug_results)
        seeds = debug_results['seeds'][:]
        assert seeds.max() == 4
        assert ws_output.max() == 4

        # Expect seeds at (25,25,25), (25,25,75), (25,75,25), etc...
        expected_seed_coords = list(np.ndindex((2, 2)))
        expected_seed_coords = 50 * np.array(expected_seed_coords) + 25

        #print "EXPECTED:\n", expected_seed_coords
        #print "SEEDS:\n", np.array(np.where(seeds)).transpose()

        for seed_coord in expected_seed_coords:
            assert seeds[tuple(seed_coord)], "No seed at: {}".format(
                seed_coord)
Beispiel #5
0
def ws_distance_transform(pmap,
                          threshold,
                          sigma_seeds,
                          sigma_weights=0.,
                          min_membrane_size=0,
                          min_segment_size=0,
                          group_seeds=False,
                          preserve_membrane=True,
                          grow_on_pmap=True,
                          out_debug_dict=None):
    """
    Watershed on distance transform on 2d or 3d probabiity map.

    @params:
    pmap: probability map, 2d or 3d numpy.ndarray of type float32.
    threshold: threshold for pixels that are considered in distance transform.
    sigma_seeds: smoothing factor for distance transform used for finding seeds.
    sigma_weights: smoothing factor for heiht map used for the watershed (default 0.).
    min_membrane_size: size filter for connected membrane components after thresholding (default 0 -> no size filtering).
    min_segment_size: size filter for resulting segments (default 0 -> no size filtering).
    group_seeds: use heuristics to group adjacent seeds (default: False).
    preserve_membrane: preserve membrane seeds (default: False).
    grow_on_pmap: grow on the probability map instead of distance transform (default: True).
    out_debug_dict: dictionary to store debug images as chunked arrays (default: None).
    @returns:
    fragments: numpy.ndarray of type uint32
    n_labels:  number of labels
    """
    fragments, max_label = wsDtSegmentation(pmap, threshold, min_membrane_size,
                                            min_segment_size, sigma_seeds,
                                            sigma_weights, group_seeds,
                                            preserve_membrane, grow_on_pmap,
                                            out_debug_dict)
    return fragments - 1, max_label
Beispiel #6
0
    def execute(self, slot, subindex, roi, result):
        assert slot is self.Superpixels, \
            "Unknown or unconnected output slot: {}".format( slot )

        pmap = self._opSelectedInput.Output(roi.start, roi.stop).wait()

        if self.debug_results:
            self.debug_results.clear()
        wsDtSegmentation( pmap[...,0],
                          self.Pmin.value,
                          self.MinMembraneSize.value,
                          self.MinSegmentSize.value,
                          self.SigmaMinima.value,
                          self.SigmaWeights.value,
                          self.GroupSeeds.value,
                          self.PreserveMembranePmaps.value,
                          out_debug_image_dict=self.debug_results,
                          out=result[...,0] )
        
        self.watershed_completed()
    def test_group_seeds_ram_usage(self):
        """
        The original implementation of the groupSeeds option needed
        a lot of RAM, scaling with the number of seeds by N**2.
        The new implementation does the work in batches, so it
        doesn't need as much RAM.  
        
        Here we create a test image that will result in lots of seeds,
        and we'll verify that RAM usage stays under control.
        
        The test image looks roughly like this (seeds marked with 'x'):
        
        +-----------------------------------------------------+
        |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
        |                                                     |
        |                                                     |
        |       x  x  x  x  x  x  x  x  x  x  x  x  x  x      |
        |                                                     |
        |                                                     |
        +-----------------------------------------------------+
        """
        input_data = np.zeros((101, 20001), dtype=np.float32)

        # Add borders
        input_data[0] = 1
        input_data[-1] = 1
        input_data[:, 0] = 1
        input_data[:, -1] = 1

        # Add tick marks
        input_data[:10, ::10] = 1

        # Sanity check, try without groupSeeds, make sure we've got a lot of segments
        ws_output = wsDtSegmentation(input_data,
                                     0.5,
                                     0,
                                     0,
                                     0.0,
                                     0.0,
                                     groupSeeds=False)
        assert ws_output.max() > 1900

        # Now check RAM with groupSeeds=True
        ws_output = assert_mem_usage_factor(3.0)(wsDtSegmentation)(
            input_data, 0.5, 0, 0, 2.0, 0.0, groupSeeds=True)
        assert ws_output.max() == 1
def create_supervoxels_with_wsdt( boundary_volume,
                                  mask,
                                  boundary_channel=0,
                                  pmin=0.5,
                                  minMembraneSize=10000,
                                  minSegmentSize=300,
                                  sigmaMinima=3,
                                  sigmaWeights=1.6,
                                  groupSeeds=False,
                                  preserve_membrane_pmaps=False ):
    """
    Generate supervoxels using Timo's watershed of the distance-transform method.
    """
    logger = logging.getLogger(__name__)
    logger.info('status=wsdt supervoxels')
    assert boundary_volume.ndim == 4, "Expected a 4D volume."
    boundary_volume = boundary_volume[..., boundary_channel]

    if mask is not None:
        # Forbid the watershed from bleeding into the masked area prematurely
        mask = mask.astype(np.bool, copy=False)
        # Mask is now inverted
        inverted_mask = np.logical_not(mask, out=mask)
        boundary_volume[inverted_mask] = 2.0

    watershed = wsdt.wsDtSegmentation( boundary_volume,
                                       pmin,
                                       minMembraneSize,
                                       minSegmentSize,
                                       sigmaMinima,
                                       sigmaWeights,
                                       groupSeeds,
                                       preserve_membrane_pmaps)

    if mask is not None:
        watershed[inverted_mask] = 0

    #logger.warn("FIXME: Saving watershed to temporary file for debugging purposes...")
    #tmpdir = tempfile.mkdtemp(prefix="wsdt_output_")
    #watershed_path = os.path.join(tmpdir, 'watershed.h5')
    #with h5py.File(watershed_path, 'w') as watershed_file:
    #    watershed_file.create_dataset('watershed', data=watershed)
    
    logger.info('status=wsdt supervoxels finished')
    return watershed
def wsdt(prob_map):

    # off the shelve settings
    threshold  = 0.3
    minMemSize = 50
    minSegSize = 75
    sigMinima  = 2.0
    sigWeights = 2.6
    groupSeeds = False

    segmentation, _ = wsDtSegmentation(prob_map, threshold,
            minMemSize, minSegSize,
            sigMinima, sigWeights, groupSeeds)

    if not 0 in segmentation:
        segmentation -= 1

    return segmentation
def superpixels(pmaps, outfile=None):
    import wsdt
    from wsdt import wsDtSegmentation
    # 2d distance transform superpixel for the probability maps
    #pmap_path = "/path/to/neurocut_examples/probability_map.h5"
    #pmap_key  = "data"
    #pmaps = vigra.readHDF5(pmap_path, pmap_key)

    # parameters for the watershed on distance trafo

    # threshold for computing the distance trafo
    threshold = 0.5
    # minimal size of connected components that are taken into account
    # for the distance trafo
    min_mem = 50
    # minimal size of segments in the result
    min_seg = 75
    # sigma for smoothing the seed map
    sig_seeds = 1.6
    # sigma for smoothing the weight map
    sig_weights = 2.0

    segmentation = numpy.zeros_like(pmaps, dtype = numpy.uint32)
    # we need an offset for each slice, because we need distinct ids in each slice
    offset = 0
    # iterate over the z-slices and perform the wsdt in each
    #for z in xrange(segmentation.shape[2]):
    segmentation[:,:] = wsDtSegmentation(
        pmaps[:,:], threshold,
        min_mem, min_seg,
        sig_seeds, sig_weights)
    # add the offset
    #segmentation[:,:] += offset
    # get the new offset
    #offset = numpy.max(segmentation)

    # save the result
    if outfile is not None:
        save_key  = "superpixel"

        vigra.writeHDF5(segmentation, outfile, save_key)

    return segmentation
def create_supervoxels_with_wsdt( boundary_volume,
                                  mask,
                                  boundary_channel=0,
                                  pmin=0.5,
                                  minMembraneSize=10000,
                                  minSegmentSize=300,
                                  sigmaMinima=3,
                                  sigmaWeights=1.6,
                                  cleanCloseSeeds=False ):
    """
    Generate supervoxels using Timo's watershed of the distance-transform method.
    """
    assert boundary_volume.ndim == 4, "Expected a 4D volume."
    boundary_volume = boundary_volume[..., boundary_channel]

    if mask is not None:
        # Forbid the watershed from bleeding into the masked area prematurely
        mask = mask.astype(np.bool, copy=False)
        # Mask is now inverted
        inverted_mask = np.logical_not(mask, out=mask)
        boundary_volume[inverted_mask] = 2.0

    watershed = wsdt.wsDtSegmentation( boundary_volume,
                                       pmin,
                                       minMembraneSize,
                                       minSegmentSize,
                                       sigmaMinima,
                                       sigmaWeights,
                                       cleanCloseSeeds=False,
                                       returnSeedsOnly=False )

    if mask is not None:
        watershed[inverted_mask] = 0

    #logger.warn("FIXME: Saving watershed to temporary file for debugging purposes...")
    #tmpdir = tempfile.mkdtemp(prefix="wsdt_output_")
    #watershed_path = os.path.join(tmpdir, 'watershed.h5')
    #with h5py.File(watershed_path, 'w') as watershed_file:
    #    watershed_file.create_dataset('watershed', data=watershed)
    
    return watershed
Beispiel #12
0
    def execute(self, slot, subindex, roi, result):
        assert slot is self.Superpixels, \
            "Unknown or unconnected output slot: {}".format( slot )

        pmap = self._opSelectedInput.Output(roi.start, roi.stop).wait()

        if self.debug_results:
            self.debug_results.clear()
        ws, max_label = wsDtSegmentation(
            pmap[..., 0],
            self.Pmin.value,
            self.MinMembraneSize.value,
            self.MinSegmentSize.value,
            self.SigmaMinima.value,
            self.SigmaWeights.value,
            self.GroupSeeds.value,
            self.PreserveMembranePmaps.value,
            out_debug_image_dict=self.debug_results,
            out=result[..., 0])

        self.watershed_completed()
def watersheds(prob_map):

    threshold = 0.25
    # off the shelve settings
    minMemSize = 15
    minSegSize = 30
    sigMinima  = 2.0
    sigWeights = 2.6
    groupSeeds = True

    segmentation = np.zeros_like(prob_map, dtype = np.uint32)
    offset = 0
    for z in xrange(prob_map.shape[2]):

        wsdt, _ = wsDtSegmentation(prob_map[:,:,z], threshold,
            minMemSize, minSegSize,
            sigMinima, sigWeights, groupSeeds)
        segmentation[:,:,z] = wsdt
        segmentation[:,:,z] += offset
        offset = np.max(segmentation)

    return segmentation
    def test_debug_output(self):
        """
        Just exercise the API for debug images, even though we're not
        really checking the *contents* of the images in this test.
        """
        pmap = self._gen_input_data(3)
        debug_images = {}
        ws_output = wsDtSegmentation(pmap,
                                     0.5,
                                     0,
                                     10,
                                     0.1,
                                     0.1,
                                     groupSeeds=False,
                                     out_debug_image_dict=debug_images)
        assert ws_output.max() == 8

        assert 'thresholded membranes' in debug_images
        assert debug_images['thresholded membranes'].shape == ws_output.shape

        assert 'filtered membranes' in debug_images
        assert debug_images['filtered membranes'].shape == ws_output.shape
    def test_border_seeds(self):
        """
        check if seeds at the borders are generated
        """

        # create a volume with membrane evidence everywhere
        pmap = np.ones((50, 50, 50))

        # create funnel without membrane evidence growing larger towards the block border.
        pmap[0, 12:39, 12:39] = 0
        pmap[1:50, 13:38, 13:38] = 0

        debug_results = {}
        _ws_output = wsDtSegmentation(pmap,
                                      0.5,
                                      0,
                                      10,
                                      0.1,
                                      0.1,
                                      groupSeeds=False,
                                      out_debug_image_dict=debug_results)
        seeds = debug_results['seeds'][:]
        assert seeds.sum() == 1
        assert seeds[0, 25, 25] == 1
def wsdt(prob_map):

    threshold = 0.3
    minMemSize = 1
    minSegSize = 1
    sigMinima = 2.0
    sigWeights = 2.6
    groupSeeds = False

    segmentation = np.zeros_like(prob_map, dtype=np.uint32)
    offset = 0
    for z in xrange(prob_map.shape[2]):
        wsdt, _ = wsDtSegmentation(prob_map[:, :, z], threshold, minMemSize,
                                   minSegSize, sigMinima, sigWeights,
                                   groupSeeds)

        if not 0 in wsdt:
            wsdt -= 1

        segmentation[:, :, z] = wsdt
        segmentation[:, :, z] += offset
        offset = np.max(segmentation) + 1

    return segmentation
Beispiel #17
0
def make_ws(inp, thresh, sig_min):
    return wsDtSegmentation(inp, thresh, 25, 50, sig_min, 0., True)
    def test_group_close_seeds(self):
        """
        In this test we'll use input data that looks roughly like the following:
        
            0                101               202               303
          0 +-----------------+-----------------+-----------------+
            |        |        |        |        |                 |
            |                 |                 |                 |
            |                 |                 |                 |
            |                                   |                 |
         50 |      x   x             y   y      |        z        |
            |                                   |                 |
            |                 |                 |                 |
            |                 |                 |                 |
            |        |        |        |        |                 |
        101 +-----------------+-----------------+-----------------+

        The x and y markers indicate where seeds will end up.
        
        With groupSeeds=False, we get 5 seed points and 5 final segments.
        But with groupSeeds=True, the two x points end up in the same segment,
        and the two y points end up in the same segment.
        The lone z point will not be merged with anything.
        """

        input_data = np.zeros((101, 303), dtype=np.float32)

        # Add borders
        input_data[0] = 1
        input_data[-1] = 1
        input_data[:, 0] = 1
        input_data[:, -1] = 1

        # Add complete divider for the z compartment
        input_data[:, 202] = 1

        # Add notches extending from the upper/lower borders
        input_data[1:10, 51] = 1
        input_data[1:40, 101] = 1
        input_data[1:10, 151] = 1
        input_data[-10:-1, 51] = 1
        input_data[-40:-1, 101] = 1
        input_data[-10:-1, 151] = 1

        # First, try without groupSeeds
        debug_results = {}
        ws_output = wsDtSegmentation(input_data,
                                     0.5,
                                     0,
                                     0,
                                     0.0,
                                     0.0,
                                     groupSeeds=False,
                                     out_debug_image_dict=debug_results)
        assert ws_output.max() == 5

        # Now, with groupSeeds=True, the left-hand seeds should
        # be merged and the right-hand seeds should be merged
        debug_results = {}
        ws_output = wsDtSegmentation(input_data,
                                     0.5,
                                     0,
                                     0,
                                     0.0,
                                     0.0,
                                     groupSeeds=True,
                                     out_debug_image_dict=debug_results)
        assert ws_output.max() == 3

        assert (ws_output[:, 0:90] == ws_output[51, 51]).all()
        assert (ws_output[:, 110:190] == ws_output[51, 151]).all()
        assert (ws_output[:, 210:290] == ws_output[51, 251]).all()

        # The segment values are different
        assert ws_output[51, 51] != ws_output[51, 151] != ws_output[51, 251]