def segment_glomeruli2d(input_file, tissue_mask_file, output_file, voxel_xy):
    kmask = io.imread(tissue_mask_file)
    if kmask.max() == 0:
        tifffile.imsave(output_file, kmask, compress=5)
        return

    # normalize image
    img = io.imread(input_file)
    img = ndimage.median_filter(img, 3)
    img = img * 255. / img.max()

    # remove all intensity variations larger than maximum radius of a glomerulus
    d = mahotas.disk(int(float(glomeruli_maxrad) / voxel_xy))
    img = img - mahotas.open(img.astype(np.uint8), d)
    img = img * 255. / img.max()
    ch = img[np.where(kmask > 0)]

    # segment glomeruli by otsu thresholding	only if this threshold is higher than the 75-th percentile in the kidney mask
    t = mahotas.otsu(img.astype(np.uint8))

    cells = None

    if t > np.percentile(ch, 75) * 1.5:
        cells = img > t
        cells[np.where(kmask == 0)] = 0
        cells = mahotas.open(
            cells, mahotas.disk(int(float(glomeruli_minrad) / 2. / voxel_xy)))
    else:
        cells = np.zeros_like(img)

    tifffile.imsave(output_file, img_as_ubyte(cells), compress=5)
Example #2
0
    def generate_correct(image, prob, segmentation):

        hist = Util.get_histogram(segmentation.astype(np.uint64))
        labels = range(1, len(hist))  # do not include zeros

        np.random.shuffle(labels)

        for l in labels:

            binary_mask = Util.threshold(segmentation, l)
            borders = mh.labeled.borders(binary_mask, Bc=mh.disk(2))
            labeled_borders = skimage.measure.label(borders)
            labeled_borders[borders == 0] = 0
            relabeled_borders, no_relabeled_borders = mh.labeled.relabel(
                labeled_borders.astype(np.uint16))

            for border in range(1, no_relabeled_borders + 1):

                isolated_border = Util.threshold(relabeled_borders, border)

                patches = Patch.analyze_border(image, prob, binary_mask,
                                               binary_mask.invert(),
                                               isolated_border)

                for s in patches:

                    yield s
                    yield Patch.fliplr(s)
                    yield Patch.flipud(s)
                    yield Patch.rotate(s, 90)
                    yield Patch.rotate(s, 180)
                    yield Patch.rotate(s, 270)
Example #3
0
    def extract(self):
        '''Extracts neighbour features.

        Returns
        -------
        pandas.DataFrame
            extracted feature values for each object in `label_image`
        '''
        # Create an empty dataset in case no objects were detected
        logger.info('extract neighbour features')
        features = list()

        for obj in self.object_ids:
            pad = max(self.neighbour_distance, self.touching_distance)
            object_image = self._get_bbox_containing_neighbours(obj, pad)

            # dilate the current object
            object_image_dilate = mh.dilate(object_image == obj,
                                            Bc=mh.disk(
                                                self.neighbour_distance))

            # mask the corresponding region of the label image
            object_image_mask = np.copy(object_image)
            object_image_mask[object_image_dilate == 0] = 0
            object_image_mask[object_image == obj] = 0
            neighbour_ids = np.unique(object_image_mask)
            unique_values = neighbour_ids[np.nonzero(neighbour_ids)].tolist()
            neighbour_count = len(unique_values)

            # save these unique values as a string
            if neighbour_count == 0:
                neighbour_string = '.'
            else:
                neighbour_string = '.'.join(str(x) for x in unique_values)

            # create an inverted image of the surrounding cells
            neighbours = np.zeros_like(object_image)
            for n in unique_values:
                neighbours += mh.dilate(object_image == n)

            # calculate the distance from each pixel of object to neighbours
            dist = ndi.morphology.distance_transform_edt(
                np.invert(neighbours > 0))

            # select perimeter pixels whose distance to neighbours is
            # less than threshold touching distance
            perimeter_image = mh.bwperim(object_image == obj)
            dist[perimeter_image == 0] = 0
            dist[dist > self.touching_distance] = 0

            fraction_touching = np.count_nonzero(dist) / float(
                np.count_nonzero(perimeter_image))

            values = [neighbour_count, neighbour_string, fraction_touching]
            features.append(values)
        return pd.DataFrame(features,
                            columns=self.names,
                            index=self.object_ids)
def segment_layer(filename, params):
	'''
	Segment one layer in a stack
	'''
	#extract pixel size in xy and z
	xsize, zsize = extract_zoom(params.folder)

	#load image
	img = tifffile.imread(params.inputfolder + params.folder + filename)

	#normalize image
	img = ndimage.median_filter(img, 3)
	per_low = np.percentile(img, 5)
	img[img < per_low] = per_low
	img = img - img.min()

	per_high = np.percentile(img, 99)
	img[img > per_high] = per_high
	img = img*255./img.max()


	imgf = ndimage.gaussian_filter(img*1., 30./xsize).astype(np.uint8)

	kmask = (imgf > mahotas.otsu(imgf.astype(np.uint8)))*255.

	sizefactor = 10
	small = ndimage.interpolation.zoom(kmask, 1./sizefactor)	#scale the image to a smaller size

	rad = int(300./xsize)

	small_ext = np.zeros([small.shape[0] + 4*rad, small.shape[1] + 4*rad])
	small_ext[2*rad : 2*rad + small.shape[0], 2*rad : 2*rad + small.shape[1]] = small

	small_ext = mahotas.close(small_ext.astype(np.uint8), mahotas.disk(rad))
	small = small_ext[2*rad : 2*rad + small.shape[0], 2*rad : 2*rad + small.shape[1]]
	small = mahotas.close_holes(small)*1.			
	small = small*255./small.max()

	kmask = ndimage.interpolation.zoom(small, sizefactor)	#scale back to normal size
	kmask = normalize(kmask)
	kmask = (kmask > mahotas.otsu(kmask.astype(np.uint8)))*255.	#remove artifacts of interpolation

	if np.median(imgf[np.where(kmask > 0)]) < (np.median(imgf[np.where(kmask == 0)]) + 1)*3:
		kmask = np.zeros_like(kmask)


	#save indices of the kidney mask
#	ind = np.where(kmask > 0)
#	ind = np.array(ind)
#	np.save(params.inputfolder + '../segmented/masks/' + params.folder + filename[:-4] + '.npy', ind)

	#save outlines
	im = np.zeros([img.shape[0], img.shape[1], 3])
	img = tifffile.imread(params.inputfolder + params.folder + filename)
	im[:,:,0] = im[:,:,1] = im[:,:,2] = np.array(img)
	output = overlay(kmask, im, (255,0,0), borders = True)
	tifffile.imsave(params.inputfolder + '../segmented/outlines/' + params.folder + filename[:-4] + '.tif', (output).astype(np.uint8))
Example #5
0
def test_eccentricity():
    D = mh.disk(32, 2)
    ecc = mahotas.features.shape.eccentricity(D)
    assert 0 <= ecc < .01

    Index = np.indices((33,33)).astype(float)
    Index -= 15
    X,Y = Index
    ellipse = ((X**2+2*Y**2) < 12**2)
    assert 0 < mahotas.features.shape.eccentricity(ellipse) < 1
def test_eccentricity():
    D = mh.disk(32, 2)
    ecc = mahotas.features.shape.eccentricity(D)
    assert 0 <= ecc < .01

    Index = np.indices((33, 33)).astype(float)
    Index -= 15
    X, Y = Index
    ellipse = ((X**2 + 2 * Y**2) < 12**2)
    assert 0 < mahotas.features.shape.eccentricity(ellipse) < 1
def segment_tissue2d(input_file, output_file, voxel_xy):
    # load image
    img = io.imread(input_file)

    # normalize image
    img = ndimage.median_filter(img, 3)
    img = img * 255. / img.max()

    ##segment kidney tissue

    sizefactor = 10.
    small = ndimage.interpolation.zoom(
        img, 1. / sizefactor)  # scale the image to a smaller size

    imgf = ndimage.gaussian_filter(small, 3. / voxel_xy)  # Gaussian filter
    median = np.percentile(imgf, 40)  # 40-th percentile for thresholding

    kmask = imgf > median * 1.5  # thresholding
    kmask = mahotas.dilate(kmask, mahotas.disk(5))
    kmask = mahotas.close_holes(kmask)  # closing holes
    kmask = mahotas.erode(kmask, mahotas.disk(5)) * 255

    # remove objects that are darker than 2*percentile
    l, n = ndimage.label(kmask)
    llist = np.unique(l)
    if len(llist) > 2:
        means = ndimage.mean(imgf, l, llist)
        bv = llist[np.where(means < median * 2)]
        ix = np.in1d(l.ravel(), bv).reshape(l.shape)
        kmask[ix] = 0

    kmask = ndimage.interpolation.zoom(kmask,
                                       sizefactor)  # scale back to normal size
    kmask = normalize(kmask)
    kmask = (kmask > mahotas.otsu(kmask.astype(np.uint8))
             )  # remove artifacts of interpolation

    tifffile.imsave(output_file, img_as_ubyte(kmask), compress=5)
Example #8
0
  def random_watershed(array, speed_image, border_seeds=False, erode=False):
    '''
    '''
    copy_array = np.array(array, dtype=np.bool)

    if erode:
      
      for i in range(10):
        copy_array = mh.erode(copy_array)


    seed_array = np.array(copy_array)
    if border_seeds:
      seed_array = mh.labeled.border(copy_array, 1, 0, Bc=mh.disk(7))

    coords = zip(*np.where(seed_array==1))

    if len(coords) == 0:
      # print 'err'
      return np.zeros(array.shape)

    seed1_ = None
    seed2_ = None
    max_distance = -np.inf

    for i in range(10):
      seed1 = random.choice(coords)
      seed2 = random.choice(coords)
      d = distance.euclidean(seed1, seed2)
      if max_distance < d:
        max_distance = d
        seed1_ = seed1
        seed2_ = seed2

    seeds = np.zeros(array.shape, dtype=np.uint8)
    seeds[seed1_[0], seed1_[1]] = 1
    seeds[seed2_[0], seed2_[1]] = 2



    for i in range(8):
      seeds = mh.dilate(seeds)

    # Util.view(seeds,large=True)      
    # print speed_image.shape, seeds.shape
    ws = mh.cwatershed(speed_image, seeds)
    ws[array == 0] = 0

    return ws    
Example #9
0
def mahotas_clean_up_seg(input_jacobian, frame_num):
    import mahotas as mh
    dsk = mh.disk(7)
    thresh_r = 0.1
    thresh_g = 1
    size_cutoff = 200

    thresholded_jacobian = (np.int32(np.log(1+input_jacobian[frame_num][0])>thresh_r)+\
                            np.int32(np.log(1+input_jacobian[frame_num][1])>thresh_g))>0
    thresholded_jacobian = mh.close_holes(thresholded_jacobian)
    thresholded_jacobian = mh.erode(thresholded_jacobian, dsk)
    labeled = mh.label(thresholded_jacobian)[0]
    sizes = mh.labeled.labeled_size(labeled)
    too_small = np.where(sizes < size_cutoff)
    labeled = mh.labeled.remove_regions(labeled, too_small)
    thresholded_jacobian = labeled > 0
    thresholded_jacobian = mh.dilate(thresholded_jacobian, dsk)
    return thresholded_jacobian
Example #10
0
def show_segmentation_boundaries(input_image,seg_mask,frame_num,sizeX,sizeY):
    import mahotas as mh
    cmap = plt.get_cmap('gray')
    #outlines
    dsk = mh.disk(7)
    boundaries = mh.dilate(seg_mask,dsk)-seg_mask
    boundaries=boundaries>0
    cmap_2_use = truncate_colormap(cmap,0.9,1)
    border2overlay = np.ma.masked_where(boundaries ==0, boundaries)

    x =mh.as_rgb(input_image[frame_num][0,:,:],input_image[frame_num][1,:,:],np.zeros((sizeY,sizeX)))
    x[:,:,1][x[:,:,1]>240]=240
    x[:,:,0][x[:,:,0]>240]=240

    slice2show = [slice(0,sizeY),slice(0,sizeX)]

    plt.imshow(x[slice2show]/np.array([240.,240.,1]).reshape(1,1,3))
    plt.imshow(border2overlay[slice2show],cmap_2_use,alpha=0.8),plt.axis('off')
Example #11
0
def mahotas_clean_up_seg(input_jacobian,frame_num):
    import mahotas as mh
    dsk = mh.disk(7)
    thresh_r = 0.1
    thresh_g = 1
    size_cutoff = 200
    
    thresholded_jacobian = (np.int32(np.log(1+input_jacobian[frame_num][0])>thresh_r)+\
                            np.int32(np.log(1+input_jacobian[frame_num][1])>thresh_g))>0
    thresholded_jacobian = mh.close_holes(thresholded_jacobian)
    thresholded_jacobian = mh.erode(thresholded_jacobian,dsk)
    labeled = mh.label(thresholded_jacobian)[0]
    sizes = mh.labeled.labeled_size(labeled)
    too_small = np.where(sizes < size_cutoff)
    labeled = mh.labeled.remove_regions(labeled, too_small)
    thresholded_jacobian = labeled>0
    thresholded_jacobian = mh.dilate(thresholded_jacobian,dsk)
    return thresholded_jacobian
Example #12
0
  def generate_correct(image, prob, label):
      '''
      '''

      labels = np.arange(len(Util.get_histogram(label)))[1:] # no zeros
      np.random.shuffle(labels)

      for l in labels:

          # neighbors = PG.grab_neighbors(label, l)
          # for n in neighbors:

          #     patches = PG.analyze_border(image, prob, label, l, n, sample_rate=10)

          #     for s in patches:

          #         yield s
          #         yield PG.fliplr(s)
          #         yield PG.flipud(s)
          #         yield PG.rotate(s, 90)
          #         yield PG.rotate(s, 180)
          #         yield PG.rotate(s, 270)    


        binary_mask = Util.threshold(label, l)
        borders = mh.labeled.borders(binary_mask,Bc=mh.disk(2))
        labeled_borders = skimage.measure.label(borders)
        labeled_borders[borders==0] = 0
        relabeled_borders, no_relabeled_borders = mh.labeled.relabel(labeled_borders.astype(np.uint16))

        for border in range(1,no_relabeled_borders+1):
        
            isolated_border = Util.threshold(relabeled_borders, border)

            patches = PGNew.analyze_border(image, prob, binary_mask, isolated_border)

            for s in patches:

                yield s
                yield PGNew.fliplr(s)
                yield PGNew.flipud(s)
                yield PGNew.rotate(s, 90)
                yield PGNew.rotate(s, 180)
                yield PGNew.rotate(s, 270)  
Example #13
0
def show_segmentation_boundaries(input_image, seg_mask, frame_num, sizeX,
                                 sizeY):
    import mahotas as mh
    cmap = plt.get_cmap('gray')
    #outlines
    dsk = mh.disk(7)
    boundaries = mh.dilate(seg_mask, dsk) - seg_mask
    boundaries = boundaries > 0
    cmap_2_use = truncate_colormap(cmap, 0.9, 1)
    border2overlay = np.ma.masked_where(boundaries == 0, boundaries)

    x = mh.as_rgb(input_image[frame_num][0, :, :],
                  input_image[frame_num][1, :, :], np.zeros((sizeY, sizeX)))
    x[:, :, 1][x[:, :, 1] > 240] = 240
    x[:, :, 0][x[:, :, 0] > 240] = 240

    slice2show = [slice(0, sizeY), slice(0, sizeX)]

    plt.imshow(x[slice2show] / np.array([240., 240., 1]).reshape(1, 1, 3))
    plt.imshow(border2overlay[slice2show], cmap_2_use,
               alpha=0.8), plt.axis('off')
Example #14
0
  def fix_single_merge(cnn, cropped_image, cropped_prob, cropped_binary, N=10, invert=True, dilate=True, 
                       border_seeds=True, erode=False, debug=False, before_merge_error=None,
                       real_border=np.zeros((1,1)), oversampling=False, crop=True):
    '''
    invert: True/False for invert or gradient image
    '''

    bbox = mh.bbox(cropped_binary)

    orig_cropped_image = np.array(cropped_image)
    orig_cropped_prob  = np.array(cropped_prob)
    orig_cropped_binary = np.array(cropped_binary)



    speed_image = None
    if invert:
      speed_image = Legacy.invert(cropped_image, smooth=True, sigma=2.5)
    else:
      speed_image = Legacy.gradient(cropped_image)

    Util.view(speed_image, large=False, color=False)


    dilated_binary = np.array(cropped_binary, dtype=np.bool)
    if dilate:
      for i in range(20):
          dilated_binary = mh.dilate(dilated_binary)      

    Util.view(dilated_binary, large=False, color=False)

    borders = np.zeros(cropped_binary.shape)

    best_border_prediction = np.inf
    best_border_image = np.zeros(cropped_binary.shape)

    original_border = mh.labeled.border(cropped_binary, 1, 0, Bc=mh.disk(3))

    results_no_border = []
    predictions = []
    borders = []
    results = []

    for n in range(N):
        ws = Legacy.random_watershed(dilated_binary, speed_image, border_seeds=border_seeds, erode=erode)
        
        if ws.max() == 0:
          continue

        ws_label1 = ws.max()
        ws_label2 = ws.max()-1
        border = mh.labeled.border(ws, ws_label1, ws_label2)

        # Util.view(ws, large=True)


        # Util.view(border, large=True)

        # print i, len(border[border==True])

        #
        # remove parts of the border which overlap with the original border
        #

        

        ws[cropped_binary == 0] = 0

        # Util.view(ws, large=False, color=False)        

        ws_label1_array = Util.threshold(ws, ws_label1)
        ws_label2_array = Util.threshold(ws, ws_label2)

        eroded_ws1 = np.array(ws_label1_array, dtype=np.bool)
        eroded_ws2 = np.array(ws_label2_array, dtype=np.bool)
        if erode:

          for i in range(5):
            eroded_ws1 = mh.erode(eroded_ws1)

          # Util.view(eroded_ws, large=True, color=False)

          dilated_ws1 = np.array(eroded_ws1)
          for i in range(5):
            dilated_ws1 = mh.dilate(dilated_ws1)


          for i in range(5):
            eroded_ws2 = mh.erode(eroded_ws2)

          # Util.view(eroded_ws, large=True, color=False)

          dilated_ws2 = np.array(eroded_ws2)
          for i in range(5):
            dilated_ws2 = mh.dilate(dilated_ws2)




          new_ws = np.zeros(ws.shape, dtype=np.uint8)
          new_ws[dilated_ws1 == 1] = ws_label1
          new_ws[dilated_ws2 == 1] = ws_label2


          ws = new_ws

          # Util.view(new_ws, large=True, color=True)

        # ws[original_border == 1] = 0
        
        prediction = Patch.grab_group_test_and_unify(cnn, cropped_image, cropped_prob, ws, ws_label1, ws_label2, oversampling=oversampling)
        
        if prediction == -1 or prediction >= .5:
          # invalid
          continue


        # here we have for one border
        # the border
        # the prediction
        # borders.append(border)
        # predictions.append(prediction)
        results.append((prediction, border))



    return results
Example #15
0
def test_perimeter():
    for r in (40, 80, 160):
        disk = mh.disk(r, 2)
        p = mahotas.labeled.perimeter(disk)
        p_exact = r * np.pi * 2
        assert .9 < (p / p_exact) < 1.1
Example #16
0
def test_perimeter():
    for r in (40,80,160):
        disk = mh.disk(r, 2)
        p = mahotas.labeled.perimeter(disk)
        p_exact = r*np.pi*2
        assert .9 < (p/p_exact)  < 1.1
Example #17
0
def segment_layer(filename, params):
    '''
	Segment one layer in a stack
	'''
    start = time.time()
    #extract pixel size in xy and z
    xsize, zsize = extract_zoom(params.folder)

    #load image
    img = tifffile.imread(params.inputfolder + params.folder + filename)

    #normalize image
    img = ndimage.median_filter(img, 3)
    img = img * 255. / img.max()

    ##segment kidney tissue

    sizefactor = 10.
    small = ndimage.interpolation.zoom(
        img, 1. / sizefactor)  #scale the image to a smaller size

    imgf = ndimage.gaussian_filter(small, 3. / xsize)  #Gaussian filter
    median = np.percentile(imgf, 40)  #40-th percentile for thresholding

    kmask = imgf > median * 1.5  #thresholding
    kmask = mahotas.dilate(kmask, mahotas.disk(5))
    kmask = mahotas.close_holes(kmask)  #closing holes
    kmask = mahotas.erode(kmask, mahotas.disk(5)) * 255

    #remove objects that are darker than 2*percentile
    l, n = ndimage.label(kmask)
    llist = np.unique(l)
    if len(llist) > 2:
        means = ndimage.mean(imgf, l, llist)
        bv = llist[np.where(means < median * 2)]
        ix = np.in1d(l.ravel(), bv).reshape(l.shape)
        kmask[ix] = 0

    kmask = ndimage.interpolation.zoom(kmask,
                                       sizefactor)  #scale back to normal size
    kmask = normalize(kmask)
    kmask = (kmask > mahotas.otsu(kmask.astype(
        np.uint8))) * 255.  #remove artifacts of interpolation

    #save indices of the kidney mask
    ind = np.where(kmask > 0)
    ind = np.array(ind)
    np.save(
        params.inputfolder + '../segmented/masks/kidney/' + params.folder +
        filename[:-4] + '.npy', ind)

    #segment glomeruli, if there is a kidney tissue
    if kmask.max() > 0:
        #remove all intensity variations larger than maximum radius of a glomerulus
        d = mahotas.disk(int(float(params.maxrad) / xsize))
        img = img - mahotas.open(img.astype(np.uint8), d)
        img = img * 255. / img.max()
        ch = img[np.where(kmask > 0)]

        #segment glomeruli by otsu thresholding	only if this threshold is higher than the 75-th percentile in the kidney mask
        t = mahotas.otsu(img.astype(np.uint8))

        if t > np.percentile(ch, 75) * 1.5:
            cells = img > t
            cells[np.where(kmask == 0)] = 0
            cells = mahotas.open(
                cells, mahotas.disk(int(float(params.minrad) / 2. / xsize)))

        else:
            cells = np.zeros_like(img)

    else:
        cells = np.zeros_like(img)

    #save indices of the glomeruli mask
    ind = np.where(cells > 0)
    ind = np.array(ind)
    np.save(
        params.inputfolder + '../segmented/masks/glomeruli/' + params.folder +
        filename[:-4] + '.npy', ind)
Example #18
0
    def fix_single_merge(cnn,
                         cropped_image,
                         cropped_prob,
                         cropped_binary,
                         N=10,
                         invert=True,
                         dilate=True,
                         border_seeds=True,
                         erode=False,
                         debug=False,
                         before_merge_error=None,
                         real_border=np.zeros((1, 1)),
                         oversampling=False,
                         crop=True):
        '''
    invert: True/False for invert or gradient image
    '''

        bbox = mh.bbox(cropped_binary)

        orig_cropped_image = np.array(cropped_image)
        orig_cropped_prob = np.array(cropped_prob)
        orig_cropped_binary = np.array(cropped_binary)

        speed_image = None
        if invert:
            speed_image = Util.invert(cropped_image, smooth=True, sigma=2.5)
        else:
            speed_image = Util.gradient(cropped_image)

        dilated_binary = np.array(cropped_binary, dtype=np.bool)
        if dilate:
            for i in range(20):
                dilated_binary = mh.dilate(dilated_binary)

        # Util.view(dilated_binary, large=True)

        borders = np.zeros(cropped_binary.shape)

        best_border_prediction = np.inf
        best_border_image = np.zeros(cropped_binary.shape)

        original_border = mh.labeled.border(cropped_binary,
                                            1,
                                            0,
                                            Bc=mh.disk(3))

        results_no_border = []
        predictions = []

        for n in range(N):
            ws = Util.random_watershed(dilated_binary,
                                       speed_image,
                                       border_seeds=border_seeds,
                                       erode=erode)

            if ws.max() == 0:
                continue

            ws_label1 = ws.max()
            ws_label2 = ws.max() - 1
            border = mh.labeled.border(ws, ws_label1, ws_label2)

            # Util.view(ws, large=True)

            # Util.view(border, large=True)

            # print i, len(border[border==True])

            #
            # remove parts of the border which overlap with the original border
            #

            ws[cropped_binary == 0] = 0

            # Util.view(ws, large=False, color=False)

            ws_label1_array = Util.threshold(ws, ws_label1)
            ws_label2_array = Util.threshold(ws, ws_label2)

            eroded_ws1 = np.array(ws_label1_array, dtype=np.bool)
            eroded_ws2 = np.array(ws_label2_array, dtype=np.bool)
            if erode:

                for i in range(5):
                    eroded_ws1 = mh.erode(eroded_ws1)

                # Util.view(eroded_ws, large=True, color=False)

                dilated_ws1 = np.array(eroded_ws1)
                for i in range(5):
                    dilated_ws1 = mh.dilate(dilated_ws1)

                for i in range(5):
                    eroded_ws2 = mh.erode(eroded_ws2)

                # Util.view(eroded_ws, large=True, color=False)

                dilated_ws2 = np.array(eroded_ws2)
                for i in range(5):
                    dilated_ws2 = mh.dilate(dilated_ws2)

                new_ws = np.zeros(ws.shape, dtype=np.uint8)
                new_ws[dilated_ws1 == 1] = ws_label1
                new_ws[dilated_ws2 == 1] = ws_label2

                ws = new_ws

                # Util.view(new_ws, large=True, color=True)

            # ws[original_border == 1] = 0

            prediction = Patch.grab_group_test_and_unify(
                cnn,
                cropped_image,
                cropped_prob,
                ws,
                ws_label1,
                ws_label2,
                oversampling=oversampling)

            if prediction == -1:
                # invalid
                continue

            # if (prediction < best_border_prediction):
            #   best_border_prediction = prediction
            #   best_border_image = border
            #   print 'new best', n, prediction

            best_border_image = border

            borders += (border * prediction)

            result = np.array(cropped_binary)
            best_border_image[result == 0] = 0
            result[best_border_image == 1] = 2

            result = skimage.measure.label(result)

            result_no_border = np.array(result)
            result_no_border[best_border_image == 1] = 0

            predictions.append(prediction)
            results_no_border.append(result_no_border)

        # result = np.array(cropped_binary)
        # best_border_image[result==0] = 0
        # result[best_border_image==1] = 2

        # result = skimage.measure.label(result)

        # result_no_border = np.array(result)
        # result_no_border[best_border_image==1] = 0
        # result_no_border = mh.croptobbox(result_no_border)

        # if before_merge_error == None:
        #   continue

        # print result_no_border.shape, before_merge_error.shape

        # if before_merge_error.shape[0] != result_no_border.shape[0] or before_merge_error.shape[1] != result_no_border.shape[1]:
        #   result_no_border = np.resize(result_no_border, before_merge_error.shape)

        # print 'vi', Util.vi(before_merge_error.astype(np.uint8), result_no_border.astype(np.uint8))

        #     if debug:
        #       Util.view(ws, text=str(i) + ' ' + str(prediction))

        result = np.array(cropped_binary)
        best_border_image[result == 0] = 0
        result[best_border_image == 1] = 2

        result = skimage.measure.label(result)

        result_no_border = np.array(result)
        result_no_border[best_border_image == 1] = 0

        return borders, best_border_image, result, result_no_border, results_no_border, predictions
def main(image,
         mask,
         threshold=150,
         bead_size=2,
         superpixel_size=4,
         close_surface=False,
         close_disc_size=8,
         plot=False):
    '''Converts an image stack with labelled cell surface to a cell
    `volume` image

    Parameters
    ----------
    image: numpy.ndarray[Union[numpy.uint8, numpy.uint16]]
        grayscale image in which beads should be detected (3D)
    mask: numpy.ndarray[Union[numpy.int32, numpy.bool]]
        binary or labeled image of cell segmentation (2D)
    threshold: int, optional
        intensity of bead (default: ``150``)
    bead_size: int, optional
        minimal size of bead (default: ``2``)
    superpixel_size: int, optional
        size of superpixels for searching the 3D position of a bead
    close_surface: bool, optional
        whether the interpolated surface should be morphologically closed
    close_disc_size: int, optional
        size in pixels of the disc used to morphologically close the
        interpolated surface
    plot: bool, optional
        whether a plot should be generated (default: ``False``)

    Returns
    -------
    jtmodules.generate_volume_image.Output
    '''

    n_slices = image.shape[-1]
    logger.debug('input image has size %d in last dimension', n_slices)

    logger.debug('mask beads inside cell')
    beads_outside_cell = np.copy(image)
    for iz in range(n_slices):
        beads_outside_cell[mask > 0, iz] = 0

    logger.debug('search for 3D position of beads outside cell')
    slide = np.argmax(beads_outside_cell, axis=2)
    slide[slide > np.percentile(slide[mask == 0], 20)] = 0

    logger.debug('determine surface of slide')
    slide_coordinates = array_to_coordinate_list(slide)
    bottom_surface = fit_plane(
        subsample_coordinate_list(slide_coordinates, 2000))

    logger.debug('detect_beads in 2D')
    mip = np.max(image, axis=-1)
    try:
        # TODO: use LOG filter???
        beads, beads_centroids = detect_blobs(image=mip,
                                              mask=np.invert(mask > 0),
                                              threshold=threshold,
                                              min_area=bead_size)
    except:
        logger.warn('detect_blobs failed, returning empty volume image')
        volume_image = np.zeros(shape=mask.shape, dtype=image.dtype)
        figure = str()
        return Output(volume_image, figure)

    n_beads = np.count_nonzero(beads_centroids)
    logger.info('found %d beads on cells', n_beads)

    if n_beads == 0:
        logger.warn('empty volume image')
        volume_image = np.zeros(shape=mask.shape, dtype=image.dtype)
    else:
        logger.debug('locate beads in 3D')
        beads_coords_3D = locate_in_3D(image=image,
                                       mask=beads_centroids,
                                       bin_size=superpixel_size)

        logger.info('interpolate cell surface')
        volume_image = interpolate_surface(coords=beads_coords_3D,
                                           output_shape=np.shape(image[:, :,
                                                                       1]),
                                           method='linear')

        volume_image = volume_image.astype(image.dtype)

        if (close_surface is True):
            import mahotas as mh
            logger.info('morphological closing of cell surface')
            volume_image = mh.close(volume_image, Bc=mh.disk(close_disc_size))
        volume_image[mask == 0] = 0

    if plot:
        logger.debug('convert bottom surface plane to image for plotting')
        bottom_surface_image = np.zeros(slide.shape, dtype=np.uint8)
        for ix in range(slide.shape[0]):
            for iy in range(slide.shape[1]):
                bottom_surface_image[ix, iy] = plane(ix, iy, bottom_surface.x)

        logger.info('create plot')
        from jtlib import plotting
        plots = [
            plotting.create_intensity_image_plot(mip, 'ul', clip=True),
            plotting.create_intensity_image_plot(bottom_surface_image,
                                                 'll',
                                                 clip=True),
            plotting.create_intensity_image_plot(volume_image, 'ur', clip=True)
        ]
        figure = plotting.create_figure(plots,
                                        title='Convert stack to volume image')
    else:
        figure = str()

    return Output(volume_image, figure)
Example #20
0
  def split_new(image, binary):
    '''
    '''

    bbox = mh.bbox(binary)
    
    sub_image = np.array(image[bbox[0]:bbox[1], bbox[2]:bbox[3]])
    sub_binary = np.array(binary[bbox[0]:bbox[1], bbox[2]:bbox[3]])

    sub_binary_border = mh.labeled.borders(sub_binary, Bc=mh.disk(3))    
    
    sub_binary = mh.erode(sub_binary.astype(np.bool))
    for e in range(5):
      sub_binary = mh.erode(sub_binary)
    # sub_binary = mh.erode(sub_binary)    
    

    if sub_image.shape[0] < 2 or sub_image.shape[1] < 2:
      return np.zeros(binary.shape, dtype=np.bool), np.zeros(binary.shape, dtype=np.bool)

    #
    # smooth the image
    #
    sub_image = mh.gaussian_filter(sub_image, 3.5)

    grad_x = np.gradient(sub_image)[0]
    grad_y = np.gradient(sub_image)[1]
    grad = np.add(np.abs(grad_x), np.abs(grad_y))

    grad -= grad.min()
    grad /= grad.max()
    grad *= 255
    grad = grad.astype(np.uint8)
    
    coords = zip(*np.where(sub_binary==1))

    if len(coords) < 2:
      print 'STRAAAAANGE'
      return np.zeros(binary.shape, dtype=np.bool), np.zeros(binary.shape, dtype=np.bool)

    seed1 = random.choice(coords)
    seed2 = random.choice(coords)
    seeds = np.zeros(sub_binary.shape, dtype=np.uint64)
    seeds[seed1] = 1
    seeds[seed2] = 2

    for i in range(10):
      seeds = mh.dilate(seeds)

    ws = mh.cwatershed(grad, seeds)
    ws[sub_binary==0] = 0

#     ws_relabeled = skimage.measure.label(ws.astype(np.uint8))
#     ws_relabeled[sub_binary==0] = 0
#     max_label = ws_relabeled.max()
#     plt.figure()
#     imshow(ws)

    binary_mask = Util.threshold(ws, ws.max())
    border = mh.labeled.border(ws, ws.max(), ws.max()-1, Bc=mh.disk(2))
#     border[sub_binary_border == 1] = 0 # remove any "real" border pixels
    
#     plt.figure()
#     imshow(binary_mask)

#     plt.figure()
#     imshow(border)

    
    large_label = np.zeros(binary.shape, dtype=np.bool)
    large_border = np.zeros(binary.shape, dtype=np.bool)
    large_label[bbox[0]:bbox[1], bbox[2]:bbox[3]] = binary_mask
    large_border[bbox[0]:bbox[1], bbox[2]:bbox[3]] = border
    
    return large_label, large_border
Example #21
0
    def split_label(image, binary):

        bbox = mh.bbox(binary)

        sub_image = np.array(image[bbox[0]:bbox[1], bbox[2]:bbox[3]])
        sub_binary = np.array(binary[bbox[0]:bbox[1], bbox[2]:bbox[3]])

        sub_binary_border = mh.labeled.borders(sub_binary, Bc=mh.disk(3))

        sub_binary = mh.erode(sub_binary.astype(np.bool))
        for e in range(15):
            sub_binary = mh.erode(sub_binary)
        # # sub_binary = mh.erode(sub_binary)

        if sub_binary.shape[0] < 2 or sub_binary.shape[1] < 2:
            return np.zeros(binary.shape,
                            dtype=np.bool), np.zeros(binary.shape,
                                                     dtype=np.bool)

        #
        # smooth the image
        #
        sub_image = mh.gaussian_filter(sub_image, 3.5)

        grad_x = np.gradient(sub_image)[0]
        grad_y = np.gradient(sub_image)[1]
        grad = np.add(np.abs(grad_x), np.abs(grad_y))

        grad -= grad.min()
        grad /= grad.max()
        grad *= 255
        grad = grad.astype(np.uint8)

        coords = zip(*np.where(sub_binary == 1))

        if len(coords) < 2:
            # print 'STRAAAAANGE'
            return np.zeros(binary.shape,
                            dtype=np.bool), np.zeros(binary.shape,
                                                     dtype=np.bool)

        seed1 = random.choice(coords)
        seed2 = random.choice(coords)
        seeds = np.zeros(sub_binary.shape, dtype=np.uint64)
        seeds[seed1] = 1
        seeds[seed2] = 2

        for i in range(10):
            seeds = mh.dilate(seeds)

        ws = mh.cwatershed(grad, seeds)
        ws[sub_binary == 0] = 0

        #     ws_relabeled = skimage.measure.label(ws.astype(np.uint8))
        #     ws_relabeled[sub_binary==0] = 0
        #     max_label = ws_relabeled.max()
        #     plt.figure()
        #     imshow(ws)

        binary_mask = Util.threshold(ws, ws.max())
        border = mh.labeled.border(ws, ws.max(), ws.max() - 1, Bc=mh.disk(2))
        border[sub_binary_border == 1] = 0  # remove any "real" border pixels

        #     plt.figure()
        #     imshow(binary_mask)

        #     plt.figure()
        #     imshow(border)

        # at this point, there can be multiple borders and labels
        labeled_border = skimage.measure.label(border)
        labeled_binary_mask = skimage.measure.label(binary_mask)
        # .. and we are going to select only the largest
        largest_border_label = Util.get_largest_label(
            labeled_border.astype(np.uint16), True)
        largest_binary_mask_label = Util.get_largest_label(
            labeled_binary_mask.astype(np.uint16), True)
        # .. filter out everything else
        border[labeled_border != largest_border_label] = 0
        binary_mask[labeled_binary_mask != largest_binary_mask_label] = 0

        large_label = np.zeros(binary.shape, dtype=np.bool)
        large_border = np.zeros(binary.shape, dtype=np.bool)
        large_label[bbox[0]:bbox[1], bbox[2]:bbox[3]] = binary_mask
        large_border[bbox[0]:bbox[1], bbox[2]:bbox[3]] = border

        return large_label, large_border
def main(image, mask, threshold=150, bead_size=2, superpixel_size=4,
         close_surface=False, close_disc_size=8, plot=False):
    '''Converts an image stack with labelled cell surface to a cell
    `volume` image

    Parameters
    ----------
    image: numpy.ndarray[Union[numpy.uint8, numpy.uint16]]
        grayscale image in which beads should be detected (3D)
    mask: numpy.ndarray[Union[numpy.int32, numpy.bool]]
        binary or labeled image of cell segmentation (2D)
    threshold: int, optional
        intensity of bead (default: ``150``)
    bead_size: int, optional
        minimal size of bead (default: ``2``)
    superpixel_size: int, optional
        size of superpixels for searching the 3D position of a bead
    close_surface: bool, optional
        whether the interpolated surface should be morphologically closed
    close_disc_size: int, optional
        size in pixels of the disc used to morphologically close the
        interpolated surface
    plot: bool, optional
        whether a plot should be generated (default: ``False``)

    Returns
    -------
    jtmodules.generate_volume_image.Output
    '''

    n_slices = image.shape[-1]
    logger.debug('input image has size %d in last dimension', n_slices)

    logger.debug('mask beads inside cell')
    beads_outside_cell = np.copy(image)
    for iz in range(n_slices):
        beads_outside_cell[mask > 0, iz] = 0

    logger.debug('search for 3D position of beads outside cell')
    slide = np.argmax(beads_outside_cell, axis=2)
    slide[slide > np.percentile(slide[mask == 0], 20)] = 0

    logger.debug('determine surface of slide')
    slide_coordinates = array_to_coordinate_list(slide)
    bottom_surface = fit_plane(subsample_coordinate_list(
        slide_coordinates, 2000)
    )

    logger.debug('detect_beads in 2D')
    mip = np.max(image, axis=-1)
    try:
        # TODO: use LOG filter???
        beads, beads_centroids = detect_blobs(
            image=mip, mask=np.invert(mask > 0), threshold=threshold,
            min_area=bead_size
        )
    except:
        logger.warn('detect_blobs failed, returning empty volume image')
        volume_image = np.zeros(shape=mask.shape, dtype=image.dtype)
        figure = str()
        return Output(volume_image, figure)

    n_beads = np.count_nonzero(beads_centroids)
    logger.info('found %d beads on cells', n_beads)

    if n_beads == 0:
        logger.warn('empty volume image')
        volume_image = np.zeros(shape=mask.shape, dtype=image.dtype)
    else:
        logger.debug('locate beads in 3D')
        beads_coords_3D = locate_in_3D(
            image=image, mask=beads_centroids,
            bin_size=superpixel_size
        )

        logger.info('interpolate cell surface')
        volume_image = interpolate_surface(
            coords=beads_coords_3D,
            output_shape=np.shape(image[:, :, 1]),
            method='linear'
        )

        volume_image = volume_image.astype(image.dtype)

        if (close_surface is True):
            import mahotas as mh
            logger.info('morphological closing of cell surface')
            volume_image = mh.close(volume_image,
                                    Bc=mh.disk(close_disc_size))
        volume_image[mask == 0] = 0

    if plot:
        logger.debug('convert bottom surface plane to image for plotting')
        bottom_surface_image = np.zeros(slide.shape, dtype=np.uint8)
        for ix in range(slide.shape[0]):
            for iy in range(slide.shape[1]):
                bottom_surface_image[ix, iy] = plane(
                    ix, iy, bottom_surface.x)

        logger.info('create plot')
        from jtlib import plotting
        plots = [
            plotting.create_intensity_image_plot(
                mip, 'ul', clip=True
            ),
            plotting.create_intensity_image_plot(
                bottom_surface_image, 'll', clip=True
            ),
            plotting.create_intensity_image_plot(
                volume_image, 'ur', clip=True
            )
        ]
        figure = plotting.create_figure(
            plots, title='Convert stack to volume image'
        )
    else:
        figure = str()

    return Output(volume_image, figure)