Beispiel #1
0
	def get_disease2(self):
		r,g,b = my_image.image_split(self.i_source)
		hsv = rgb2hsv(self.i_source)
		dise= np.copy(self.i_source[:,:,1])
		dise[dise>1]=0
		dise[(hsv[:,:,0]>0) & (hsv[:,:,0]<float(45.0/255))&(r<100)&(g<100)&(b<50)]=1
		label_im, nb_labels = ndimage.label(dise)
		sizes = ndimage.sum(dise, label_im, range(nb_labels + 1))
		mean_vals = ndimage.sum(dise, label_im, range(1, nb_labels + 1))
		mask_size = sizes < np.max(sizes)
		remove_pixel = mask_size[label_im]
		label_im[remove_pixel] = 0
		label_im[label_im>0]=1
		
#		pdb.set_trace()
		###
		# remove artifacts connected to image border
		self.s_disease = 0
		# label image regions
		region = regionprops(label(label_im))
		for r1 in region:
#			pdb.set_trace()
			if r1.area > 10:
				self.s_disease += r1.area
			else:
				minr, minc, maxr, maxc = r1.bbox
				label_im[float(minr):float(maxr),float(minc):float(maxc)]=0
							
		self.i_desease = label_im 
		self.i_leaf = self.i_source#blade
		self.i_back = self.i_source#background
		self.s_leaf = 1#s_b+s_d
Beispiel #2
0
    def _estimate_profile(self, image, image_err, mask):
        """
        Estimate image profile.
        """
        from scipy import ndimage

        p = self.parameters
        labels = self._label_image(image, mask)

        profile_err = None

        index = np.arange(1, len(self._get_x_edges(image)))

        if p['method'] == 'sum':
            profile = ndimage.sum(image.data, labels.data, index)

            if image.unit.is_equivalent('counts'):
                profile_err = np.sqrt(profile)
            elif image_err:
                # gaussian error propagation
                err_sum = ndimage.sum(image_err.data ** 2, labels.data, index)
                profile_err = np.sqrt(err_sum)

        elif p['method'] == 'mean':
            # gaussian error propagation
            profile = ndimage.mean(image.data, labels.data, index)
            if image_err:
                N = ndimage.sum(~np.isnan(image_err.data), labels.data, index)
                err_sum = ndimage.sum(image_err.data ** 2, labels.data, index)
                profile_err = np.sqrt(err_sum) / N

        return profile, profile_err
 def calculate_zernikes(self, workspace):
     zernike_indexes = cpmz.get_zernike_indexes(self.zernike_degree.value + 1)
     meas = workspace.measurements
     for o in self.objects:
         object_name = o.object_name.value
         objects = workspace.object_set.get_objects(object_name)
         #
         # First, get a table of centers and radii of minimum enclosing
         # circles per object
         #
         ij = np.zeros((objects.count + 1, 2))
         r = np.zeros(objects.count + 1)
         for labels, indexes in objects.get_labels():
             ij_, r_ = minimum_enclosing_circle(labels, indexes)
             ij[indexes] = ij_
             r[indexes] = r_
         #
         # Then compute x and y, the position of each labeled pixel
         # within a unit circle around the object
         #
         ijv = objects.ijv
         l = ijv[:, 2]
         yx = (ijv[:, :2] - ij[l, :]) / r[l, np.newaxis]
         z = cpmz.construct_zernike_polynomials(
                 yx[:, 1], yx[:, 0], zernike_indexes)
         for image_group in self.images:
             image_name = image_group.image_name.value
             image = workspace.image_set.get_image(
                     image_name, must_be_grayscale=True)
             pixels = image.pixel_data
             mask = (ijv[:, 0] < pixels.shape[0]) & \
                    (ijv[:, 1] < pixels.shape[1])
             mask[mask] = image.mask[ijv[mask, 0], ijv[mask, 1]]
             yx_ = yx[mask, :]
             l_ = l[mask]
             z_ = z[mask, :]
             if len(l_) == 0:
                 for i, (n, m) in enumerate(zernike_indexes):
                     ftr = self.get_zernike_magnitude_name(image_name, n, m)
                     meas[object_name, ftr] = np.zeros(0)
                     if self.wants_zernikes == Z_MAGNITUDES_AND_PHASE:
                         ftr = self.get_zernike_phase_name(image_name, n, m)
                         meas[object_name, ftr] = np.zeros(0)
                 continue
             areas = scind.sum(
                     np.ones(l_.shape, int), labels=l_, index=objects.indices)
             for i, (n, m) in enumerate(zernike_indexes):
                 vr = scind.sum(
                         pixels[ijv[mask, 0], ijv[mask, 1]] * z_[:, i].real,
                         labels=l_, index=objects.indices)
                 vi = scind.sum(
                         pixels[ijv[mask, 0], ijv[mask, 1]] * z_[:, i].imag,
                         labels=l_, index=objects.indices)
                 magnitude = np.sqrt(vr * vr + vi * vi) / areas
                 ftr = self.get_zernike_magnitude_name(image_name, n, m)
                 meas[object_name, ftr] = magnitude
                 if self.wants_zernikes == Z_MAGNITUDES_AND_PHASE:
                     phase = np.arctan2(vr, vi)
                     ftr = self.get_zernike_phase_name(image_name, n, m)
                     meas[object_name, ftr] = phase
def getRealLabeledAreaCenter(image,labeled_image,indices,info):
        print "Getting real area and center"
        shape=numpy.shape(image)
        ones=numpy.ones(shape)
        area=nd.sum(ones,labels=labeled_image,index=indices)
        center=nd.center_of_mass(ones,labels=labeled_image,index=indices)

        ll=0
        try:
                len(area)
        except:
                area=[area]
                center=[center]
                try:
                        len(indices)
                except:
                        indices=[indices]
        try:
                info.keys()
        except:
                offset=1
        else:
                offset=0
        for l in indices:
                info[l-offset][0]=area[ll]
                info[l-offset][4]=center[ll]
                ll += 1
        return info     
def getRealLabeledPerimeter(image,edge_mask,labeled_image,indices,info,testlog):
        print "Getting real perimeter length"
        edgeimage,testlog=findEdgeSobel(edge_mask,0,0.5,1.0,False,testlog)
        mask=ma.getmask(edgeimage)
        length=nd.sum(mask,labels=labeled_image,index=indices)
                
        ll=0
        try:
                len(length)
        except:
                length=[length]
                try:
                        len(indices)
                except:
                        indices=[indices]
        try:
                info.keys()
        except:
                offset=1
        else:
                offset=0
        for l in indices:
                info[l-offset][3]=length[ll]
                ll += 1
        return info     
Beispiel #6
0
def remove_small_objects(arr, min_size, connectivity=8):
    '''
    Remove objects less than the given size.
    Function is based on skimage.morphology.remove_small_objects

    Parameters
    ----------
    arr : numpy.ndarray
        Binary array containing the mask.
    min_size : int
        Smallest allowed size.
    connectivity : int, optional
        Connectivity of the neighborhood.
    '''

    struct = nd.generate_binary_structure(arr.ndim, connectivity)

    labels, num = nd.label(arr, struct)

    sizes = nd.sum(arr, labels, range(1, num + 1))

    for i, size in enumerate(sizes):
        if size >= min_size:
            continue

        posns = np.where(labels == i + 1)

        arr[posns] = 0

    return arr
def kill_isolated_pixels(array,
                         structure=None,
                         threshold=0.2):
    """
    Return array with isolated islands removed.
    Only keeping the biggest islands (largest surface).

    :param array: Array with completely isolated cells
    :param struct: Structure array for generating unique regions
    :return: Filtered array with just the largest island
    """

    filtered_array = np.copy(array)

    # Put to 0 pixels that are below 'threshold'
    filtered_array[filtered_array < threshold] = 0
    mask = filtered_array > 0

    # Detect islands ("label")
    label_array, num_labels = ndimage.label(mask, structure=structure)

    # Count the number of pixels for each island
    num_pixels_per_island = ndimage.sum(filtered_array, label_array, range(num_labels + 1))

    # Only keep the biggest island
    mask_biggest_island = num_pixels_per_island < np.max(num_pixels_per_island)
    remove_pixel = mask_biggest_island[label_array]

    filtered_array[remove_pixel] = 0

    return filtered_array
def fillDataDict(radlist, anglelist, freqlist):
        """
        Get min/max statistics on data lists
        """
        d = {}
        freqnumpy = numpy.asarray(freqlist, dtype=numpy.int32)
        d['minf'] = float(ndimage.minimum(freqnumpy))
        d['maxf'] = float(ndimage.maximum(freqnumpy))
        if ndimage.sum(freqnumpy) < 10:
                apDisplay.printWarning("not enough eulers to draw a map")
                return None
        d['rangef'] = d['maxf']-d['minf']+1

        angnumpy = numpy.asarray(anglelist, dtype=numpy.float32)
        d['mina'] = float(ndimage.minimum(angnumpy))
        d['maxa'] = float(ndimage.maximum(angnumpy))
        if d['maxa'] > 330.0*math.pi/180.0:
                d['maxa'] = 2.0*math.pi
        d['rangea'] = d['maxa']-d['mina']

        radnumpy = numpy.asarray(radlist, dtype=numpy.float32)
        d['minr'] = float(ndimage.minimum(radnumpy))
        d['maxr'] = float(ndimage.maximum(radnumpy))
        d['ranger'] = d['maxr']-d['minr']

        xnumpy = radnumpy * numpy.cos(angnumpy - d['mina'])
        ynumpy = radnumpy * numpy.sin(angnumpy - d['mina'])
        d['minx'] = float(ndimage.minimum(xnumpy))
        d['maxx'] = float(ndimage.maximum(xnumpy))
        d['miny'] = float(ndimage.minimum(ynumpy))
        d['maxy'] = float(ndimage.maximum(ynumpy))
        d['rangex'] = d['maxx']-d['minx']
        d['rangey'] = d['maxy']-d['miny']

        return d
def segmentationize(imageSe):
    """
    Divides coherent forms of an image in smaller groups of type integer.
    """
    
    # create an matrix of distances to the next sourrounding area
    distance = ndimage.distance_transform_edt(imageSe, sampling=3)
    erosed = ndimage.binary_erosion(imageSe, iterations=8).astype(imageSe.dtype)
    distanceE = ndimage.distance_transform_edt(erosed, sampling=3)
    distance += (2 * distanceE)
    labels, num = label(imageSe, background=0, return_num='True')
    sizes_image = ndimage.sum(imageSe, labels, range(num))
    sizes_image = np.sort(sizes_image, axis=None)
    pos = int(0.4 * num)
    areal = int(sizes_image[pos] ** 0.5)
    if areal <= 10:
        areal = 10
    elif (areal % 2) != 0:
        areal += 1
    footer = circarea(areal) # draw circle area
    
    # find the positions of the maxima from the distances
    local_maxi = peak_local_max(distance, indices=False, footprint=footer, labels=imageSe)
    markers = label(local_maxi)
    
    # watershed algorithm starts at the maxima and returns labels of particles
    simplefilter("ignore", FutureWarning)   # avoid warning in watershed method
    labels_ws = watershed(-distance, markers, mask=imageSe)
    simplefilter("default", FutureWarning)
    
    return labels, labels_ws, local_maxi
def removeSmall(im, size):
    '''
    Remove small regions from a numpy image
    inut image is black on white (std)
    inversion is done internally
    Image for labeling needs to be White on black
    The image returned is inverted (black on white )
    '''
    #im = 255-im
    label_im, nb_labels = ndimage.label(im)
    mask = im>im.mean()
    sizes = ndimage.sum(mask, label_im, range(nb_labels + 1))
    mean_vals = ndimage.sum(im, label_im, range(1, nb_labels + 1))
    mask_size = sizes < size
    remove_pixel = mask_size[label_im]
    return remove_pixel
Beispiel #11
0
def threshold_connect_components(map, threshold, copy=True):
    """ Given a map with some coefficients set to zero, segment the
        connect components with number of voxels smaller than the
        threshold and set them to 0.

        Parameters
        ----------
        map: ndarray
            The map to segment
        threshold:
            The minimum number of voxels to keep a cluster.
        copy: bool, optional
            If copy is false, the input array is modified inplace
    """
    labels, n_labels = ndimage.label(map)
    weights = ndimage.sum(np.ones_like(labels), 
                          labels, index=range(n_labels)) 
    if copy:
        map = map.copy()
    for index, weight in enumerate(weights):
        if index == 0:
            continue
        if weight < threshold:
            map[labels == index] = 0
    return map
Beispiel #12
0
def clean_zones(zones, minSegmentSize):
    ''' Remove small zones and replace with nearest neigbour'''
    # bad zones mask
    badMask = zones == -1

    # split multi-part zones
    zonesAll = split_multi_zones(zones)

    # find areas of all zones
    zAllIndeces = np.unique(zonesAll)
    zAllIndeces = zAllIndeces[zAllIndeces >= 0]
    zAllAreas = nd.sum(np.ones_like(zones), zonesAll, zAllIndeces)

    # set zones with small areas to -1
    for zai in zAllIndeces[zAllAreas < minSegmentSize]:
        zonesAll[zonesAll == zai] = -1

    # fill small segments with values from nearest neighbours
    invalid_cell_mask = zonesAll == -1
    indices = nd.distance_transform_edt(invalid_cell_mask, return_distances=False, return_indices=True)
    zonesClean = zones[tuple(indices)]

    # mask bad values with 0
    zonesClean[badMask] = -1

    return zonesClean
Beispiel #13
0
    def updatemain(self):

        if self.verbose:
            print "updating",self.layer
        if self.xview:
            # dataswappedX = np.swapaxes(self.data,0,1)
            self.arr=self.dataswappedX[self.layer]
        elif self.yview:
            # dataswappedY = np.swapaxes(self.data,0,2)
            self.arr=self.dataswappedY[self.layer]
        else:
            self.arr=self.data[self.layer]
        self.img1a.setImage(self.arr)
        if self.firsttime:
            self.firsttime = False
        else:
            if self.verbose:
                print self.rois
            if self.rois[self.layer]:
                # self.p1.removeItem(self.roi)
                # self.restorePolyLineState(self.roi, self.rois[self.layer])
                self.roi.setState(self.rois[self.layer])
                # self.p1.addItem(self.roi)
                
            self.update()
            self.label_layer.setText("layer: "+str(self.layer+1)+"/"+str(len(self.data[:,:,:,0])))
            self.label_shape.setText("shape: "+str(self.arr[:,:,0].shape))
            self.label_size.setText("size: "+str(self.arr[:,:,0].size))
            self.label_min.setText("min: "+str(self.arr[:,:,0].min()))
            self.label_max.setText("max: "+str(self.arr[:,:,0].max()))
            self.label_mean.setText("mean: "+str(self.arr[:,:,0].mean()))
            self.label_sd.setText("sd: "+str(ndimage.standard_deviation(self.arr[:,:,0])))
            self.label_sum.setText("sum: "+str(ndimage.sum(self.arr[:,:,0])))
        self.img1a.updateImage()
Beispiel #14
0
 def makeSummedMask(self):
   '''Make a mask by summing all frames, creating a histogram and using the maximum bin
   '''
   #self.sumData = self.imgData.sum(axis=0)
   sumData = self.cData.getImageSum()
   hist, bins = np.histogram(sumData.ravel(), bins=100)
   mask = sumData > bins[3]
   label_im, nb_labels = ndimage.label(mask)
   sizes = ndimage.sum(mask, label_im, range(nb_labels + 1))
   mean_vals = ndimage.sum(self.cData.getImage(), label_im, range(1, nb_labels + 1))
   mask_size = sizes < max(sizes)
   #print(sizes, mask_size, max(sizes))
   remove_pixel = mask_size[label_im]
   label_im[remove_pixel] = 0
   label_im = ndimage.binary_dilation(label_im)
   return label_im
Beispiel #15
0
def print_mask_summary(mask):
    labels, nmax = ni.label(mask)
    pix_sum = ni.sum(mask, labels=labels, index=np.arange(1, nmax+1))

    print "number of islands :" , len(pix_sum), "%5.2f%%" % (float(len(pix_sum))/len(mask.flat)*100.)
    print "total area :", np.max(pix_sum)
    print "number of large islands (A > 9 pix) :", np.sum(pix_sum > 9)
Beispiel #16
0
def test_sum11():
    labels = np.array([1, 2], np.int8)
    for type in types:
        input = np.array([[1, 2], [3, 4]], type)
        output = ndimage.sum(input, labels=labels,
                                       index=2)
        assert_almost_equal(output, 6.0)
    def get_labels(self):
        """
        find clusters and extract center and size
        Parameters
        ----------

        Returns
        -------
        self.labels : 'list'
            list of cluster labels
        self.centers : 'list'
            list of cluster centers
        self.sizes : 'list'
            list of cluster sizes

        """
        b_img = self.img_b
        label_im, nb_labels = ndimage.label(b_img)

        center = np.asarray(ndimage.center_of_mass(b_img, label_im,
                            range(1, nb_labels + 1)))
        size = np.asarray(ndimage.sum(b_img, label_im,
                          range(1, nb_labels + 1)))

        self.labels = label_im
        self.centers = center
        self.sizes = size
Beispiel #18
0
def test_sum12():
    labels = np.array([[1, 2], [2, 4]], np.int8)
    for type in types:
        input = np.array([[1, 2], [3, 4]], type)
        output = ndimage.sum(input, labels=labels,
                                        index=[4, 8, 2])
        assert_array_almost_equal(output, [4.0, 0.0, 5.0])
Beispiel #19
0
def test_sum08():
    "sum 8"
    labels = np.array([1, 0], bool)
    for type in types:
        input = np.array([1, 2], type)
        output = ndimage.sum(input, labels=labels)
        assert_equal(output, 1.0)
Beispiel #20
0
def test_sum09():
    "sum 9"
    labels = np.array([1, 0], bool)
    for type in types:
        input = np.array([[1, 2], [3, 4]], type)
        output = ndimage.sum(input, labels=labels)
        assert_almost_equal(output, 4.0)
Beispiel #21
0
def test_sum06():
    "sum 6"
    labels = np.array([], bool)
    for type in types:
        input = np.array([], type)
        output = ndimage.sum(input, labels=labels)
        assert_equal(output, 0.0)
Beispiel #22
0
def test_sum07():
    "sum 7"
    labels = np.ones([0, 4], bool)
    for type in types:
        input = np.zeros([0, 4], type)
        output = ndimage.sum(input, labels=labels)
        assert_equal(output, 0.0)
Beispiel #23
0
def FilterArea(img, labels, nb_labels, threshold):
    
    """
        Function definition
        +++++++++++++++++++
            
        .. py:function:: FilterArea(img, labels, nb_labels, threshold)
            
            This method eliminates connected components whose areas are smaller than a threshold. 

            :param numpy_array img: binary image on which connected components were estimated.
            :param numpy_array img: labeled image that corresponds to the output of the **ConnenctedComponents(img)**
                                    method.
            :param int nb_labels: number of labels in labeled image.
            :param float threshold: area threshold to eliminate small connected components.
            :return: new labeled image and number of newlabels.
            :rtype: numpy array of the same dimensions with img - int.
        """
    
    filt_labels = np.copy(labels)
    
    areas = ndimage.sum(img, labels, range(nb_labels + 1))
    mask_size = areas < threshold
    remove_pixel = mask_size[labels]
    filt_labels[remove_pixel] = 0
    new_labels = np.unique(filt_labels)
    filt_labels = np.searchsorted(new_labels, filt_labels)
        
    return filt_labels, new_labels.shape[0]-1
Beispiel #24
0
def get_largest_two_component(img, prt = False, threshold = None):
    s = ndimage.generate_binary_structure(3,2) # iterate structure
    labeled_array, numpatches = ndimage.label(img,s) # labeling
    sizes = ndimage.sum(img,labeled_array,range(1,numpatches+1))
    sizes_list = [sizes[i] for i in range(len(sizes))]
    sizes_list.sort()
    #if(prt):
    #    print('component size', sizes_list, flush = True)
    if(len(sizes) == 1):
        return img
    else:
        if(threshold):
            out_img = np.zeros_like(img)
            for temp_size in sizes_list:
                if(temp_size > threshold):
                    temp_lab = np.where(sizes == temp_size)[0] + 1
                    temp_cmp = labeled_array == temp_lab
                    out_img = (out_img + temp_cmp) > 0
            return out_img
        else:
            max_size1 = sizes_list[-1]
            max_size2 = sizes_list[-2]
            max_label1 = np.where(sizes == max_size1)[0] + 1
            max_label2 = np.where(sizes == max_size2)[0] + 1
            component1 = labeled_array == max_label1
            component2 = labeled_array == max_label2
            #if(prt):
            #    print(max_size2, max_size1, max_size2/max_size1, flush = True)
            if(max_size2*10 > max_size1):
                component1 = (component1 + component2) > 0

            return component1
Beispiel #25
0
def _sim_mask(in_file):
    import nibabel as nb
    import numpy as np
    import os.path as op
    import scipy.ndimage as sn
    from scipy.ndimage.morphology import (binary_opening, binary_dilation)
    from pyacwereg.misc import ball as gen_ball

    if not isinstance(in_file, basestring):
        in_file = in_file[2]

    out_file = op.abspath('sim_mask.nii.gz')

    im = nb.load(in_file)
    data = im.get_data()
    data[data > 1.0e-4] = 1
    data[data < 1] = 0

    ball1 = gen_ball(4, 1.9)
    data = binary_opening(data.astype(np.uint8), structure=ball1,
                          iterations=1).astype(np.uint8)
    # Get largest object
    label_im, nb_labels = sn.label(data)
    sizes = sn.sum(data, label_im, range(nb_labels + 1))
    larger = np.squeeze(np.argwhere(sizes == sizes.max()))
    data[label_im != larger] = 0

    # Dilate
    # data = binary_dilation(data, structure=ball1,
    #                        iterations=1).astype(np.uint8)

    nb.Nifti1Image(
        data, im.get_affine(), im.get_header()).to_filename(out_file)
    return out_file
Beispiel #26
0
    def connected_comonents(self, threshold):
        connect_structure = np.ones((3,3,3), dtype='int')
        grid = self.grid
        labeled_arr, n_labels = ni.label(grid, connect_structure)

        if n_labels == 0:
            return labeled_arr, n_labels

        labels_list = range(1,n_labels+1)
        count_objects = ni.sum(grid, labeled_arr, labels_list)
        if n_labels == 1:
            count_objects = [count_objects]

        t0 = time.time()
        new_labels_list = []

        for c,l in zip(count_objects, labels_list):
            if c > threshold:
                new_labels_list.append(l)
            else:
                labeled_arr[np.where(labeled_arr == l)] = 0

        # relabel stuff
        for nl,l in enumerate(new_labels_list):
            labeled_arr[np.where(labeled_arr == l)] = nl+1
        n_labels = len(new_labels_list)
        t1 = time.time()
        print 'time:', t1-t0
        return labeled_arr, n_labels
Beispiel #27
0
def reg_median_cont(data,mask,min_size):
    emask = ndimage.morphology.binary_erosion(mask,iterations=2)
    cmask = mask[:]
    cmask[emask==1]=0
    label_im, nb_labels = ndimage.label(cmask)
    sizes = ndimage.sum(cmask,label_im,range(nb_labels+1))
    mask_size = sizes < min_size
    remove_pixel = mask_size[label_im]
    label_im[remove_pixel] = 0
    labels = np.unique(label_im)
    label_im = np.searchsorted(labels, label_im)
    labels = np.unique(label_im)
    out = np.array(label_im,dtype=np.float)
    for lab in labels:
        if( lab==0 ): continue
        try:
            slice_x, slice_y = ndimage.find_objects(label_im==lab)[0]
        except IndexError:
            print ("Bad index: "%lab)
            continue
#        print lab
        rois = data[slice_x, slice_y]
        tmask = label_im==lab 
        roim = tmask[slice_x, slice_y]
        roio = out[slice_x, slice_y]
        mean = np.ma.median(np.ma.array(rois,mask=~roim))
        roio[roim] = mean

    return out
def getAxyLabels(labels, imageDir="Left_to_right", edgeThickness=1, fraction=None):
    """
    Get the edges touched by clusters/avalanche
    given by a 2D array of 1's or 
    labels, as obtained using scipy.ndimage.label
    
    Parameters:
    ----------------
    labels : ndarray
    A 2D array with the cluster numbers
    as calculated from scipy.ndimage.label
    
    imageDir : string
    The direction of the avalanche motion
    Left <-> right
    Bottom <-> top

    edgeThickness : int
    the width of the frame around the image
    which is considered as the thickness of each edge
    
    fraction : float
    This is the minimum fraction of the size of the avalanche/cluster inside
    an edge (of thickness edgeThickness) with sets the avalanche/cluster
    as touching
    """
    et = edgeThickness
    if not fraction:
        fraction = 0.
    # Find first the 4 borders
    # Definition good for "Left_to_right"
    left = list(labels[0:et,:].flatten())
    right = list(labels[-et:,:].flatten())
    bottom = list(labels[:,0:et].flatten())
    top = list(labels[:,-et:].flatten())
    if imageDir=="Left_to_right":
        lrbt = left, right, bottom, top
    elif imageDir == "Right_to_left":
        lrbt = right, left, top, bottom
    elif imageDir == "Bottom_to_top":
        lrbt = bottom, top, right, left
    elif imageDir == "Top_to_bottom":
        lrbt = top, bottom, left, right
    else:
        raise ValueError, "avalanche direction not defined"
    # Find the sets
    # Select the labels contained in the edges
    #setLrbt = set(left+right+bottom+top)
    setLrbt = set(itertools.chain(*lrbt))
    # Remove the value 0 as it is not a cluster
    setLrbt.remove(0)
    maxLabel = labels.max()
    # Prepare a list with all '0000' labels
    list_Axy = ['0000']*maxLabel
    # Search for the Axy except for the A00
    for cluster in setLrbt: # iter over clusters touching the edges
        fraction_size = int(fraction * nd.sum(labels == cluster)) + 1
        list_Axy[cluster-1] = "".join([((edge.count(cluster) >= fraction_size) and '1' or '0') for edge in lrbt])
        #pixels_on_the_edge = "/".join([str(edge.count(cluster)) for edge in lrbt])
    return scipy.array(list_Axy)
def downsample(ar, fact):
	sx, sy = ar.shape
	X, Y = np.ogrid[0:sx, 0:sy]
	regions = sy/fact * (X/fact) + Y/fact
	res = ndimage.sum(ar, labels=regions, index=np.arange(regions.max() + 1))
	res.shape = (sx/fact, sy/fact)
	return res
Beispiel #30
0
    def largestObjectInMask(self, mask=None, saveMask=False):
        """Takes a numpy.uint8 array with 1s and 0s for values.  Labels each connected
        region of 1s with a different integer.  Determines the largest such connected
        region.  Discards all blocks except the largest, and returns the mask with only
        the largest object represented by 1s."""

        if mask==None:
            mask = self.mask

        # this is the part where all the magic is performed by scipy
        labeled, how_many_labels = ndimage.label(mask)

        # spit out an array listing the size of each labeled block
        sizes = ndimage.sum(mask, labeled, range(how_many_labels + 1))

        # find the label of the largest region
        max_label = list(sizes).index(max(sizes))

        # if you're not in the largest region, you get set to zero
        # if you are in the largest region, you get set to 1
        mask[labeled!=max_label]=0
        mask[labeled==max_label]=1

        mask = np.uint8(mask)

        if saveMask:
            self.mask = mask

        return mask
Beispiel #31
0
def test_sum03():
    for type in types:
        input = np.ones([], type)
        output = ndimage.sum(input)
        assert_almost_equal(output, 1.0)
Beispiel #32
0
def weightedregionprops(L, ncc, dfore):

    if DEBUG_TRACKINGSETTINGS:
        print 'in weightedregionprops, ncc = ' + str(
            ncc) + ', max(L) = ' + str(num.max(L)) + ', nnz(L) = ' + str(
                num.flatnonzero(L).shape) + ', sum(dfore) = ' + str(
                    num.sum(num.sum(dfore)))
    if DEBUG_TRACKINGSETTINGS:
        for l in range(1, num.max(L) + 1):
            print 'nnz(L == %d) = ' % l + str(num.alen(
                num.flatnonzero(L == l)))

    if ncc == 0:
        return []

    # all connected components
    index = range(1, ncc + 1)

    time0 = time.time()

    # create the unnormalized weight matrix
    w = dfore
    #w[L==0] = 0

    # compute the normalization terms
    z = num.array(meas.sum(w, L, index), ndmin=1)
    z[z == 0] = 1

    # compute the unnormalized centers
    cx = num.array(meas.sum(w * params.GRID.X, L, index), ndmin=1)
    cy = num.array(meas.sum(w * params.GRID.Y, L, index), ndmin=1)

    # normalize centers
    cx /= z
    cy /= z

    # compute unnormalized, uncentered variances
    cx2 = num.array(meas.sum(w * params.GRID.X2, L, index), ndmin=1)
    cy2 = num.array(meas.sum(w * params.GRID.Y2, L, index), ndmin=1)
    cxy = num.array(meas.sum(w * params.GRID.XY, L, index), ndmin=1)

    # normalize variances
    cx2 /= z
    cy2 /= z
    cxy /= z

    # center variances
    cx2 -= cx**2
    cy2 -= cy**2
    cxy -= cx * cy

    # create ellipses
    ellipses = []
    for i in range(len(cx)):
        # compute major, minor, angle from cov
        (sizeH, sizeW, angle) = cov2ell2(cx2[i], cy2[i], cxy[i])
        if (sizeH < .125) or num.isnan(sizeH):
            sizeH = .125
        if (sizeW < .125) or num.isnan(sizeW):
            sizeW = .125
        # compute area
        area = num.pi * sizeW * sizeH * 4
        ellipses.append(Ellipse(cx[i], cy[i], sizeW, sizeH, angle, area, -1))

    return ellipses
Beispiel #33
0
def test_sum10():
    labels = np.array([1, 0], bool)
    input = np.array([[1, 2], [3, 4]], bool)
    output = ndimage.sum(input, labels=labels)
    assert_almost_equal(output, 2.0)
Beispiel #34
0
def test_sum09():
    labels = np.array([1, 0], bool)
    for type in types:
        input = np.array([[1, 2], [3, 4]], type)
        output = ndimage.sum(input, labels=labels)
        assert_almost_equal(output, 4.0)
Beispiel #35
0
def isolateregions(binary_array, size_threshold=0, pad_size=5,
                   fill_hole=False, rel_size=0.1, morph_smooth=False):
    '''

    Labels regions in a boolean array and returns individual arrays for each
    region. Regions below a threshold can optionlly be removed. Small holes
    may also be filled in.

    Parameters
    ----------
    binary_array : numpy.ndarray
        A binary array of regions.
    size_threshold : int, optional
        Sets the pixel size on the size of regions.
    pad_size : int, optional
        Padding to be added to the individual arrays.
    fill_hole : int, optional
        Enables hole filling.
    rel_size : float or int, optional
        If < 1.0, sets the minimum size a hole must be relative to the area
        of the mask. Otherwise, this is the maximum number of pixels the hole
        must have to be deleted.
    morph_smooth : bool, optional
        Morphologically smooth the image using a binar opening and closing.

    Returns
    -------
    output_arrays : list
        Regions separated into individual arrays.
    num : int
        Number of filaments
    corners : list
        Contains the indices where each skeleton array was taken from
        the original.

    '''

    output_arrays = []
    corners = []

    # Label skeletons
    labels, num = nd.label(binary_array, eight_con())

    # Remove skeletons which have fewer pixels than the threshold.
    if size_threshold != 0:
        sums = nd.sum(binary_array, labels, range(1, num + 1))
        remove_fils = np.where(sums <= size_threshold)[0]
        for lab in remove_fils:
            binary_array[np.where(labels == lab + 1)] = 0

        # Relabel after deleting short skeletons.
        labels, num = nd.label(binary_array, eight_con())

    # Split each skeleton into its own array.
    for n in range(1, num + 1):
        x, y = np.where(labels == n)
        # Make an array shaped to the skeletons size and padded on each edge
        # the +1 is because, e.g., range(0, 5) only has 5 elements, but the
        # indices we're using are range(0, 6)
        shapes = (x.max() - x.min() + 2 * pad_size,
                  y.max() - y.min() + 2 * pad_size)
        eachfil = np.zeros(shapes)
        eachfil[x - x.min() + pad_size, y - y.min() + pad_size] = 1
        # Fill in small holes
        if fill_hole:
            eachfil = _fix_small_holes(eachfil, rel_size=rel_size)
        if morph_smooth:
            eachfil = nd.binary_opening(eachfil, np.ones((3, 3)))
            eachfil = nd.binary_closing(eachfil, np.ones((3, 3)))
        output_arrays.append(eachfil)
        # Keep the coordinates from the original image
        lower = (x.min() - pad_size, y.min() - pad_size)
        upper = (x.max() + pad_size + 1, y.max() + pad_size + 1)
        corners.append([lower, upper])

    return output_arrays, num, corners
Beispiel #36
0
    def run(self, workspace):
        """Run the module on an image set"""

        object_name = self.object_name.value
        remaining_object_name = self.remaining_objects.value
        original_objects = workspace.object_set.get_objects(object_name)

        if self.mask_choice == MC_IMAGE:
            mask = workspace.image_set.get_image(self.masking_image.value,
                                                 must_be_binary=True)
            mask = mask.pixel_data
        else:
            masking_objects = workspace.object_set.get_objects(
                self.masking_objects.value)
            mask = masking_objects.segmented > 0
        if self.wants_inverted_mask:
            mask = ~mask
        #
        # Load the labels
        #
        labels = original_objects.segmented.copy()
        nobjects = np.max(labels)
        #
        # Resize the mask to cover the objects
        #
        mask, m1 = cpo.size_similarly(labels, mask)
        mask[~m1] = False
        #
        # Apply the mask according to the overlap choice.
        #
        if nobjects == 0:
            pass
        elif self.overlap_choice == P_MASK:
            labels = labels * mask
        else:
            pixel_counts = fix(
                scind.sum(mask, labels,
                          np.arange(1, nobjects + 1, dtype=np.int32)))
            if self.overlap_choice == P_KEEP:
                keep = pixel_counts > 0
            else:
                total_pixels = fix(
                    scind.sum(
                        np.ones(labels.shape),
                        labels,
                        np.arange(1, nobjects + 1, dtype=np.int32),
                    ))
                if self.overlap_choice == P_REMOVE:
                    keep = pixel_counts == total_pixels
                elif self.overlap_choice == P_REMOVE_PERCENTAGE:
                    fraction = self.overlap_fraction.value
                    keep = pixel_counts / total_pixels >= fraction
                else:
                    raise NotImplementedError(
                        "Unknown overlap-handling choice: %s",
                        self.overlap_choice.value)
            keep = np.hstack(([False], keep))
            labels[~keep[labels]] = 0
        #
        # Renumber the labels matrix if requested
        #
        if self.retain_or_renumber == R_RENUMBER:
            unique_labels = np.unique(labels[labels != 0])
            indexer = np.zeros(nobjects + 1, int)
            indexer[unique_labels] = np.arange(1, len(unique_labels) + 1)
            labels = indexer[labels]
            parent_objects = unique_labels
        else:
            parent_objects = np.arange(1, nobjects + 1)
        #
        # Add the objects
        #
        remaining_objects = cpo.Objects()
        remaining_objects.segmented = labels
        remaining_objects.unedited_segmented = original_objects.unedited_segmented
        workspace.object_set.add_objects(remaining_objects,
                                         remaining_object_name)
        #
        # Add measurements
        #
        m = workspace.measurements
        m.add_measurement(
            remaining_object_name,
            cellprofiler_core.measurement.FF_PARENT % object_name,
            parent_objects,
        )
        if np.max(original_objects.segmented) == 0:
            child_count = np.array([], int)
        else:
            child_count = fix(
                scind.sum(
                    labels,
                    original_objects.segmented,
                    np.arange(1, nobjects + 1, dtype=np.int32),
                ))
            child_count = (child_count > 0).astype(int)
        m.add_measurement(
            object_name,
            cellprofiler_core.measurement.FF_CHILDREN_COUNT %
            remaining_object_name,
            child_count,
        )
        if self.retain_or_renumber == R_RETAIN:
            remaining_object_count = nobjects
        else:
            remaining_object_count = len(unique_labels)
        I.add_object_count_measurements(m, remaining_object_name,
                                        remaining_object_count)
        I.add_object_location_measurements(m, remaining_object_name, labels)
        #
        # Save the input, mask and output images for display
        #
        if self.show_window:
            workspace.display_data.original_labels = original_objects.segmented
            workspace.display_data.final_labels = labels
            workspace.display_data.mask = mask
Beispiel #37
0
    def run_image_pair_objects(self, workspace, first_image_name,
                               second_image_name, object_name):
        '''Calculate per-object correlations between intensities in two images'''
        first_image = workspace.image_set.get_image(first_image_name,
                                                    must_be_grayscale=True)
        second_image = workspace.image_set.get_image(second_image_name,
                                                     must_be_grayscale=True)
        objects = workspace.object_set.get_objects(object_name)
        #
        # Crop both images to the size of the labels matrix
        #
        labels = objects.segmented
        try:
            first_pixels = objects.crop_image_similarly(first_image.pixel_data)
            first_mask = objects.crop_image_similarly(first_image.mask)
        except ValueError:
            first_pixels, m1 = cpo.size_similarly(labels, first_image.pixel_data)
            first_mask, m1 = cpo.size_similarly(labels, first_image.mask)
            first_mask[~m1] = False
        try:
            second_pixels = objects.crop_image_similarly(second_image.pixel_data)
            second_mask = objects.crop_image_similarly(second_image.mask)
        except ValueError:
            second_pixels, m1 = cpo.size_similarly(labels, second_image.pixel_data)
            second_mask, m1 = cpo.size_similarly(labels, second_image.mask)
            second_mask[~m1] = False
        mask = ((labels > 0) & first_mask & second_mask)
        first_pixels = first_pixels[mask]
        second_pixels = second_pixels[mask]
        labels = labels[mask]
        result = []
        first_pixel_data = first_image.pixel_data
        first_mask = first_image.mask
        first_pixel_count = np.product(first_pixel_data.shape)
        second_pixel_data = second_image.pixel_data
        second_mask = second_image.mask
        second_pixel_count = np.product(second_pixel_data.shape)
        #
        # Crop the larger image similarly to the smaller one
        #
        if first_pixel_count < second_pixel_count:
            second_pixel_data = first_image.crop_image_similarly(second_pixel_data)
            second_mask = first_image.crop_image_similarly(second_mask)
        elif second_pixel_count < first_pixel_count:
            first_pixel_data = second_image.crop_image_similarly(first_pixel_data)
            first_mask = second_image.crop_image_similarly(first_mask)
        mask = (first_mask & second_mask &
                (~ np.isnan(first_pixel_data)) &
                (~ np.isnan(second_pixel_data)))
        if np.any(mask):
            #
            # Perform the correlation, which returns:
            # [ [ii, ij],
            #   [ji, jj] ]
            #
            fi = first_pixel_data[mask]
            si = second_pixel_data[mask]

        n_objects = objects.count
        # Handle case when both images for the correlation are completely masked out

        if n_objects == 0:
            corr = np.zeros((0,))
            overlap = np.zeros((0,))
            K1 = np.zeros((0,))
            K2 = np.zeros((0,))
            M1 = np.zeros((0,))
            M2 = np.zeros((0,))
            RWC1 = np.zeros((0,))
            RWC2 = np.zeros((0,))
            C1 = np.zeros((0,))
            C2 = np.zeros((0,))
        elif np.where(mask)[0].__len__() == 0:
            corr = np.zeros((n_objects,))
            corr[:] = np.NaN
            overlap = K1 = K2 = M1 = M2 = RWC1 = RWC2 = C1 = C2 = corr
        else:
            #
            # The correlation is sum((x-mean(x))(y-mean(y)) /
            #                         ((n-1) * std(x) *std(y)))
            #
            lrange = np.arange(n_objects, dtype=np.int32) + 1
            area = fix(scind.sum(np.ones_like(labels), labels, lrange))
            mean1 = fix(scind.mean(first_pixels, labels, lrange))
            mean2 = fix(scind.mean(second_pixels, labels, lrange))
            #
            # Calculate the standard deviation times the population.
            #
            std1 = np.sqrt(fix(scind.sum((first_pixels - mean1[labels - 1]) ** 2,
                                         labels, lrange)))
            std2 = np.sqrt(fix(scind.sum((second_pixels - mean2[labels - 1]) ** 2,
                                         labels, lrange)))
            x = first_pixels - mean1[labels - 1]  # x - mean(x)
            y = second_pixels - mean2[labels - 1]  # y - mean(y)
            corr = fix(scind.sum(x * y / (std1[labels - 1] * std2[labels - 1]),
                                 labels, lrange))
            # Explicitly set the correlation to NaN for masked objects
            corr[scind.sum(1, labels, lrange) == 0] = np.NaN
            result += [
                [first_image_name, second_image_name, object_name, "Mean Correlation coeff", "%.3f" % np.mean(corr)],
                [first_image_name, second_image_name, object_name, "Median Correlation coeff",
                 "%.3f" % np.median(corr)],
                [first_image_name, second_image_name, object_name, "Min Correlation coeff", "%.3f" % np.min(corr)],
                [first_image_name, second_image_name, object_name, "Max Correlation coeff", "%.3f" % np.max(corr)]]

            # Threshold as percentage of maximum intensity of objects in each channel
            tff = (self.thr.value / 100) * fix(scind.maximum(first_pixels, labels, lrange))
            tss = (self.thr.value / 100) * fix(scind.maximum(second_pixels, labels, lrange))

            combined_thresh = (first_pixels >= tff[labels - 1]) & (second_pixels >= tss[labels - 1])
            fi_thresh = first_pixels[combined_thresh]
            si_thresh = second_pixels[combined_thresh]
            tot_fi_thr = scind.sum(first_pixels[first_pixels >= tff[labels - 1]], labels[first_pixels >= tff[labels - 1]],
                                   lrange)
            tot_si_thr = scind.sum(second_pixels[second_pixels >= tss[labels - 1]],
                                   labels[second_pixels >= tss[labels - 1]], lrange)

            nonZero = (fi > 0) | (si > 0)
            xvar = np.var(fi[nonZero], axis=0, ddof=1)
            yvar = np.var(si[nonZero], axis=0, ddof=1)

            xmean = np.mean(fi[nonZero], axis=0)
            ymean = np.mean(si[nonZero], axis=0)

            z = fi[nonZero] + si[nonZero]
            zvar = np.var(z, axis=0, ddof=1)

            covar = 0.5 * (zvar - (xvar + yvar))

            denom = 2 * covar
            num = (yvar - xvar) + np.sqrt((yvar - xvar) * (yvar - xvar) + 4 * (covar * covar))
            a = (num / denom)
            b = (ymean - a * xmean)

            i = 1
            while i > 0.003921568627:
                thr_fi_c = i
                thr_si_c = (a * i) + b
                combt = (fi < thr_fi_c) | (si < thr_si_c)
                costReg = scistat.pearsonr(fi[combt], si[combt])
                if costReg[0] <= 0:
                    break
                i = i - 0.003921568627

            # Costes' thershold for entire image is applied to each object
            fi_above_thr = first_pixels > thr_fi_c
            si_above_thr = second_pixels > thr_si_c
            combined_thresh_c = fi_above_thr & si_above_thr
            fi_thresh_c = first_pixels[combined_thresh_c]
            si_thresh_c = second_pixels[combined_thresh_c]
            if np.any(fi_above_thr):
                tot_fi_thr_c = scind.sum(first_pixels[first_pixels >= thr_fi_c], labels[first_pixels >= thr_fi_c], lrange)
            else:
                tot_fi_thr_c = np.zeros(len(lrange))
            if np.any(si_above_thr):
                tot_si_thr_c = scind.sum(second_pixels[second_pixels >= thr_si_c], labels[second_pixels >= thr_si_c],
                                         lrange)
            else:
                tot_si_thr_c = np.zeros(len(lrange))

            # Manders Coefficient
            M1 = np.zeros(len(lrange))
            M2 = np.zeros(len(lrange))

            if np.any(combined_thresh):
                M1 = np.array(scind.sum(fi_thresh,labels[combined_thresh],lrange)) / np.array(tot_fi_thr)
                M2 = np.array(scind.sum(si_thresh,labels[combined_thresh],lrange)) / np.array(tot_si_thr)
            result += [[first_image_name, second_image_name, object_name,"Mean Manders coeff","%.3f"%np.mean(M1)],
                       [first_image_name, second_image_name, object_name,"Median Manders coeff","%.3f"%np.median(M1)],
                       [first_image_name, second_image_name, object_name,"Min Manders coeff","%.3f"%np.min(M1)],
                       [first_image_name, second_image_name, object_name,"Max Manders coeff","%.3f"%np.max(M1)]]
            result += [[second_image_name, first_image_name, object_name,"Mean Manders coeff","%.3f"%np.mean(M2)],
                       [second_image_name, first_image_name, object_name,"Median Manders coeff","%.3f"%np.median(M2)],
                       [second_image_name, first_image_name, object_name,"Min Manders coeff","%.3f"%np.min(M2)],
                       [second_image_name, first_image_name, object_name,"Max Manders coeff","%.3f"%np.max(M2)]]

            # RWC Coefficient
            RWC1 = np.zeros(len(lrange))
            RWC2 = np.zeros(len(lrange))
            [Rank1] = np.lexsort(([labels], [first_pixels]))
            [Rank2] = np.lexsort(([labels], [second_pixels]))
            Rank1_U = np.hstack([[False], first_pixels[Rank1[:-1]] != first_pixels[Rank1[1:]]])
            Rank2_U = np.hstack([[False], second_pixels[Rank2[:-1]] != second_pixels[Rank2[1:]]])
            Rank1_S = np.cumsum(Rank1_U)
            Rank2_S = np.cumsum(Rank2_U)
            Rank_im1 = np.zeros(first_pixels.shape, dtype=int)
            Rank_im2 = np.zeros(second_pixels.shape, dtype=int)
            Rank_im1[Rank1] = Rank1_S
            Rank_im2[Rank2] = Rank2_S

            R = max(Rank_im1.max(), Rank_im2.max()) + 1
            Di = abs(Rank_im1 - Rank_im2)
            weight = (R - Di) * 1.0 / R
            weight_thresh = weight[combined_thresh]
            if np.any(combined_thresh_c):
                RWC1 = np.array(scind.sum(fi_thresh * weight_thresh, labels[combined_thresh], lrange)) / np.array(
                        tot_fi_thr)
                RWC2 = np.array(scind.sum(si_thresh * weight_thresh, labels[combined_thresh], lrange)) / np.array(
                        tot_si_thr)

            result += [[first_image_name, second_image_name, object_name, "Mean RWC coeff", "%.3f" % np.mean(RWC1)],
                       [first_image_name, second_image_name, object_name, "Median RWC coeff", "%.3f" % np.median(RWC1)],
                       [first_image_name, second_image_name, object_name, "Min RWC coeff", "%.3f" % np.min(RWC1)],
                       [first_image_name, second_image_name, object_name, "Max RWC coeff", "%.3f" % np.max(RWC1)]]
            result += [[second_image_name, first_image_name, object_name, "Mean RWC coeff", "%.3f" % np.mean(RWC2)],
                       [second_image_name, first_image_name, object_name, "Median RWC coeff", "%.3f" % np.median(RWC2)],
                       [second_image_name, first_image_name, object_name, "Min RWC coeff", "%.3f" % np.min(RWC2)],
                       [second_image_name, first_image_name, object_name, "Max RWC coeff", "%.3f" % np.max(RWC2)]]

            # Costes Automated Threshold
            C1 = np.zeros(len(lrange))
            C2 = np.zeros(len(lrange))
            if np.any(combined_thresh_c):
                C1 = np.array(scind.sum(fi_thresh_c,labels[combined_thresh_c],lrange)) / np.array(tot_fi_thr_c)
                C2 = np.array(scind.sum(si_thresh_c,labels[combined_thresh_c],lrange)) / np.array(tot_si_thr_c)
            result += [[first_image_name, second_image_name, object_name,"Mean Manders coeff (Costes)","%.3f"%np.mean(C1)],
                       [first_image_name, second_image_name, object_name,"Median Manders coeff (Costes)","%.3f"%np.median(C1)],
                       [first_image_name, second_image_name, object_name,"Min Manders coeff (Costes)","%.3f"%np.min(C1)],
                       [first_image_name, second_image_name, object_name,"Max Manders coeff (Costes)","%.3f"%np.max(C1)]
                       ]
            result += [[second_image_name, first_image_name, object_name,"Mean Manders coeff (Costes)","%.3f"%np.mean(C2)],
                       [second_image_name, first_image_name, object_name,"Median Manders coeff (Costes)","%.3f"%np.median(C2)],
                       [second_image_name, first_image_name, object_name,"Min Manders coeff (Costes)","%.3f"%np.min(C2)],
                       [second_image_name, first_image_name, object_name,"Max Manders coeff (Costes)","%.3f"%np.max(C2)]
                       ]

            # Overlap Coefficient
            fpsq = scind.sum(first_pixels[combined_thresh] ** 2, labels[combined_thresh], lrange)
            spsq = scind.sum(second_pixels[combined_thresh] ** 2, labels[combined_thresh], lrange)
            pdt = np.sqrt(np.array(fpsq) * np.array(spsq))

            if np.any(combined_thresh):
                overlap = fix(
                        scind.sum(first_pixels[combined_thresh] * second_pixels[combined_thresh],
                                  labels[combined_thresh],
                                  lrange) / pdt)
                K1 = fix((scind.sum(first_pixels[combined_thresh] * second_pixels[combined_thresh],
                                    labels[combined_thresh], lrange)) / (np.array(fpsq)))
                K2 = fix(
                        scind.sum(first_pixels[combined_thresh] * second_pixels[combined_thresh],
                                  labels[combined_thresh],
                                  lrange) / np.array(spsq))
            else:
                overlap = K1 = K2 = np.zeros(len(lrange))
            result += [
                [first_image_name, second_image_name, object_name, "Mean Overlap coeff", "%.3f" % np.mean(overlap)],
                [first_image_name, second_image_name, object_name, "Median Overlap coeff", "%.3f" % np.median(overlap)],
                [first_image_name, second_image_name, object_name, "Min Overlap coeff", "%.3f" % np.min(overlap)],
                [first_image_name, second_image_name, object_name, "Max Overlap coeff", "%.3f" % np.max(overlap)]]

        measurement = ("Correlation_Correlation_%s_%s" %
                       (first_image_name, second_image_name))
        overlap_measurement = (F_OVERLAP_FORMAT % (first_image_name,
                                                   second_image_name))
        k_measurement_1 = (F_K_FORMAT % (first_image_name,
                                         second_image_name))
        k_measurement_2 = (F_K_FORMAT % (second_image_name,
                                         first_image_name))
        manders_measurement_1 = (F_MANDERS_FORMAT % (first_image_name,
                                                     second_image_name))
        manders_measurement_2 = (F_MANDERS_FORMAT % (second_image_name,
                                                     first_image_name))
        rwc_measurement_1 = (F_RWC_FORMAT % (first_image_name,
                                             second_image_name))
        rwc_measurement_2 = (F_RWC_FORMAT % (second_image_name,
                                             first_image_name))
        costes_measurement_1 = (F_COSTES_FORMAT % (first_image_name,
                                                   second_image_name))
        costes_measurement_2 = (F_COSTES_FORMAT % (second_image_name,
                                                   first_image_name))

        workspace.measurements.add_measurement(object_name, measurement, corr)
        workspace.measurements.add_measurement(object_name, overlap_measurement, overlap)
        workspace.measurements.add_measurement(object_name, k_measurement_1, K1)
        workspace.measurements.add_measurement(object_name, k_measurement_2, K2)
        workspace.measurements.add_measurement(object_name, manders_measurement_1, M1)
        workspace.measurements.add_measurement(object_name, manders_measurement_2, M2)
        workspace.measurements.add_measurement(object_name, rwc_measurement_1, RWC1)
        workspace.measurements.add_measurement(object_name, rwc_measurement_2, RWC2)
        workspace.measurements.add_measurement(object_name, costes_measurement_1, C1)
        workspace.measurements.add_measurement(object_name, costes_measurement_2, C2)

        if n_objects == 0:
            return [[first_image_name, second_image_name, object_name,
                     "Mean correlation", "-"],
                    [first_image_name, second_image_name, object_name,
                     "Median correlation", "-"],
                    [first_image_name, second_image_name, object_name,
                     "Min correlation", "-"],
                    [first_image_name, second_image_name, object_name,
                     "Max correlation", "-"]]
        else:
            return result
Beispiel #38
0
def test_sum02():
    for type in types:
        input = np.zeros([0, 4], type)
        output = ndimage.sum(input)
        assert_equal(output, 0.0)
Beispiel #39
0
def test_sum01():
    for type in types:
        input = np.array([], type)
        output = ndimage.sum(input)
        assert_equal(output, 0.0)
 def measure_zernike(self, pixels, labels, n, m):
     # I'll put some documentation in here to explain what it does.
     # If someone ever wants to call it, their editor might display
     # the documentation.
     '''Measure the intensity of the image with Zernike (N, M)
     
     pixels - the intensity image to be measured
     labels - the labels matrix that labels each object with an integer
     n, m - the Zernike coefficients.
     
     See http://en.wikipedia.org/wiki/Zernike_polynomials for an
     explanation of the Zernike polynomials
     '''
     #
     # The strategy here is to operate on the whole array instead
     # of operating on one object at a time. The most important thing
     # is to avoid having to run the Python interpreter once per pixel
     # in the image and the second most important is to avoid running
     # it per object in case there are hundreds of objects.
     #
     # We play lots of indexing tricks here to operate on the whole image.
     # I'll try to explain some - hopefully, you can reuse.
     #
     # You could move the calculation of the minimum enclosing circle
     # outside of this function. The function gets called more than
     # 10 times, so the same calculation is performed 10 times.
     # It would make the code a little more confusing, so I'm leaving
     # it as-is.
     ###########################################
     #
     # The minimum enclosing circle (MEC) is the smallest circle that
     # will fit around the object. We get the centers and radii of
     # all of the objects at once. You'll see how that lets us
     # compute the X and Y position of each pixel in a label all at
     # one go.
     #
     # First, get an array that lists the whole range of indexes in
     # the labels matrix.
     #
     indexes = np.arange(1, np.max(labels)+1,dtype=np.int32)
     #
     # Then ask for the minimum_enclosing_circle for each object named
     # in those indexes. MEC returns the i and j coordinate of the center
     # and the radius of the circle and that defines the circle entirely.
     #
     centers, radius = minimum_enclosing_circle(labels, indexes)
     center_x = centers[:, 1]
     center_y = centers[:, 0]
     #
     # Make up fake values for 0 (the background). This lets us do our
     # indexing tricks. Really, we're going to ignore the background,
     # but we want to do the indexing without ignoring the background
     # because that's easier.
     #
     center_x = np.hstack([[0], center_x])
     center_y = np.hstack([[0], center_y])
     radius = np.hstack([[1], radius])
     #
     # Now get one array that's the y coordinate of each pixel and one
     # that's the x coordinate. This might look stupid and wasteful,
     # but these "arrays" are never actually realized and made into
     # real memory.
     #
     y, x = np.mgrid[0:labels.shape[0], 0:labels.shape[1]]
     #
     # Get the x and y coordinates relative to the object centers.
     # This uses Numpy broadcasting. For each pixel, we use the
     # value in the labels matrix as an index into the appropriate
     # one-dimensional array. So we get the value for that object.
     #
     y -= center_y[labels]
     x -= center_x[labels]
     #
     # Zernikes take x and y values from zero to one. We scale the
     # integer coordinate values by dividing them by the radius of
     # the circle. Again, we use the indexing trick to look up the
     # values for each object.
     #
     y = y.astype(float) / radius[labels]
     x = x.astype(float) / radius[labels]
     #
     #################################
     #
     # ZERNIKE POLYNOMIALS
     #
     # Now we can get Zernike polynomials per-pixel where each pixel
     # value is calculated according to its object's MEC.
     #
     # We use a mask of all of the non-zero labels so the calculation
     # runs a little faster.
     #
     zernike_polynomial = construct_zernike_polynomials(
         x, y, np.array([ [ n, m ]]))
     #
     # Multiply the Zernike polynomial by the image to dissect
     # the image by the Zernike basis set.
     #
     output_pixels = pixels * zernike_polynomial[:,:,0]
     #
     # The zernike polynomial is a complex number. We get a power
     # spectrum here to combine the real and imaginary parts
     #
     output_pixels = np.sqrt(output_pixels * output_pixels.conjugate())
     #
     # Finally, we use Scipy to sum the intensities. Scipy has different
     # versions with different quirks. The "fix" function takes all
     # of that into account.
     #
     # The sum function calculates the sum of the pixel values for
     # each pixel in an object, using the labels matrix to name
     # the pixels in an object
     #
     result = fix(scind.sum(output_pixels.real, labels, indexes))
     #
     # And we're done! Did you like it? Did you get it?
     #
     return result
Beispiel #41
0
def skeleton_length(skeleton):
    '''
    Length finding via morphological operators. We use the differences in
    connectivity between 4 and 8-connected to split regions. Connections
    between 4 and 8-connected regions are found using a series of hit-miss
    operators.

    The inputted skeleton MUST have no intersections otherwise the returned
    length will not be correct!

    Parameters
    ----------
    skeleton : numpy.ndarray
        Array containing the skeleton.

    Returns
    -------
    length : float
        Length of the skeleton.

    '''

    # 4-connected labels
    four_labels = nd.label(skeleton)[0]

    four_sizes = nd.sum(skeleton, four_labels, range(np.max(four_labels) + 1))

    # Lengths is the number of pixels minus number of objects with more
    # than 1 pixel.
    four_length = np.sum(
        four_sizes[four_sizes > 1]) - len(four_sizes[four_sizes > 1])

    # Find pixels which a 4-connected and subtract them off the skeleton

    four_objects = np.where(four_sizes > 1)[0]

    skel_copy = copy.copy(skeleton)
    for val in four_objects:
        skel_copy[np.where(four_labels == val)] = 0

    # Remaining pixels are only 8-connected
    # Lengths is same as before, multiplied by sqrt(2)

    eight_labels = nd.label(skel_copy, eight_con())[0]

    eight_sizes = nd.sum(
        skel_copy, eight_labels, range(np.max(eight_labels) + 1))

    eight_length = (
                       np.sum(eight_sizes) - np.max(eight_labels)) * np.sqrt(2)

    # If there are no 4-connected pixels, we don't need the hit-miss portion.
    if four_length == 0.0:
        conn_length = 0.0

    else:

        store = np.zeros(skeleton.shape)

        # Loop through the 4 rotations of the structuring elements
        for k in range(0, 4):
            hm1 = nd.binary_hit_or_miss(
                skeleton, structure1=np.rot90(struct1, k=k))
            store += hm1

            hm2 = nd.binary_hit_or_miss(
                skeleton, structure1=np.rot90(struct2, k=k))
            store += hm2

            hm_check3 = nd.binary_hit_or_miss(
                skeleton, structure1=np.rot90(check3, k=k))
            store -= hm_check3

            if k <= 1:
                hm_check1 = nd.binary_hit_or_miss(
                    skeleton, structure1=np.rot90(check1, k=k))
                store -= hm_check1

                hm_check2 = nd.binary_hit_or_miss(
                    skeleton, structure1=np.rot90(check2, k=k))
                store -= hm_check2

        conn_length = np.sqrt(2) * \
                      np.sum(np.sum(store, axis=1), axis=0)  # hits

    return conn_length + eight_length + four_length
Beispiel #42
0
def _fix_small_holes(mask_array, rel_size=0.1):
    '''
    Helper function to remove only small holes within a masked region.

    Parameters
    ----------
    mask_array : numpy.ndarray
        Array containing the masked region.

    rel_size : float, optional
        If < 1.0, sets the minimum size a hole must be relative to the area
        of the mask. Otherwise, this is the maximum number of pixels the hole
        must have to be deleted.

    Returns
    -------
    mask_array : numpy.ndarray
        Altered array.
    '''

    if rel_size <= 0.0:
        raise ValueError("rel_size must be positive.")
    elif rel_size > 1.0:
        pixel_flag = True
    else:
        pixel_flag = False

    # Find the region area
    reg_area = len(np.where(mask_array == 1)[0])

    # Label the holes
    holes = np.logical_not(mask_array).astype(float)
    lab_holes, n_holes = nd.label(holes, eight_con())

    # If no holes, return
    if n_holes == 1:
        return mask_array

    # Ignore area outside of the region.
    out_label = lab_holes[0, 0]
    # Set size to be just larger than the region. Thus it can never be
    # deleted.
    holes[np.where(lab_holes == out_label)] = reg_area + 1.

    # Sum up the regions and find holes smaller than the threshold.
    sums = nd.sum(holes, lab_holes, range(1, n_holes + 1))
    if pixel_flag:  # Use number of pixels
        delete_holes = np.where(sums < rel_size)[0]
    else:  # Use relative size of holes.
        delete_holes = np.where(sums / reg_area < rel_size)[0]

    # Return if there is nothing to delete.
    if delete_holes == []:
        return mask_array

    # Add one to take into account 0 in list if object label 1.
    delete_holes += 1
    for label in delete_holes:
        mask_array[np.where(lab_holes == label)] = 1

    return mask_array
                        axis=2).astype(uint8)

    ## Convert to black white image. The threshold here is currently set to 100.
    falseImage[falseImage > 100] = 255
    falseImage[falseImage < 101] = 0

    ## Remove spurs from the data
    falseImage = ndimage.binary_opening(falseImage)
    falseImage = ndimage.binary_closing(falseImage).astype(uint8)

    ## Further clean image by applying Gaussian filter
    falseImage = ndimage.gaussian_filter(falseImage, sigma=1 / (2.0))

    ## Label all blobs in the image
    label_im, nb_labels = ndimage.label(falseImage)
    sizes = ndimage.sum(falseImage, label_im, range(nb_labels + 1))

    ## Remove all blobs that have a surface area less than 1000 pixels
    mask_size = sizes < max(sizes)
    max_id = max(enumerate(sizes), key=lambda x: x[1])[0]
    mask_size = sizes < 1000
    remove_pixel = mask_size[label_im]

    ## Find the main object in the scene. This is the larges blob.
    main_object = sizes < max(sizes) - 1
    get_pixels = main_object[label_im]
    label_im[remove_pixel] = 0
    data[get_pixels] = [0, 0, 0]

    ## Highlight main object in rgb
    label_im[label_im > 0] = 255
Beispiel #44
0
def test_sum04():
    for type in types:
        input = np.array([1, 2], type)
        output = ndimage.sum(input)
        assert_almost_equal(output, 3.0)
    def run(self, workspace):
        objects = workspace.object_set.get_objects(self.object_name.value)
        dimensions = len(objects.shape)
        assert isinstance(objects, cpo.Objects)
        has_pixels = objects.areas > 0
        labels = objects.small_removed_segmented
        kept_labels = objects.segmented
        neighbor_objects = workspace.object_set.get_objects(
            self.neighbors_name.value)
        assert isinstance(neighbor_objects, cpo.Objects)
        neighbor_labels = neighbor_objects.small_removed_segmented
        #
        # Need to add in labels touching border.
        #
        unedited_segmented = neighbor_objects.unedited_segmented
        touching_border = np.zeros(np.max(unedited_segmented) + 1, bool)
        touching_border[unedited_segmented[0, :]] = True
        touching_border[unedited_segmented[-1, :]] = True
        touching_border[unedited_segmented[:, 0]] = True
        touching_border[unedited_segmented[:, -1]] = True
        touching_border[0] = False
        touching_border_mask = touching_border[unedited_segmented]
        nobjects = np.max(labels)
        nkept_objects = len(objects.indices)
        nneighbors = np.max(neighbor_labels)
        if np.any(touching_border) and np.all(
                ~touching_border_mask[neighbor_labels != 0]):
            # Add the border labels if any were excluded
            touching_border_object_number = np.cumsum(
                touching_border) + np.max(neighbor_labels)
            touching_border_mask = touching_border_mask & (neighbor_labels
                                                           == 0)
            neighbor_labels = neighbor_labels.copy().astype(np.int32)
            neighbor_labels[
                touching_border_mask] = touching_border_object_number[
                    unedited_segmented[touching_border_mask]]

        _, object_numbers = objects.relate_labels(labels, kept_labels)
        if self.neighbors_are_objects:
            neighbor_numbers = object_numbers
            neighbor_has_pixels = has_pixels
        else:
            _, neighbor_numbers = neighbor_objects.relate_labels(
                neighbor_labels, neighbor_objects.segmented)
            neighbor_has_pixels = (np.bincount(
                neighbor_objects.small_removed_segmented.ravel())[1:] > 0)
        neighbor_count = np.zeros((nobjects, ))
        pixel_count = np.zeros((nobjects, ))
        first_object_number = np.zeros((nobjects, ), int)
        second_object_number = np.zeros((nobjects, ), int)
        first_x_vector = np.zeros((nobjects, ))
        second_x_vector = np.zeros((nobjects, ))
        first_y_vector = np.zeros((nobjects, ))
        second_y_vector = np.zeros((nobjects, ))
        angle = np.zeros((nobjects, ))
        percent_touching = np.zeros((nobjects, ))
        expanded_labels = None
        if self.distance_method == D_EXPAND:
            # Find the i,j coordinates of the nearest foreground point
            # to every background point
            if dimensions == 2:
                i, j = scind.distance_transform_edt(labels == 0,
                                                    return_distances=False,
                                                    return_indices=True)
                # Assign each background pixel to the label of its nearest
                # foreground pixel. Assign label to label for foreground.
                labels = labels[i, j]
            else:
                k, i, j = scind.distance_transform_edt(labels == 0,
                                                       return_distances=False,
                                                       return_indices=True)
                labels = labels[k, i, j]
            expanded_labels = labels  # for display
            distance = 1  # dilate once to make touching edges overlap
            scale = S_EXPANDED
            if self.neighbors_are_objects:
                neighbor_labels = labels.copy()
        elif self.distance_method == D_WITHIN:
            distance = self.distance.value
            scale = str(distance)
        elif self.distance_method == D_ADJACENT:
            distance = 1
            scale = S_ADJACENT
        else:
            raise ValueError("Unknown distance method: %s" %
                             self.distance_method.value)
        if nneighbors > (1 if self.neighbors_are_objects else 0):
            first_objects = []
            second_objects = []
            object_indexes = np.arange(nobjects, dtype=np.int32) + 1
            #
            # First, compute the first and second nearest neighbors,
            # and the angles between self and the first and second
            # nearest neighbors
            #
            ocenters = centers_of_labels(
                objects.small_removed_segmented).transpose()
            ncenters = centers_of_labels(
                neighbor_objects.small_removed_segmented).transpose()
            areas = fix(
                scind.sum(np.ones(labels.shape), labels, object_indexes))
            perimeter_outlines = outline(labels)
            perimeters = fix(
                scind.sum(np.ones(labels.shape), perimeter_outlines,
                          object_indexes))

            i, j = np.mgrid[0:nobjects, 0:nneighbors]
            distance_matrix = np.sqrt((ocenters[i, 0] - ncenters[j, 0])**2 +
                                      (ocenters[i, 1] - ncenters[j, 1])**2)
            #
            # order[:,0] should be arange(nobjects)
            # order[:,1] should be the nearest neighbor
            # order[:,2] should be the next nearest neighbor
            #
            if distance_matrix.shape[1] == 1:
                # a little buggy, lexsort assumes that a 2-d array of
                # second dimension = 1 is a 1-d array
                order = np.zeros(distance_matrix.shape, int)
            else:
                order = np.lexsort([distance_matrix])
            first_neighbor = 1 if self.neighbors_are_objects else 0
            first_object_index = order[:, first_neighbor]
            first_x_vector = ncenters[first_object_index, 1] - ocenters[:, 1]
            first_y_vector = ncenters[first_object_index, 0] - ocenters[:, 0]
            if nneighbors > first_neighbor + 1:
                second_object_index = order[:, first_neighbor + 1]
                second_x_vector = ncenters[second_object_index,
                                           1] - ocenters[:, 1]
                second_y_vector = ncenters[second_object_index,
                                           0] - ocenters[:, 0]
                v1 = np.array((first_x_vector, first_y_vector))
                v2 = np.array((second_x_vector, second_y_vector))
                #
                # Project the unit vector v1 against the unit vector v2
                #
                dot = np.sum(v1 * v2, 0) / np.sqrt(
                    np.sum(v1**2, 0) * np.sum(v2**2, 0))
                angle = np.arccos(dot) * 180.0 / np.pi

            # Make the structuring element for dilation
            if dimensions == 2:
                strel = strel_disk(distance)
            else:
                strel = skimage.morphology.ball(distance)
            #
            # A little bigger one to enter into the border with a structure
            # that mimics the one used to create the outline
            #
            if dimensions == 2:
                strel_touching = strel_disk(distance + 0.5)
            else:
                strel_touching = skimage.morphology.ball(distance + 0.5)
            #
            # Get the extents for each object and calculate the patch
            # that excises the part of the image that is "distance"
            # away
            if dimensions == 2:
                i, j = np.mgrid[0:labels.shape[0], 0:labels.shape[1]]
                min_i, max_i, min_i_pos, max_i_pos = scind.extrema(
                    i, labels, object_indexes)
                min_j, max_j, min_j_pos, max_j_pos = scind.extrema(
                    j, labels, object_indexes)
                min_i = np.maximum(fix(min_i) - distance, 0).astype(int)
                max_i = np.minimum(fix(max_i) + distance + 1,
                                   labels.shape[0]).astype(int)
                min_j = np.maximum(fix(min_j) - distance, 0).astype(int)
                max_j = np.minimum(fix(max_j) + distance + 1,
                                   labels.shape[1]).astype(int)
            else:
                k, i, j = np.mgrid[0:labels.shape[0], 0:labels.shape[1],
                                   0:labels.shape[2]]
                min_k, max_k, min_k_pos, max_k_pos = scind.extrema(
                    k, labels, object_indexes)
                min_i, max_i, min_i_pos, max_i_pos = scind.extrema(
                    i, labels, object_indexes)
                min_j, max_j, min_j_pos, max_j_pos = scind.extrema(
                    j, labels, object_indexes)
                min_k = np.maximum(fix(min_k) - distance, 0).astype(int)
                max_k = np.minimum(fix(max_k) + distance + 1,
                                   labels.shape[0]).astype(int)
                min_i = np.maximum(fix(min_i) - distance, 0).astype(int)
                max_i = np.minimum(fix(max_i) + distance + 1,
                                   labels.shape[1]).astype(int)
                min_j = np.maximum(fix(min_j) - distance, 0).astype(int)
                max_j = np.minimum(fix(max_j) + distance + 1,
                                   labels.shape[2]).astype(int)
            #
            # Loop over all objects
            # Calculate which ones overlap "index"
            # Calculate how much overlap there is of others to "index"
            #
            for object_number in object_numbers:
                if object_number == 0:
                    #
                    # No corresponding object in small-removed. This means
                    # that the object has no pixels, e.g., not renumbered.
                    #
                    continue
                index = object_number - 1
                if dimensions == 2:
                    patch = labels[min_i[index]:max_i[index],
                                   min_j[index]:max_j[index]]
                    npatch = neighbor_labels[min_i[index]:max_i[index],
                                             min_j[index]:max_j[index]]
                else:
                    patch = labels[min_k[index]:max_k[index],
                                   min_i[index]:max_i[index],
                                   min_j[index]:max_j[index], ]
                    npatch = neighbor_labels[min_k[index]:max_k[index],
                                             min_i[index]:max_i[index],
                                             min_j[index]:max_j[index], ]

                #
                # Find the neighbors
                #
                patch_mask = patch == (index + 1)
                extended = scind.binary_dilation(patch_mask, strel)
                neighbors = np.unique(npatch[extended])
                neighbors = neighbors[neighbors != 0]
                if self.neighbors_are_objects:
                    neighbors = neighbors[neighbors != object_number]
                nc = len(neighbors)
                neighbor_count[index] = nc
                if nc > 0:
                    first_objects.append(np.ones(nc, int) * object_number)
                    second_objects.append(neighbors)
                if self.neighbors_are_objects:
                    #
                    # Find the # of overlapping pixels. Dilate the neighbors
                    # and see how many pixels overlap our image. Use a 3x3
                    # structuring element to expand the overlapping edge
                    # into the perimeter.
                    #
                    if dimensions == 2:
                        outline_patch = (perimeter_outlines[
                            min_i[index]:max_i[index],
                            min_j[index]:max_j[index]] == object_number)
                    else:
                        outline_patch = (perimeter_outlines[
                            min_k[index]:max_k[index],
                            min_i[index]:max_i[index],
                            min_j[index]:max_j[index], ] == object_number)

                    extended = scind.binary_dilation(
                        (patch != 0) & (patch != object_number),
                        strel_touching)
                    overlap = np.sum(outline_patch & extended)
                    pixel_count[index] = overlap
            if sum([len(x) for x in first_objects]) > 0:
                first_objects = np.hstack(first_objects)
                reverse_object_numbers = np.zeros(
                    max(np.max(object_numbers), np.max(first_objects)) + 1,
                    int)
                reverse_object_numbers[object_numbers] = (
                    np.arange(len(object_numbers)) + 1)
                first_objects = reverse_object_numbers[first_objects]

                second_objects = np.hstack(second_objects)
                reverse_neighbor_numbers = np.zeros(
                    max(np.max(neighbor_numbers), np.max(second_objects)) + 1,
                    int)
                reverse_neighbor_numbers[neighbor_numbers] = (
                    np.arange(len(neighbor_numbers)) + 1)
                second_objects = reverse_neighbor_numbers[second_objects]
                to_keep = (first_objects > 0) & (second_objects > 0)
                first_objects = first_objects[to_keep]
                second_objects = second_objects[to_keep]
            else:
                first_objects = np.zeros(0, int)
                second_objects = np.zeros(0, int)
            if self.neighbors_are_objects:
                percent_touching = pixel_count * 100 / perimeters
            else:
                percent_touching = pixel_count * 100.0 / areas
            object_indexes = object_numbers - 1
            neighbor_indexes = neighbor_numbers - 1
            #
            # Have to recompute nearest
            #
            first_object_number = np.zeros(nkept_objects, int)
            second_object_number = np.zeros(nkept_objects, int)
            if nkept_objects > (1 if self.neighbors_are_objects else 0):
                di = (ocenters[object_indexes[:, np.newaxis], 0] -
                      ncenters[neighbor_indexes[np.newaxis, :], 0])
                dj = (ocenters[object_indexes[:, np.newaxis], 1] -
                      ncenters[neighbor_indexes[np.newaxis, :], 1])
                distance_matrix = np.sqrt(di * di + dj * dj)
                distance_matrix[~has_pixels, :] = np.inf
                distance_matrix[:, ~neighbor_has_pixels] = np.inf
                #
                # order[:,0] should be arange(nobjects)
                # order[:,1] should be the nearest neighbor
                # order[:,2] should be the next nearest neighbor
                #
                order = np.lexsort([distance_matrix
                                    ]).astype(first_object_number.dtype)
                if self.neighbors_are_objects:
                    first_object_number[has_pixels] = order[has_pixels, 1] + 1
                    if nkept_objects > 2:
                        second_object_number[has_pixels] = order[has_pixels,
                                                                 2] + 1
                else:
                    first_object_number[has_pixels] = order[has_pixels, 0] + 1
                    if order.shape[1] > 1:
                        second_object_number[has_pixels] = order[has_pixels,
                                                                 1] + 1
        else:
            object_indexes = object_numbers - 1
            neighbor_indexes = neighbor_numbers - 1
            first_objects = np.zeros(0, int)
            second_objects = np.zeros(0, int)
        #
        # Now convert all measurements from the small-removed to
        # the final number set.
        #
        neighbor_count = neighbor_count[object_indexes]
        neighbor_count[~has_pixels] = 0
        percent_touching = percent_touching[object_indexes]
        percent_touching[~has_pixels] = 0
        first_x_vector = first_x_vector[object_indexes]
        second_x_vector = second_x_vector[object_indexes]
        first_y_vector = first_y_vector[object_indexes]
        second_y_vector = second_y_vector[object_indexes]
        angle = angle[object_indexes]
        #
        # Record the measurements
        #
        assert isinstance(workspace, cpw.Workspace)
        m = workspace.measurements
        assert isinstance(m, cpmeas.Measurements)
        image_set = workspace.image_set
        features_and_data = [
            (M_NUMBER_OF_NEIGHBORS, neighbor_count),
            (M_FIRST_CLOSEST_OBJECT_NUMBER, first_object_number),
            (
                M_FIRST_CLOSEST_DISTANCE,
                np.sqrt(first_x_vector**2 + first_y_vector**2),
            ),
            (M_SECOND_CLOSEST_OBJECT_NUMBER, second_object_number),
            (
                M_SECOND_CLOSEST_DISTANCE,
                np.sqrt(second_x_vector**2 + second_y_vector**2),
            ),
            (M_ANGLE_BETWEEN_NEIGHBORS, angle),
        ]
        if self.neighbors_are_objects:
            features_and_data.append((M_PERCENT_TOUCHING, percent_touching))
        for feature_name, data in features_and_data:
            m.add_measurement(self.object_name.value,
                              self.get_measurement_name(feature_name), data)
        if len(first_objects) > 0:
            m.add_relate_measurement(
                self.module_num,
                cpmeas.NEIGHBORS,
                self.object_name.value,
                self.object_name.value
                if self.neighbors_are_objects else self.neighbors_name.value,
                m.image_set_number * np.ones(first_objects.shape, int),
                first_objects,
                m.image_set_number * np.ones(second_objects.shape, int),
                second_objects,
            )

        labels = kept_labels

        neighbor_count_image = np.zeros(labels.shape, int)
        object_mask = objects.segmented != 0
        object_indexes = objects.segmented[object_mask] - 1
        neighbor_count_image[object_mask] = neighbor_count[object_indexes]
        workspace.display_data.neighbor_count_image = neighbor_count_image

        if self.neighbors_are_objects:
            percent_touching_image = np.zeros(labels.shape)
            percent_touching_image[object_mask] = percent_touching[
                object_indexes]
            workspace.display_data.percent_touching_image = percent_touching_image

        image_set = workspace.image_set
        if self.wants_count_image.value:
            neighbor_cm_name = self.count_colormap.value
            neighbor_cm = get_colormap(neighbor_cm_name)
            sm = matplotlib.cm.ScalarMappable(cmap=neighbor_cm)
            img = sm.to_rgba(neighbor_count_image)[:, :, :3]
            img[:, :, 0][~object_mask] = 0
            img[:, :, 1][~object_mask] = 0
            img[:, :, 2][~object_mask] = 0
            count_image = cpi.Image(img, masking_objects=objects)
            image_set.add(self.count_image_name.value, count_image)
        else:
            neighbor_cm_name = cpprefs.get_default_colormap()
            neighbor_cm = matplotlib.cm.get_cmap(neighbor_cm_name)
        if self.neighbors_are_objects and self.wants_percent_touching_image:
            percent_touching_cm_name = self.touching_colormap.value
            percent_touching_cm = get_colormap(percent_touching_cm_name)
            sm = matplotlib.cm.ScalarMappable(cmap=percent_touching_cm)
            img = sm.to_rgba(percent_touching_image)[:, :, :3]
            img[:, :, 0][~object_mask] = 0
            img[:, :, 1][~object_mask] = 0
            img[:, :, 2][~object_mask] = 0
            touching_image = cpi.Image(img, masking_objects=objects)
            image_set.add(self.touching_image_name.value, touching_image)
        else:
            percent_touching_cm_name = cpprefs.get_default_colormap()
            percent_touching_cm = matplotlib.cm.get_cmap(
                percent_touching_cm_name)

        if self.show_window:
            workspace.display_data.neighbor_cm_name = neighbor_cm_name
            workspace.display_data.percent_touching_cm_name = percent_touching_cm_name
            workspace.display_data.orig_labels = objects.segmented
            workspace.display_data.expanded_labels = expanded_labels
            workspace.display_data.object_mask = object_mask
            workspace.display_data.dimensions = dimensions
Beispiel #46
0
def fluor_polarity_txy(fluor_chan, bmask, cell_tracks):
    """
    Calculates polarity of a fluorescence signal within an object at each time
    point across a time series. A DataFrame containing tracking info for these
    objects (a unique label for each tracked object and the x-y position at
    each time point) needs to be included as this function does not incorporate
    any tracking algorithms. See https://doi.org/10.1101/457119 for detailed
    descriptions of the 'Distance' and 'Angular' polarity metrics.
  
    Parameters
    ----------
    fluor_chan: ndarray
        A 3d image stack (t, x, y) of the fluorescence signal to be measured.
        
    bmask: ndarray
        A 3d image stack (t, x, y) of binary masks of the objects containing
        the signal in 'fluor_chan' (e.g. cell 'footprints'). The shapes of
        'fluor_chan' and 'bmask' must be identical.
        
    cell_tracks: DataFrame
        This DataFrame summarizes the x-y positions of previously-tracked
        objects that each have a unique label. EXACTLY four columns need to be
        present and named as follows:        
        'Time_s' contains the timepoints of each x-y frame in a 3d time series.
        'Object_id' contains a unique label for each object that was tracked
        in time.
        'X' contains the x coordinate of the geometric center of each object
        at each timepoint.
        'Y' contains the y coordinate of the geometric center of each object
        at each timepoint.
  
    Returns
    -------
    output: DataFrame 
        This DataFrame contains the original 'Time_s' and 'Object_id' columns,
        with the further addition of 'Distance_polarity_score' and
        'Angular_polarity_score' columns, indicating the polarity measurement
        of each object at each timepoint.
        
    """
    assert type(bmask) is np.ndarray, "Binary masks are not a numpy array!"
    assert type(
        fluor_chan) is np.ndarray, "Fluorescence images are not a numpy array!"
    assert fluor_chan.shape == bmask.shape, "Fluorescence image and binary mask are different dimensions!"
    assert type(
        cell_tracks
    ) is pd.DataFrame, "'cell tracks' need to be formatted as a pandas DataFrame!"
    assert 'Time_s' in cell_tracks, "'cell_tracks' is missing 'Time_s' column!"
    assert 'Object_id' in cell_tracks, "'cell_tracks' is missing 'Object_id' column!"
    assert 'X' in cell_tracks and 'Y' in cell_tracks, "'cell_tracks' is missing 'X' and/or 'Y' column(s)!"
    assert len(
        cell_tracks.columns
    ) == 4, "'cell_tracks' must contain EXACTLY five columns labeled 'Time_s', 'Object_id, 'X', and 'Y'!"

    #reformat input DataFrame so order of columns is consistent
    sortdata = pd.DataFrame(columns=[])
    sortdata['Time_s'] = cell_tracks['Time_s']
    sortdata['Object_id'] = cell_tracks['Object_id']
    sortdata['X'] = cell_tracks['X']
    sortdata['Y'] = cell_tracks['Y']
    cell_tracks = None
    cell_tracks = sortdata
    sortdata = None

    time_intv = cell_tracks.loc[1, 'Time_s'] - cell_tracks.loc[
        0, 'Time_s']  # for determining time interval between each frame
    final_table = pd.DataFrame(columns=[])
    img_labels = np.zeros(bmask.shape, dtype=int)

    for x, frame in enumerate(bmask):
        img_labels[x] = sk.measure.label(frame)

    areascol = []
    labelscol = []
    objs = []
    intlocscol = []
    cenlocscol = []
    xlist = []
    major_axes_col = []

    # label objects in binary mask and get x-y positions for the geometric center
    # and weighted fluorescence intensity center for each labeled object
    for x, frame in enumerate(img_labels):
        areas = [
            r.area for r in sk.measure.regionprops(frame, coordinates='rc')
        ]
        labels = [
            r.label for r in sk.measure.regionprops(frame, coordinates='rc')
        ]
        major_axes = [
            r.major_axis_length
            for r in sk.measure.regionprops(frame, coordinates='rc')
        ]
        intlocs = [
            list(r.weighted_centroid) for r in sk.measure.regionprops(
                frame, intensity_image=fluor_chan[x, :, :], coordinates='rc')
        ]
        cenlocs = [
            list(r.weighted_centroid) for r in sk.measure.regionprops(
                frame, intensity_image=bmask[x, :, :], coordinates='rc')
        ]
        areascol.append(areas)
        labelscol.append(labels)
        intlocscol.append(intlocs)
        cenlocscol.append(cenlocs)
        major_axes_col.append(major_axes)
        y = 0
        while y < np.amax(frame):
            xlist.append(x)
            y += 1

    # make a numpy array from all the lists generated in preceding 'for' loop
    flatarea = mpu.datastructures.flatten(areascol)
    flatlabel = mpu.datastructures.flatten(labelscol)
    flatmajor_axes = mpu.datastructures.flatten(major_axes_col)
    flatcoords = mpu.datastructures.flatten(intlocscol)
    flatcoords = np.reshape(np.asarray(flatcoords), (len(flatcoords) // 2, 2))
    flatcencoords = mpu.datastructures.flatten(cenlocscol)
    flatcencoords = np.reshape(np.asarray(flatcencoords),
                               (len(flatcencoords) // 2, 2))
    objs.append(xlist)
    objs.append(flatlabel)
    objs.append(flatarea)
    objs.append(flatmajor_axes)
    objs = np.transpose(np.asarray(objs))
    objs = np.concatenate((objs, flatcoords, flatcencoords), axis=1)
    areascol = None
    labelscol = None
    intlocscol = None
    cenlocscol = None

    # normalize distances between geometric and fluorescence center to origin to make later calcuations easier
    absx = objs[:, 4] - objs[:, 6]
    absy = objs[:, 5] - objs[:, 7]
    absx = np.reshape(np.asarray(absx), (len(absx), 1))
    absy = np.reshape(np.asarray(absy), (len(absy), 1))

    objs = np.concatenate((objs, absx, absy), axis=1)
    flatlabel = None
    flatarea = None
    flatcencoords = None
    flatcoords = None
    absx = None
    absy = None

    collection = pd.DataFrame(objs,
                              columns=[
                                  'Timepoint', 'Reg_Props_Obj_Num', 'Area',
                                  'Major_axis_length', 'Y_intensity',
                                  'X_intensity', 'Y_center', 'X_center',
                                  'Y_adj', 'X_adj'
                              ])
    collection['Timepoint'] = (collection['Timepoint'] * time_intv).astype(int)
    collection['Reg_Props_Obj_Num'] = collection['Reg_Props_Obj_Num'].astype(
        int)
    collection['Distance_polarity_score'] = (
        (collection['X_adj']**2 + collection['Y_adj']**2)**
        0.5) / (collection['Major_axis_length'] / 2)
    objs = None

    polarity_scores_final = []
    assert len(collection.columns) == 11
    for x, frame in enumerate(img_labels):
        pointslist = []
        weightedpointlist = []
        obj_intensitylist = []

        # find all x-y positions where there is an object present
        for index, item in np.ndenumerate(frame):
            if item > 0:
                nextpoint = [item, index]
                pointslist.append(nextpoint)

        pointslist.sort()
        subcollection = (collection[collection['Timepoint'] == (
            x * time_intv)]).values

        # find the total intensity of each object in the current image frame
        z = 1
        while z <= np.amax(frame):
            obj_intensity = ndimage.sum(fluor_chan[x, :, :],
                                        img_labels[x, :, :],
                                        index=z)
            obj_intensitylist.append(obj_intensity)
            z += 1

        # for each point in object, find the consine between its vector and the "polarity" vector
        for y, item in enumerate(pointslist):
            objnum = item[0]
            xypos = item[1]
            center = (subcollection[(objnum - 1),
                                    6], subcollection[(objnum - 1), 7])
            fluorcenter = (subcollection[(objnum - 1),
                                         4], subcollection[(objnum - 1), 5])
            adjxypoint = np.subtract(xypos, center)
            adjxyfluor = np.subtract(fluorcenter, center)
            cosine = getcosine(adjxypoint, adjxyfluor)
            pointintensity = fluor_chan[x, xypos[0], xypos[1]]
            weightedpoint = cosine * pointintensity
            weightedpointlist.append(weightedpoint)

        weightedpointlist = np.asanyarray(weightedpointlist).astype(int)
        sumweightedpoints = 0
        finalweights = []

        # this sums together the values for all the individual points of a given object
        for y, item in enumerate(weightedpointlist):
            if y + 1 == len(weightedpointlist):
                sumweightedpoints = sumweightedpoints + weightedpointlist[y]
                finalweights.append(sumweightedpoints)
                sumweightedpoints = 0
            elif pointslist[y][0] - pointslist[y + 1][0] == 0:
                sumweightedpoints = sumweightedpoints + weightedpointlist[y]
            elif pointslist[y][0] - pointslist[y + 1][0] == -1:
                sumweightedpoints = sumweightedpoints + weightedpointlist[y]
                finalweights.append(sumweightedpoints)
                sumweightedpoints = 0

        polarity_scores = np.asanyarray(finalweights) / np.asarray(
            obj_intensitylist)
        polarity_scores_final.append(list(polarity_scores))

    polarity_scores_final = mpu.datastructures.flatten(polarity_scores_final)
    polarity_scores_final = np.transpose(np.asarray(polarity_scores_final))
    collection['Angular_polarity_score'] = polarity_scores_final

    # Below for loop matches values from the 'polarity scores array' to those in the DataFrame
    # containing the labeled tracks. This is needed since polarity scores are calculated for
    # every object, even ones that have no associated track label.
    xy_coords = np.zeros((len(collection), len(collection.columns)),
                         dtype=float)
    for indx, row in cell_tracks.iterrows():
        time_idx = row['Time_s']
        x_idx = row['X']
        lookup = (collection['Timepoint']
                  == time_idx) & (abs(collection['X_center'] - x_idx) < 0.001)
        extract = collection[lookup]
        # Below 'if' statement for catching cases where => 2 rows have very similar x-coords.
        # If true, also use y-coords for further discrimination
        if extract.shape[0] > 1:
            extract = None
            lookup = None
            y_idx = row['Y']
            lookup = (collection['Timepoint'] == time_idx) & (
                abs(collection['X_center'] - x_idx) <
                0.001) & (abs(collection['Y_center'] - y_idx) < 0.001)
            extract = collection[lookup]
        extract = extract.values
        xy_coords[indx, :] = extract

    new_coords = pd.DataFrame({
        'X_intensity_center': xy_coords[:, 5],
        'Y_intensity_center': xy_coords[:, 4],
        'X_object_center': xy_coords[:, 7],
        'Y_object_center': xy_coords[:, 6],
        'Distance_polarity_score': xy_coords[:, 10],
        'Angular_polarity_score': xy_coords[:, 11]
    })
    cell_polarity_scores = cell_tracks.join(new_coords)
    output = pd.DataFrame(columns=[])
    output['Object_id'] = cell_polarity_scores['Object_id'].astype(int)
    output['Time_s'] = cell_polarity_scores['Time_s']
    output['Distance_polarity_score'] = cell_polarity_scores[
        'Distance_polarity_score']
    output['Angular_polarity_score'] = cell_polarity_scores[
        'Angular_polarity_score']

    return output
Beispiel #47
0
    def do_measurements(self, workspace, image_name, object_name,
                        center_object_name, center_choice,
                        bin_count_settings, dd):
        '''Perform the radial measurements on the image set

        workspace - workspace that holds images / objects
        image_name - make measurements on this image
        object_name - make measurements on these objects
        center_object_name - use the centers of these related objects as
                      the centers for radial measurements. None to use the
                      objects themselves.
        center_choice - the user's center choice for this object:
                      C_SELF, C_CENTERS_OF_OBJECTS or C_EDGES_OF_OBJECTS.
        bin_count_settings - the bin count settings group
        d - a dictionary for saving reusable partial results

        returns one statistics tuple per ring.
        '''
        assert isinstance(workspace, cpw.Workspace)
        assert isinstance(workspace.object_set, cpo.ObjectSet)
        bin_count = bin_count_settings.bin_count.value
        wants_scaled = bin_count_settings.wants_scaled.value
        maximum_radius = bin_count_settings.maximum_radius.value

        image = workspace.image_set.get_image(image_name,
                                              must_be_grayscale=True)
        objects = workspace.object_set.get_objects(object_name)
        labels, pixel_data = cpo.crop_labels_and_image(objects.segmented,
                                                       image.pixel_data)
        nobjects = np.max(objects.segmented)
        measurements = workspace.measurements
        assert isinstance(measurements, cpmeas.Measurements)
        heatmaps = {}
        for heatmap in self.heatmaps:
            if heatmap.object_name.get_objects_name() == object_name and \
                            image_name == heatmap.image_name.get_image_name() and \
                            heatmap.get_number_of_bins() == bin_count:
                dd[id(heatmap)] = \
                    heatmaps[MEASUREMENT_ALIASES[heatmap.measurement.value]] = \
                    np.zeros(labels.shape)
        if nobjects == 0:
            for bin in range(1, bin_count + 1):
                for feature in (F_FRAC_AT_D, F_MEAN_FRAC, F_RADIAL_CV):
                    feature_name = (
                        (feature + FF_GENERIC) % (image_name, bin, bin_count))
                    measurements.add_measurement(
                            object_name, "_".join([M_CATEGORY, feature_name]),
                            np.zeros(0))
                    if not wants_scaled:
                        measurement_name = "_".join([M_CATEGORY, feature,
                                                     image_name, FF_OVERFLOW])
                        measurements.add_measurement(
                                object_name, measurement_name, np.zeros(0))
            return [(image_name, object_name, "no objects", "-", "-", "-", "-")]
        name = (object_name if center_object_name is None
                else "%s_%s" % (object_name, center_object_name))
        if dd.has_key(name):
            normalized_distance, i_center, j_center, good_mask = dd[name]
        else:
            d_to_edge = distance_to_edge(labels)
            if center_object_name is not None:
                #
                # Use the center of the centering objects to assign a center
                # to each labeled pixel using propagation
                #
                center_objects = workspace.object_set.get_objects(center_object_name)
                center_labels, cmask = cpo.size_similarly(
                        labels, center_objects.segmented)
                pixel_counts = fix(scind.sum(
                        np.ones(center_labels.shape),
                        center_labels,
                        np.arange(1, np.max(center_labels) + 1, dtype=np.int32)))
                good = pixel_counts > 0
                i, j = (centers_of_labels(center_labels) + .5).astype(int)
                ig = i[good]
                jg = j[good]
                lg = np.arange(1, len(i) + 1)[good]
                if center_choice == C_CENTERS_OF_OTHER:
                    #
                    # Reduce the propagation labels to the centers of
                    # the centering objects
                    #
                    center_labels = np.zeros(center_labels.shape, int)
                    center_labels[ig, jg] = lg
                cl, d_from_center = propagate(np.zeros(center_labels.shape),
                                              center_labels,
                                              labels != 0, 1)
                #
                # Erase the centers that fall outside of labels
                #
                cl[labels == 0] = 0
                #
                # If objects are hollow or crescent-shaped, there may be
                # objects without center labels. As a backup, find the
                # center that is the closest to the center of mass.
                #
                missing_mask = (labels != 0) & (cl == 0)
                missing_labels = np.unique(labels[missing_mask])
                if len(missing_labels):
                    all_centers = centers_of_labels(labels)
                    missing_i_centers, missing_j_centers = \
                        all_centers[:, missing_labels - 1]
                    di = missing_i_centers[:, np.newaxis] - ig[np.newaxis, :]
                    dj = missing_j_centers[:, np.newaxis] - jg[np.newaxis, :]
                    missing_best = lg[np.argsort((di * di + dj * dj,))[:, 0]]
                    best = np.zeros(np.max(labels) + 1, int)
                    best[missing_labels] = missing_best
                    cl[missing_mask] = best[labels[missing_mask]]
                    #
                    # Now compute the crow-flies distance to the centers
                    # of these pixels from whatever center was assigned to
                    # the object.
                    #
                    iii, jjj = np.mgrid[0:labels.shape[0], 0:labels.shape[1]]
                    di = iii[missing_mask] - i[cl[missing_mask] - 1]
                    dj = jjj[missing_mask] - j[cl[missing_mask] - 1]
                    d_from_center[missing_mask] = np.sqrt(di * di + dj * dj)
            else:
                # Find the point in each object farthest away from the edge.
                # This does better than the centroid:
                # * The center is within the object
                # * The center tends to be an interesting point, like the
                #   center of the nucleus or the center of one or the other
                #   of two touching cells.
                #
                i, j = maximum_position_of_labels(d_to_edge, labels, objects.indices)
                center_labels = np.zeros(labels.shape, int)
                center_labels[i, j] = labels[i, j]
                #
                # Use the coloring trick here to process touching objects
                # in separate operations
                #
                colors = color_labels(labels)
                ncolors = np.max(colors)
                d_from_center = np.zeros(labels.shape)
                cl = np.zeros(labels.shape, int)
                for color in range(1, ncolors + 1):
                    mask = colors == color
                    l, d = propagate(np.zeros(center_labels.shape),
                                     center_labels,
                                     mask, 1)
                    d_from_center[mask] = d[mask]
                    cl[mask] = l[mask]
            good_mask = cl > 0
            if center_choice == C_EDGES_OF_OTHER:
                # Exclude pixels within the centering objects
                # when performing calculations from the centers
                good_mask = good_mask & (center_labels == 0)
            i_center = np.zeros(cl.shape)
            i_center[good_mask] = i[cl[good_mask] - 1]
            j_center = np.zeros(cl.shape)
            j_center[good_mask] = j[cl[good_mask] - 1]

            normalized_distance = np.zeros(labels.shape)
            if wants_scaled:
                total_distance = d_from_center + d_to_edge
                normalized_distance[good_mask] = (d_from_center[good_mask] /
                                                  (total_distance[good_mask] + .001))
            else:
                normalized_distance[good_mask] = \
                    d_from_center[good_mask] / maximum_radius
            dd[name] = [normalized_distance, i_center, j_center, good_mask]
        ngood_pixels = np.sum(good_mask)
        good_labels = labels[good_mask]
        bin_indexes = (normalized_distance * bin_count).astype(int)
        bin_indexes[bin_indexes > bin_count] = bin_count
        labels_and_bins = (good_labels - 1, bin_indexes[good_mask])
        histogram = coo_matrix((pixel_data[good_mask], labels_and_bins),
                               (nobjects, bin_count + 1)).toarray()
        sum_by_object = np.sum(histogram, 1)
        sum_by_object_per_bin = np.dstack([sum_by_object] * (bin_count + 1))[0]
        fraction_at_distance = histogram / sum_by_object_per_bin
        number_at_distance = coo_matrix((np.ones(ngood_pixels), labels_and_bins),
                                        (nobjects, bin_count + 1)).toarray()
        object_mask = number_at_distance > 0
        sum_by_object = np.sum(number_at_distance, 1)
        sum_by_object_per_bin = np.dstack([sum_by_object] * (bin_count + 1))[0]
        fraction_at_bin = number_at_distance / sum_by_object_per_bin
        mean_pixel_fraction = fraction_at_distance / (fraction_at_bin +
                                                      np.finfo(float).eps)
        masked_fraction_at_distance = masked_array(fraction_at_distance,
                                                   ~object_mask)
        masked_mean_pixel_fraction = masked_array(mean_pixel_fraction,
                                                  ~object_mask)
        # Anisotropy calculation.  Split each cell into eight wedges, then
        # compute coefficient of variation of the wedges' mean intensities
        # in each ring.
        #
        # Compute each pixel's delta from the center object's centroid
        i, j = np.mgrid[0:labels.shape[0], 0:labels.shape[1]]
        imask = i[good_mask] > i_center[good_mask]
        jmask = j[good_mask] > j_center[good_mask]
        absmask = (abs(i[good_mask] - i_center[good_mask]) >
                   abs(j[good_mask] - j_center[good_mask]))
        radial_index = (imask.astype(int) + jmask.astype(int) * 2 +
                        absmask.astype(int) * 4)
        statistics = []

        for bin in range(bin_count + (0 if wants_scaled else 1)):
            bin_mask = (good_mask & (bin_indexes == bin))
            bin_pixels = np.sum(bin_mask)
            bin_labels = labels[bin_mask]
            bin_radial_index = radial_index[bin_indexes[good_mask] == bin]
            labels_and_radii = (bin_labels - 1, bin_radial_index)
            radial_values = coo_matrix((pixel_data[bin_mask],
                                        labels_and_radii),
                                       (nobjects, 8)).toarray()
            pixel_count = coo_matrix((np.ones(bin_pixels), labels_and_radii),
                                     (nobjects, 8)).toarray()
            mask = pixel_count == 0
            radial_means = masked_array(radial_values / pixel_count, mask)
            radial_cv = np.std(radial_means, 1) / np.mean(radial_means, 1)
            radial_cv[np.sum(~mask, 1) == 0] = 0
            for measurement, feature, overflow_feature in (
                    (fraction_at_distance[:, bin], MF_FRAC_AT_D, OF_FRAC_AT_D),
                    (mean_pixel_fraction[:, bin], MF_MEAN_FRAC, OF_MEAN_FRAC),
                    (np.array(radial_cv), MF_RADIAL_CV, OF_RADIAL_CV)):

                if bin == bin_count:
                    measurement_name = overflow_feature % image_name
                else:
                    measurement_name = feature % (image_name, bin + 1, bin_count)
                measurements.add_measurement(object_name,
                                             measurement_name,
                                             measurement)
                if feature in heatmaps:
                    heatmaps[feature][bin_mask] = measurement[bin_labels - 1]
            radial_cv.mask = np.sum(~mask, 1) == 0
            bin_name = str(bin + 1) if bin < bin_count else "Overflow"
            statistics += [(image_name, object_name, bin_name, str(bin_count),
                            round(np.mean(masked_fraction_at_distance[:, bin]), 4),
                            round(np.mean(masked_mean_pixel_fraction[:, bin]), 4),
                            round(np.mean(radial_cv), 4))]
        return statistics
Beispiel #48
0
def fluor_polarity_xy(fluor_chan, bmask):
    """
    Calculates polarity of a fluorescence signal within objects in a single
    image. See https://doi.org/10.1101/457119 for detailed descriptions of
    the 'Distance' and 'Angular' polarity metrics.
  
    Parameters
    ----------
    fluor_chan: ndarray
        A 2d image (x, y) of the fluorescence signal to be measured.
        
    bmask: ndarray
        A 2d image (x, y) of binary masks of the objects containing the
        signal in 'fluor_chan' (e.g. cell 'footprints'). The shapes of
        'fluor_chan' and 'bmask' must be identical.
  
    Returns
    -------
    output: DataFrame
        This DataFrame contains five columns:
        'Object_id': Label for each object in the binary mask.
        'X_center': The x-coordinate of the geometric center of the object
            in the binary mask.
        'Y_center': The y-coordinate of the geometric center of the object
            in the binary mask.
        'Distance_polarity_score': Polarity score based on the distance
            between the center of fluorescence intensity and the
            geometric center of the object.
        'Angular_polarity_score': Polarity score based on the angular
            distribution of the fluorescence signal about the geometric
            center of the object.
        
    """
    assert type(bmask) is np.ndarray, "Binary masks are not a numpy array!"
    assert type(
        fluor_chan) is np.ndarray, "Fluorescence images are not a numpy array!"
    assert fluor_chan.shape == bmask.shape, "Fluorescence image and binary mask are different dimensions!"

    final_table = pd.DataFrame(columns=[])
    img_labels = np.zeros(bmask.shape, dtype=int)

    img_labels = sk.measure.label(bmask)

    areascol = []
    labelscol = []
    objs = []
    intlocscol = []
    cenlocscol = []
    xlist = []
    major_axes_col = []

    # label objects in binary mask and get x-y positions for the geometric center
    # and weighted fluorescence intensity center for each labeled object

    areas = [
        r.area for r in sk.measure.regionprops(img_labels, coordinates='rc')
    ]
    labels = [
        r.label for r in sk.measure.regionprops(img_labels, coordinates='rc')
    ]
    major_axes = [
        r.major_axis_length
        for r in sk.measure.regionprops(img_labels, coordinates='rc')
    ]
    intlocs = [
        list(r.weighted_centroid) for r in sk.measure.regionprops(
            img_labels, intensity_image=fluor_chan[:, :], coordinates='rc')
    ]
    cenlocs = [
        list(r.weighted_centroid) for r in sk.measure.regionprops(
            img_labels, intensity_image=bmask[:, :], coordinates='rc')
    ]
    areascol.append(areas)
    labelscol.append(labels)
    intlocscol.append(intlocs)
    cenlocscol.append(cenlocs)
    major_axes_col.append(major_axes)

    # make a numpy array from all the lists generated in preceding 'for' loop
    flatarea = mpu.datastructures.flatten(areascol)
    flatlabel = mpu.datastructures.flatten(labelscol)
    flatmajor_axes = mpu.datastructures.flatten(major_axes_col)
    flatcoords = mpu.datastructures.flatten(intlocscol)
    flatcoords = np.reshape(np.asarray(flatcoords), (len(flatcoords) // 2, 2))
    flatcencoords = mpu.datastructures.flatten(cenlocscol)
    flatcencoords = np.reshape(np.asarray(flatcencoords),
                               (len(flatcencoords) // 2, 2))
    objs.append(flatlabel)
    objs.append(flatarea)
    objs.append(flatmajor_axes)
    objs = np.transpose(np.asarray(objs))
    objs = np.concatenate((objs, flatcoords, flatcencoords), axis=1)
    areascol = None
    labelscol = None
    intlocscol = None
    cenlocscol = None

    # normalize distances between geometric and fluorescence center to origin to make later calcuations easier
    absx = objs[:, 3] - objs[:, 5]
    absy = objs[:, 4] - objs[:, 6]
    absx = np.reshape(np.asarray(absx), (len(absx), 1))
    absy = np.reshape(np.asarray(absy), (len(absy), 1))

    objs = np.concatenate((objs, absx, absy), axis=1)
    flatlabel = None
    flatarea = None
    flatcencoords = None
    flatcoords = None
    absx = None
    absy = None

    collection = pd.DataFrame(objs,
                              columns=[
                                  'Reg_Props_Obj_Num', 'Area',
                                  'Major_axis_length', 'Y_intensity',
                                  'X_intensity', 'Y_center', 'X_center',
                                  'Y_adj', 'X_adj'
                              ])
    collection['Reg_Props_Obj_Num'] = collection['Reg_Props_Obj_Num'].astype(
        int)
    collection['Distance_polarity_score'] = (
        (collection['X_adj']**2 + collection['Y_adj']**2)**
        0.5) / (collection['Major_axis_length'] / 2)
    objs = None

    polarity_scores_final = []
    assert len(collection.columns) == 10
    pointslist = []
    weightedpointlist = []
    obj_intensitylist = []

    # find all x-y positions where there is an object present
    for index, item in np.ndenumerate(img_labels):
        if item > 0:
            nextpoint = [item, index]
            pointslist.append(nextpoint)

    pointslist.sort()
    subcollection = collection.values

    # find the total intensity of each object in the current image frame
    z = 1
    while z <= np.amax(img_labels):
        obj_intensity = ndimage.sum(fluor_chan[:, :],
                                    img_labels[:, :],
                                    index=z)
        obj_intensitylist.append(obj_intensity)
        z += 1

    # for each point in object, find the consine between its vector and the "polarity" vector
    y = 0
    for y, item in enumerate(pointslist):
        objnum = item[0]
        xypos = item[1]
        center = (subcollection[(objnum - 1), 5], subcollection[(objnum - 1),
                                                                6])
        fluorcenter = (subcollection[(objnum - 1),
                                     3], subcollection[(objnum - 1), 4])
        adjxypoint = np.subtract(xypos, center)
        adjxyfluor = np.subtract(fluorcenter, center)
        cosine = getcosine(adjxypoint, adjxyfluor)
        pointintensity = fluor_chan[xypos[0], xypos[1]]
        weightedpoint = cosine * pointintensity
        weightedpointlist.append(weightedpoint)

    weightedpointlist = np.asanyarray(weightedpointlist).astype(int)
    sumweightedpoints = 0
    finalweights = []

    # this sums together the values for all the individual points of a given object
    for y, item in enumerate(weightedpointlist):
        if y + 1 == len(weightedpointlist):
            sumweightedpoints = sumweightedpoints + weightedpointlist[y]
            finalweights.append(sumweightedpoints)
            sumweightedpoints = 0
        elif pointslist[y][0] - pointslist[y + 1][0] == 0:
            sumweightedpoints = sumweightedpoints + weightedpointlist[y]
        elif pointslist[y][0] - pointslist[y + 1][0] == -1:
            sumweightedpoints = sumweightedpoints + weightedpointlist[y]
            finalweights.append(sumweightedpoints)
            sumweightedpoints = 0

    polarity_scores = np.asanyarray(finalweights) / np.asarray(
        obj_intensitylist)
    polarity_scores_final.append(list(polarity_scores))

    polarity_scores_final = mpu.datastructures.flatten(polarity_scores_final)
    polarity_scores_final = np.transpose(np.asarray(polarity_scores_final))
    collection['Angular_polarity_score'] = polarity_scores_final

    output = pd.DataFrame(columns=[])
    output['Object_id'] = collection['Reg_Props_Obj_Num'].astype(int)
    output['X_center'] = collection['X_center']
    output['Y_center'] = collection['Y_center']
    output['Distance_polarity_score'] = collection['Distance_polarity_score']
    output['Angular_polarity_score'] = collection['Angular_polarity_score']

    return output
def count_in_circle(imagen, r, centro=None):
    labels = ring_mask(imagen.shape[0], 0, r, center=centro)
    return nd.sum(np.zeros(imagen.shape), labels, 1)
Beispiel #50
0
def place_seed_points(image, img, mask, n_segments, spacing, q=99.99):
    """
    Method for placing seed points in an ROI

    Note:
    Optimal point placement problem is somewhat related to the k-center problem
     metric facility location (MFL)
     Maxmin facility location
    https://en.wikipedia.org/wiki/Facility_location_problem

    Parameters
    ----------
    image
    mask
    n_segments
    spacing

    Returns
    -------

    """

    segments_z = np.zeros(n_segments, dtype=np.int64)
    segments_y = np.zeros(n_segments, dtype=np.int64)
    segments_x = np.zeros(n_segments, dtype=np.int64)

    m_inv = np.copy(mask)
    nz = np.nonzero(m_inv)
    p = [np.min(nz[0]), np.min(nz[1]), np.min(nz[2])]
    pend = [np.max(nz[0]), np.max(nz[1]), np.max(nz[2])]
    # cropping to bounding box around ROI
    m_inv = m_inv[p[0]:pend[0] + 1, p[1]:pend[1] + 1, p[2]:pend[2] + 1]

    # SEED STEP 1:  n seeds are placed as far as possible from every other seed and the edge.

    theta = 0

    for ii in range(n_segments):

        # distance transform

        dtrans = distance_transform_edt(m_inv, sampling=spacing)
        dtrans = gaussian_filter(dtrans, sigma=2.0)

        # dtransg = ndi.gaussian_gradient_magnitude(dtrans, sigma=2.0)
        # plt.figure()
        # plt.imshow(mask[0, :, :])
        # plt.figure()
        # plt.imshow(m_inv[0, :, :])
        # plt.show()

        perc1 = np.percentile(dtrans, q=q)
        mask_dtrans = dtrans > perc1
        pdtrans, nb_labels = ndi.label(mask_dtrans)

        # plt.figure()
        # plt.imshow(pdtrans[0, :, :])
        # plt.show()

        # TODO temporarily just sticking to the original method until new method has been validated.
        if ii < 1E6:
            sizes = ndi.sum(mask_dtrans, pdtrans, range(nb_labels + 1))
            # Use the maximum locations for the first two points
            coords1 = np.nonzero(pdtrans == np.argmax(sizes))
            segments_z[ii] = round(np.mean(coords1[0]))
            segments_x[ii] = round(np.mean(coords1[1]))
            segments_y[ii] = round(np.mean(coords1[2]))

        else:
            # Define a vector that is used to produce a reference frame
            u = np.array(
                [segments_x[1] - segments_x[0], segments_y[1] - segments_y[0]])
            u = u / np.sqrt(np.sum(u**2))

            phi = np.zeros((nb_labels, ))
            for vv in range(nb_labels):
                coords1 = np.nonzero(pdtrans == (vv + 1))
                v = np.array([
                    np.mean(coords1[1]) - segments_x[0],
                    np.mean(coords1[2] - segments_y[0])
                ])
                v = v / np.sqrt(np.sum(v**2))

                # Directed angle
                va = np.arctan2(v[1], v[0])
                if va < 0:
                    va += 2 * np.pi
                ua = np.arctan2(u[1], u[0])
                if ua < 0:
                    ua += 2 * np.pi

                phi[vv] = va - ua
                if phi[vv] < 0:
                    phi[vv] += 2 * np.pi

            # Difference between previous theta and current theta
            phidiff = phi - theta
            # print("phidiff 1: ", phidiff)

            phidiff += (phidiff < 0) * 2 * np.pi
            # print("phidiff 2: ", phidiff)
            iphi = np.argmin(phidiff)

            theta = phi[iphi]
            # print("theta: ", theta)

            coords1 = np.nonzero(pdtrans == (iphi + 1))
            segments_z[ii] = round(np.mean(coords1[0]))
            segments_x[ii] = round(np.mean(coords1[1]))
            segments_y[ii] = round(np.mean(coords1[2]))

        # adding a new point
        m_inv[segments_z[ii], segments_x[ii], segments_y[ii]] = False

        # Plot: Illustrate the seed point selection method

        # plt.figure()
        # plt.imshow(img)
        # my_cmap = plt.cm.get_cmap('jet')  # get a copy of the gray color map
        # my_cmap.set_bad(alpha=0)  # s
        # d11 = dtrans[segments_z[ii], :, :]
        # d11[d11==0] = np.nan
        # plt.imshow(d11, cmap=my_cmap)
        # plt.contour(mask[segments_z[ii], :, :] == 1, contours=1, colors='red', linewidths=1)
        # plt.plot(segments_y[ii], segments_x[ii], marker='o', color='green')
        # plt.axis('off')
        # plt.show()

    segments_z = segments_z + p[0]
    segments_x = segments_x + p[1]
    segments_y = segments_y + p[2]

    segments_color = np.zeros((segments_z.shape[0], image.shape[3]))
    segments = np.concatenate([
        segments_z[..., np.newaxis], segments_x[..., np.newaxis],
        segments_y[..., np.newaxis], segments_color
    ],
                              axis=1)

    sz = np.ascontiguousarray(segments_z, dtype=np.int32)
    sx = np.ascontiguousarray(segments_x, dtype=np.int32)
    sy = np.ascontiguousarray(segments_y, dtype=np.int32)

    out1 = get_mpd(sz, sx, sy)
    step_z, step_x, step_y = out1[0], out1[1], out1[2]

    return segments, step_x, step_y, step_z
Beispiel #51
0
def objstats(args):
    # Open and read from image and segmentation
    try:
        img_ds = gdal.Open(args.image, gdal.GA_ReadOnly)
    except:
        logger.error('Could not open image: {}'.format(args.image))
        sys.exit(1)

    try:
        seg_ds = ogr.Open(args.segment, 0)
        seg_layer = seg_ds.GetLayer()
    except:
        logger.error('Could not open segmentation vector file: {}'.format(
            args.segment))
        sys.exit(1)

    cols, rows = img_ds.RasterXSize, img_ds.RasterYSize
    bands = range(1, img_ds.RasterCount + 1)
    if args.bands is not None:
        bands = args.bands

    # Rasterize segments
    logger.debug('About to rasterize segment vector file')
    img_srs = osr.SpatialReference()
    img_srs.ImportFromWkt(img_ds.GetProjectionRef())

    mem_raster = gdal.GetDriverByName('MEM').Create(
        '', cols, rows, 1, gdal.GDT_UInt32)
    mem_raster.SetProjection(img_ds.GetProjection())
    mem_raster.SetGeoTransform(img_ds.GetGeoTransform())

    # Create artificial 'FID' field
    fid_layer = seg_ds.ExecuteSQL(
        'select FID, * from "{l}"'.format(l=seg_layer.GetName()))
    gdal.RasterizeLayer(mem_raster, [1], fid_layer, options=['ATTRIBUTE=FID'])
    logger.debug('Rasterized segment vector file')

    seg = mem_raster.GetRasterBand(1).ReadAsArray()
    logger.debug('Read segmentation image into memory')
    mem_raster = None
    seg_ds = None

    # Get list of unique segments
    useg = np.unique(seg)

    # If calc is num, do only for 1 band
    out_bands = 0
    for stat in args.stat:
        if stat == 'num':
            out_bands += 1
        else:
            out_bands += len(bands)

    # Create output driver
    driver = gdal.GetDriverByName(args.format)
    out_ds = driver.Create(args.output, cols, rows, out_bands,
                           gdal.GDT_Float32)

    # Loop through image bands
    out_b = 0
    out_2d = np.empty_like(seg, dtype=np.float32)
    for i_b, b in enumerate(bands):
        img_band = img_ds.GetRasterBand(b)
        ndv = img_band.GetNoDataValue()
        band_name = img_band.GetDescription()
        if not band_name:
            band_name = 'Band {i}'.format(i=b)
        logger.info('Processing input band {i}, "{b}"'.format(
            i=b, b=band_name))

        img = img_band.ReadAsArray().astype(
            gdal_array.GDALTypeCodeToNumericTypeCode(img_band.DataType))
        logger.debug('Read image band {i}, "{b}" into memory'.format(
            i=b, b=band_name))

        for stat in args.stat:
            logger.debug('    calculating {s}'.format(s=stat))
            if stat == 'mean':
                out = ndimage.mean(img, seg, useg)
            elif stat == 'var':
                out = ndimage.variance(img, seg, useg)
            elif stat == 'num':
                # Remove from list of stats so it is only calculated once
                args.stat.remove('num')
                count = np.ones_like(seg)
                out = ndimage.sum(count, seg, useg)
            elif stat == 'sum':
                out = ndimage.sum(img, seg, useg)
            elif stat == 'min':
                out = ndimage.minimum(img, seg, useg)
            elif stat == 'max':
                out = ndimage.maximum(img, seg, useg)
            elif stat == 'mode':
                out = ndimage.labeled_comprehension(img, seg, useg,
                                                    scipy_mode,
                                                    out_2d.dtype, ndv)
            else:
                logger.error('Unknown stat. Not sure how you got here')
                sys.exit(1)

            # Transform to 2D
            out_2d = out[seg - seg.min()]

            # Fill in NDV
            if ndv is not None:
                out_2d[np.where(img == ndv)] = ndv

            # Write out the data
            out_band = out_ds.GetRasterBand(out_b + 1)
            out_band.SetDescription(band_name)
            if ndv is not None:
                out_band.SetNoDataValue(ndv)
            logger.debug('    Writing object statistic for band {b}'.format(
                    b=b + 1))
            out_band.WriteArray(out_2d, 0, 0)
            out_band.FlushCache()
            logger.debug('    Wrote out object statistic for band {b}'.format(
                    b=b + 1))
            out_b += 1

    out_ds.SetGeoTransform(img_ds.GetGeoTransform())
    out_ds.SetProjection(img_ds.GetProjection())

    img_ds = None
    seg_ds = None
    out_ds = None
    logger.info('Completed object statistic calculation')
Beispiel #52
0
def threshold_components(A_s, shape, min_size=5, max_size=np.inf, max_perc=.3):
    """
    Threshold components output of a CNMF algorithm (A matrices)

    Parameters:
    ----------

    A_s: list 
        list of A matrice output from CNMF

    min_size: int
        min size of the component in pixels

    max_size: int
        max size of the component in pixels

    max_perc: float        
        fraction of the maximum of each component used to threshold 


    Returns:
    -------        

    B_s: list of the thresholded components

    lab_imgs: image representing the components in ndimage format

    cm_s: center of masses of each components
    """

    B_s = []
    lab_imgs = []

    cm_s = []
    for A_ in A_s:
        print('*')
        max_comps = A_.max(0).todense().T
        tmp = []
        cm = []
        lim = np.zeros(shape)
        for idx, a in enumerate(A_.T):
            #create mask by thresholding to 50% of the max
            print(idx)
            mask = np.reshape(a.todense() > (max_comps[idx] * max_perc), shape)
            label_im, nb_labels = ndi.label(mask)
            sizes = ndi.sum(mask, label_im, list(range(nb_labels + 1)))
            l_largest = (label_im == np.argmax(sizes))
            cm.append(
                scipy.ndimage.measurements.center_of_mass(
                    l_largest, l_largest))
            lim[l_largest] = (idx + 1)
            #       #remove connected components that are too small
            mask_size = np.logical_or(sizes < min_size, sizes > max_size)
            if np.sum(mask_size[1:]) > 1:
                print(('removing ' + str(np.sum(mask_size[1:]) - 1) +
                       ' components'))
            remove_pixel = mask_size[label_im]
            label_im[remove_pixel] = 0

            label_im = (label_im > 0) * 1

            tmp.append(label_im.flatten())

        cm_s.append(cm)
        lab_imgs.append(lim)
        B_s.append(csc.csc_matrix(np.array(tmp)).T)

    return B_s, lab_imgs, cm_s
wall_centers = dict(zip([(l,r) for (l,r) in wall_cells], wall_csv_data[['wall_center_'+dim for dim in ['x','y','z']]].values))
wall_normals = dict(zip([(l,r) for (l,r) in wall_cells], wall_csv_data[['wall_normal_'+dim for dim in ['x','y','z']]].values))
# -- oriented labelpairs dict (ie. dict[i,j]==dict[j,i]):
pin1_orientations = dict(zip([(l,r) for (l,r) in wall_cells], wall_csv_data[sig_ch+'_orientation'].values))
pin1_intensities = dict(zip([(l,r) for (l,r) in wall_cells], wall_csv_data[sig_ch+'_signal'].values))
# pin1_shifts = dict(zip([(l,r) for (l,r) in wall_cells],wall_csv_data['pin1_shift'].values))
pin1_intensities_left = dict(zip([(l,r) for (l,r) in wall_cells], wall_csv_data[sig_ch+'_signal_left'].values))
pin1_intensities_right = dict(zip([(l,r) for (l,r) in wall_cells] wall_csv_data[sig_ch+'_signal_right'].values))

wall_pin1_vectors={}
for left_label, right_label in wall_cells:
    wall_pin1_vectors[(left_label, right_label)] = pin1_orientations[(left_label, right_label)] * wall_normals[(left_label, right_label)]


# cell_centers = dict(zip(np.unique(wall_cells),[p_img.image_property('barycenter')[c][:2] for c in np.unique(wall_cells)]))
cell_centers = dict(zip(np.unique(wall_cells), np.transpose([nd.sum(wall_csv_data['wall_center_'+dim].values ,wall_cells[:,0], index=np.unique(wall_cells)) for dim in ['x','y']])/nd.sum(np.ones_like(wall_cells[:,0]),wall_cells[:,0],index=np.unique(wall_cells))[:,np.newaxis]))

weights = np.ones_like(wall_cells[:,0]).astype(float)
weights *= np.array([wall_areas[(l,r)] for (l,r) in wall_cells])
# weights *= np.array([pin1_intensities[(l,r)] for (l,r) in wall_cells])
weights *= np.array([np.abs(pin1_intensities_left[(l,r)]-pin1_intensities_right[(l,r)]) for (l,r) in wall_cells])

wall_weights = dict(zip([(l,r) for (l,r) in wall_cells],weights))


cell_pin1_vectors = dict(zip(np.unique(wall_cells),np.transpose([nd.sum(np.array([wall_weights[(l,r)]*wall_pin1_vectors[(l,r)][k] for (l,r) in wall_cells]),wall_cells[:,0],index=np.unique(wall_cells)) for k in xrange(2)])/nd.sum(np.array([wall_weights[(l,r)] for (l,r) in wall_cells]),wall_cells[:,0],index=np.unique(wall_cells))[:,np.newaxis]))

cell_labels = p_img.image_property('barycenter').keys()[p_img.image_property('layer').values()==1]
X = microscope_orientation*p_img.image_property('barycenter').values()[:,0][p_img.image_property('layer').values()==1]
Y = microscope_orientation*p_img.image_property('barycenter').values()[:,1][p_img.image_property('layer').values()==1]
Z = microscope_orientation*p_img.image_property('barycenter').values()[:,2][p_img.image_property('layer').values()==1]
def sum_in_circle(imagen, r, centro=None):
    labels = ring_mask(imagen.shape[0], 0, r, center=centro)
    return nd.sum(imagen, labels, 1)
Beispiel #55
0
def test_sum05():
    for type in types:
        input = np.array([[1, 2], [3, 4]], type)
        output = ndimage.sum(input)
        assert_almost_equal(output, 10.0)
    def run(self, workspace):
        if self.show_window:
            workspace.display_data.col_labels = ("Image", "channel", "Object",
                                                 "Feature", "Mean", "Median",
                                                 "STD")
            workspace.display_data.statistics = statistics = []
        for im in self.images:
            image_name = im.name
            image = workspace.image_set.get_image(image_name.value,
                                                  must_be_grayscale=False)
            nchan = im.nchannels.value
            for channel in range(nchan):
                for object_name in [obj.name for obj in self.objects]:
                    # Need to refresh image after each iteration...
                    if nchan == 1:
                        img = image.pixel_data.copy()
                    else:
                        img = image.pixel_data[:, :, channel].squeeze().copy()
                    if image.has_mask:
                        masked_image = img.copy()
                        masked_image[~image.mask] = 0
                    else:
                        masked_image = img
                    objects = workspace.object_set.get_objects(
                        object_name.value)
                    nobjects = objects.count
                    integrated_intensity = np.zeros((nobjects, ))
                    integrated_intensity_edge = np.zeros((nobjects, ))
                    mean_intensity = np.zeros((nobjects, ))
                    mean_intensity_edge = np.zeros((nobjects, ))
                    std_intensity = np.zeros((nobjects, ))
                    std_intensity_edge = np.zeros((nobjects, ))
                    min_intensity = np.zeros((nobjects, ))
                    min_intensity_edge = np.zeros((nobjects, ))
                    max_intensity = np.zeros((nobjects, ))
                    max_intensity_edge = np.zeros((nobjects, ))
                    mass_displacement = np.zeros((nobjects, ))
                    lower_quartile_intensity = np.zeros((nobjects, ))
                    median_intensity = np.zeros((nobjects, ))
                    mad_intensity = np.zeros((nobjects, ))
                    upper_quartile_intensity = np.zeros((nobjects, ))
                    cmi_x = np.zeros((nobjects, ))
                    cmi_y = np.zeros((nobjects, ))
                    max_x = np.zeros((nobjects, ))
                    max_y = np.zeros((nobjects, ))
                    for labels, lindexes in objects.get_labels():
                        lindexes = lindexes[lindexes != 0]
                        labels, img = cpo.crop_labels_and_image(labels, img)
                        _, masked_image = cpo.crop_labels_and_image(
                            labels, masked_image)
                        outlines = cpmo.outline(labels)

                        if image.has_mask:
                            _, mask = cpo.crop_labels_and_image(
                                labels, image.mask)
                            masked_labels = labels.copy()
                            masked_labels[~mask] = 0
                            masked_outlines = outlines.copy()
                            masked_outlines[~mask] = 0
                        else:
                            masked_labels = labels
                            masked_outlines = outlines

                        lmask = masked_labels > 0 & np.isfinite(
                            img)  # Ignore NaNs, Infs
                        has_objects = np.any(lmask)
                        if has_objects:
                            limg = img[lmask]
                            llabels = labels[lmask]
                            mesh_y, mesh_x = np.mgrid[0:masked_image.shape[0],
                                                      0:masked_image.shape[1]]
                            mesh_x = mesh_x[lmask]
                            mesh_y = mesh_y[lmask]
                            lcount = fix(
                                nd.sum(np.ones(len(limg)), llabels, lindexes))
                            integrated_intensity[lindexes - 1] = \
                                fix(nd.sum(limg, llabels, lindexes))
                            mean_intensity[lindexes - 1] = \
                                integrated_intensity[lindexes - 1] / lcount
                            std_intensity[lindexes - 1] = np.sqrt(
                                fix(
                                    nd.mean((limg -
                                             mean_intensity[llabels - 1])**2,
                                            llabels, lindexes)))
                            min_intensity[lindexes - 1] = fix(
                                nd.minimum(limg, llabels, lindexes))
                            max_intensity[lindexes - 1] = fix(
                                nd.maximum(limg, llabels, lindexes))
                            # Compute the position of the intensity maximum
                            max_position = np.array(fix(
                                nd.maximum_position(limg, llabels, lindexes)),
                                                    dtype=int)
                            max_position = np.reshape(
                                max_position, (max_position.shape[0], ))
                            max_x[lindexes - 1] = mesh_x[max_position]
                            max_y[lindexes - 1] = mesh_y[max_position]
                            # The mass displacement is the distance between the center
                            # of mass of the binary image and of the intensity image. The
                            # center of mass is the average X or Y for the binary image
                            # and the sum of X or Y * intensity / integrated intensity
                            cm_x = fix(nd.mean(mesh_x, llabels, lindexes))
                            cm_y = fix(nd.mean(mesh_y, llabels, lindexes))

                            i_x = fix(nd.sum(mesh_x * limg, llabels, lindexes))
                            i_y = fix(nd.sum(mesh_y * limg, llabels, lindexes))
                            cmi_x[lindexes -
                                  1] = i_x / integrated_intensity[lindexes - 1]
                            cmi_y[lindexes -
                                  1] = i_y / integrated_intensity[lindexes - 1]
                            diff_x = cm_x - cmi_x[lindexes - 1]
                            diff_y = cm_y - cmi_y[lindexes - 1]
                            mass_displacement[lindexes - 1] = \
                                np.sqrt(diff_x * diff_x + diff_y * diff_y)
                            #
                            # Sort the intensities by label, then intensity.
                            # For each label, find the index above and below
                            # the 25%, 50% and 75% mark and take the weighted
                            # average.
                            #
                            order = np.lexsort((limg, llabels))
                            areas = lcount.astype(int)
                            indices = np.cumsum(areas) - areas
                            for dest, fraction in ((lower_quartile_intensity,
                                                    1.0 / 4.0),
                                                   (median_intensity,
                                                    1.0 / 2.0),
                                                   (upper_quartile_intensity,
                                                    3.0 / 4.0)):
                                qindex = indices.astype(
                                    float) + areas * fraction
                                qfraction = qindex - np.floor(qindex)
                                qindex = qindex.astype(int)
                                qmask = qindex < indices + areas - 1
                                qi = qindex[qmask]
                                qf = qfraction[qmask]
                                dest[lindexes[qmask] -
                                     1] = (limg[order[qi]] * (1 - qf) +
                                           limg[order[qi + 1]] * qf)
                                #
                                # In some situations (e.g. only 3 points), there may
                                # not be an upper bound.
                                #
                                qmask = (~qmask) & (areas > 0)
                                dest[lindexes[qmask] -
                                     1] = limg[order[qindex[qmask]]]
                            #
                            # Once again, for the MAD
                            #
                            madimg = np.abs(limg -
                                            median_intensity[llabels - 1])
                            order = np.lexsort((madimg, llabels))
                            qindex = indices.astype(float) + areas / 2.0
                            qfraction = qindex - np.floor(qindex)
                            qindex = qindex.astype(int)
                            qmask = qindex < indices + areas - 1
                            qi = qindex[qmask]
                            qf = qfraction[qmask]
                            mad_intensity[lindexes[qmask] -
                                          1] = (madimg[order[qi]] * (1 - qf) +
                                                madimg[order[qi + 1]] * qf)
                            qmask = (~qmask) & (areas > 0)
                            mad_intensity[lindexes[qmask] -
                                          1] = madimg[order[qindex[qmask]]]

                        emask = masked_outlines > 0
                        eimg = img[emask]
                        elabels = labels[emask]
                        has_edge = len(eimg) > 0
                        if has_edge:
                            ecount = fix(
                                nd.sum(np.ones(len(eimg)), elabels, lindexes))
                            integrated_intensity_edge[lindexes - 1] = \
                                fix(nd.sum(eimg, elabels, lindexes))
                            mean_intensity_edge[lindexes - 1] = \
                                integrated_intensity_edge[lindexes - 1] / ecount
                            std_intensity_edge[lindexes - 1] = \
                                np.sqrt(fix(nd.mean(
                                        (eimg - mean_intensity_edge[elabels - 1]) ** 2,
                                        elabels, lindexes)))
                            min_intensity_edge[lindexes - 1] = fix(
                                nd.minimum(eimg, elabels, lindexes))
                            max_intensity_edge[lindexes - 1] = fix(
                                nd.maximum(eimg, elabels, lindexes))
                    m = workspace.measurements
                    for category, feature_name, measurement in \
                            ((INTENSITY, INTEGRATED_INTENSITY, integrated_intensity),
                             (INTENSITY, MEAN_INTENSITY, mean_intensity),
                             (INTENSITY, STD_INTENSITY, std_intensity),
                             (INTENSITY, MIN_INTENSITY, min_intensity),
                             (INTENSITY, MAX_INTENSITY, max_intensity),
                             (INTENSITY, INTEGRATED_INTENSITY_EDGE, integrated_intensity_edge),
                             (INTENSITY, MEAN_INTENSITY_EDGE, mean_intensity_edge),
                             (INTENSITY, STD_INTENSITY_EDGE, std_intensity_edge),
                             (INTENSITY, MIN_INTENSITY_EDGE, min_intensity_edge),
                             (INTENSITY, MAX_INTENSITY_EDGE, max_intensity_edge),
                             (INTENSITY, MASS_DISPLACEMENT, mass_displacement),
                             (INTENSITY, LOWER_QUARTILE_INTENSITY, lower_quartile_intensity),
                             (INTENSITY, MEDIAN_INTENSITY, median_intensity),
                             (INTENSITY, MAD_INTENSITY, mad_intensity),
                             (INTENSITY, UPPER_QUARTILE_INTENSITY, upper_quartile_intensity),
                             (C_LOCATION, LOC_CMI_X, cmi_x),
                             (C_LOCATION, LOC_CMI_Y, cmi_y),
                             (C_LOCATION, LOC_MAX_X, max_x),
                             (C_LOCATION, LOC_MAX_Y, max_y)):

                        measurement_name = "%s_%s_%s_c%s" % (
                            category, feature_name, image_name.value,
                            str(channel + 1))
                        m.add_measurement(object_name.value, measurement_name,
                                          measurement)
                        if self.show_window and len(measurement) > 0:
                            statistics.append(
                                (image_name.value, 'c' + str(channel + 1),
                                 object_name.value, feature_name,
                                 np.round(np.mean(measurement), 3),
                                 np.round(np.median(measurement),
                                          3), np.round(np.std(measurement),
                                                       3)))
Beispiel #57
0
def test_sum07():
    labels = np.ones([0, 4], bool)
    for type in types:
        input = np.zeros([0, 4], type)
        output = ndimage.sum(input, labels=labels)
        assert_equal(output, 0.0)
Beispiel #58
0
def test_sum08():
    labels = np.array([1, 0], bool)
    for type in types:
        input = np.array([1, 2], type)
        output = ndimage.sum(input, labels=labels)
        assert_equal(output, 1.0)
Beispiel #59
0
def canny(image,
          sigma=1.,
          low_threshold=None,
          high_threshold=None,
          mask=None,
          use_quantiles=False):
    """Edge filter an image using the Canny algorithm.

    Parameters
    -----------
    image : 2D array
        Grayscale input image to detect edges on; can be of any dtype.
    sigma : float, optional
        Standard deviation of the Gaussian filter.
    low_threshold : float, optional
        Lower bound for hysteresis thresholding (linking edges).
        If None, low_threshold is set to 10% of dtype's max.
    high_threshold : float, optional
        Upper bound for hysteresis thresholding (linking edges).
        If None, high_threshold is set to 20% of dtype's max.
    mask : array, dtype=bool, optional
        Mask to limit the application of Canny to a certain area.
    use_quantiles : bool, optional
        If True then treat low_threshold and high_threshold as quantiles of the
        edge magnitude image, rather than absolute edge magnitude values. If True
        then the thresholds must be in the range [0, 1].

    Returns
    -------
    output : 2D array (image)
        The binary edge map.

    See also
    --------
    skimage.sobel

    Notes
    -----
    The steps of the algorithm are as follows:

    * Smooth the image using a Gaussian with ``sigma`` width.

    * Apply the horizontal and vertical Sobel operators to get the gradients
      within the image. The edge strength is the norm of the gradient.

    * Thin potential edges to 1-pixel wide curves. First, find the normal
      to the edge at each point. This is done by looking at the
      signs and the relative magnitude of the X-Sobel and Y-Sobel
      to sort the points into 4 categories: horizontal, vertical,
      diagonal and antidiagonal. Then look in the normal and reverse
      directions to see if the values in either of those directions are
      greater than the point in question. Use interpolation to get a mix of
      points instead of picking the one that's the closest to the normal.

    * Perform a hysteresis thresholding: first label all points above the
      high threshold as edges. Then recursively label any point above the
      low threshold that is 8-connected to a labeled point as an edge.

    References
    -----------
    .. [1] Canny, J., A Computational Approach To Edge Detection, IEEE Trans.
           Pattern Analysis and Machine Intelligence, 8:679-714, 1986
           :DOI:`10.1109/TPAMI.1986.4767851`
    .. [2] William Green's Canny tutorial
           https://en.wikipedia.org/wiki/Canny_edge_detector

    Examples
    --------
    >>> from skimage import feature
    >>> # Generate noisy image of a square
    >>> im = np.zeros((256, 256))
    >>> im[64:-64, 64:-64] = 1
    >>> im += 0.2 * np.random.rand(*im.shape)
    >>> # First trial with the Canny filter, with the default smoothing
    >>> edges1 = feature.canny(im)
    >>> # Increase the smoothing for better results
    >>> edges2 = feature.canny(im, sigma=3)
    """

    #
    # The steps involved:
    #
    # * Smooth using the Gaussian with sigma above.
    #
    # * Apply the horizontal and vertical Sobel operators to get the gradients
    #   within the image. The edge strength is the sum of the magnitudes
    #   of the gradients in each direction.
    #
    # * Find the normal to the edge at each point using the arctangent of the
    #   ratio of the Y sobel over the X sobel - pragmatically, we can
    #   look at the signs of X and Y and the relative magnitude of X vs Y
    #   to sort the points into 4 categories: horizontal, vertical,
    #   diagonal and antidiagonal.
    #
    # * Look in the normal and reverse directions to see if the values
    #   in either of those directions are greater than the point in question.
    #   Use interpolation to get a mix of points instead of picking the one
    #   that's the closest to the normal.
    #
    # * Label all points above the high threshold as edges.
    # * Recursively label any point above the low threshold that is 8-connected
    #   to a labeled point as an edge.
    #
    # Regarding masks, any point touching a masked point will have a gradient
    # that is "infected" by the masked point, so it's enough to erode the
    # mask by one and then mask the output. We also mask out the border points
    # because who knows what lies beyond the edge of the image?
    #
    check_nD(image, 2)
    dtype_max = dtype_limits(image, clip_negative=False)[1]

    if low_threshold is None:
        low_threshold = 0.1
    elif use_quantiles:
        if not (0.0 <= low_threshold <= 1.0):
            raise ValueError("Quantile thresholds must be between 0 and 1.")
    else:
        low_threshold = low_threshold / dtype_max

    if high_threshold is None:
        high_threshold = 0.2
    elif use_quantiles:
        if not (0.0 <= high_threshold <= 1.0):
            raise ValueError("Quantile thresholds must be between 0 and 1.")
    else:
        high_threshold = high_threshold / dtype_max

    if mask is None:
        mask = np.ones(image.shape, dtype=bool)

    def fsmooth(x):
        return img_as_float(gaussian(x, sigma, mode='constant'))

    smoothed = smooth_with_function_and_mask(image, fsmooth, mask)
    jsobel = ndi.sobel(smoothed, axis=1)
    isobel = ndi.sobel(smoothed, axis=0)
    abs_isobel = np.abs(isobel)
    abs_jsobel = np.abs(jsobel)
    magnitude = np.hypot(isobel, jsobel)

    #
    # Make the eroded mask. Setting the border value to zero will wipe
    # out the image edges for us.
    #
    s = generate_binary_structure(2, 2)
    eroded_mask = binary_erosion(mask, s, border_value=0)
    eroded_mask = eroded_mask & (magnitude > 0)
    #
    #--------- Find local maxima --------------
    #
    # Assign each point to have a normal of 0-45 degrees, 45-90 degrees,
    # 90-135 degrees and 135-180 degrees.
    #
    local_maxima = np.zeros(image.shape, bool)
    #----- 0 to 45 degrees ------
    pts_plus = (isobel >= 0) & (jsobel >= 0) & (abs_isobel >= abs_jsobel)
    pts_minus = (isobel <= 0) & (jsobel <= 0) & (abs_isobel >= abs_jsobel)
    pts = pts_plus | pts_minus
    pts = eroded_mask & pts
    # Get the magnitudes shifted left to make a matrix of the points to the
    # right of pts. Similarly, shift left and down to get the points to the
    # top right of pts.
    c1 = magnitude[1:, :][pts[:-1, :]]
    c2 = magnitude[1:, 1:][pts[:-1, :-1]]
    m = magnitude[pts]
    w = abs_jsobel[pts] / abs_isobel[pts]
    c_plus = c2 * w + c1 * (1 - w) <= m
    c1 = magnitude[:-1, :][pts[1:, :]]
    c2 = magnitude[:-1, :-1][pts[1:, 1:]]
    c_minus = c2 * w + c1 * (1 - w) <= m
    local_maxima[pts] = c_plus & c_minus
    #----- 45 to 90 degrees ------
    # Mix diagonal and vertical
    #
    pts_plus = (isobel >= 0) & (jsobel >= 0) & (abs_isobel <= abs_jsobel)
    pts_minus = (isobel <= 0) & (jsobel <= 0) & (abs_isobel <= abs_jsobel)
    pts = pts_plus | pts_minus
    pts = eroded_mask & pts
    c1 = magnitude[:, 1:][pts[:, :-1]]
    c2 = magnitude[1:, 1:][pts[:-1, :-1]]
    m = magnitude[pts]
    w = abs_isobel[pts] / abs_jsobel[pts]
    c_plus = c2 * w + c1 * (1 - w) <= m
    c1 = magnitude[:, :-1][pts[:, 1:]]
    c2 = magnitude[:-1, :-1][pts[1:, 1:]]
    c_minus = c2 * w + c1 * (1 - w) <= m
    local_maxima[pts] = c_plus & c_minus
    #----- 90 to 135 degrees ------
    # Mix anti-diagonal and vertical
    #
    pts_plus = (isobel <= 0) & (jsobel >= 0) & (abs_isobel <= abs_jsobel)
    pts_minus = (isobel >= 0) & (jsobel <= 0) & (abs_isobel <= abs_jsobel)
    pts = pts_plus | pts_minus
    pts = eroded_mask & pts
    c1a = magnitude[:, 1:][pts[:, :-1]]
    c2a = magnitude[:-1, 1:][pts[1:, :-1]]
    m = magnitude[pts]
    w = abs_isobel[pts] / abs_jsobel[pts]
    c_plus = c2a * w + c1a * (1.0 - w) <= m
    c1 = magnitude[:, :-1][pts[:, 1:]]
    c2 = magnitude[1:, :-1][pts[:-1, 1:]]
    c_minus = c2 * w + c1 * (1.0 - w) <= m
    local_maxima[pts] = c_plus & c_minus
    #----- 135 to 180 degrees ------
    # Mix anti-diagonal and anti-horizontal
    #
    pts_plus = (isobel <= 0) & (jsobel >= 0) & (abs_isobel >= abs_jsobel)
    pts_minus = (isobel >= 0) & (jsobel <= 0) & (abs_isobel >= abs_jsobel)
    pts = pts_plus | pts_minus
    pts = eroded_mask & pts
    c1 = magnitude[:-1, :][pts[1:, :]]
    c2 = magnitude[:-1, 1:][pts[1:, :-1]]
    m = magnitude[pts]
    w = abs_jsobel[pts] / abs_isobel[pts]
    c_plus = c2 * w + c1 * (1 - w) <= m
    c1 = magnitude[1:, :][pts[:-1, :]]
    c2 = magnitude[1:, :-1][pts[:-1, 1:]]
    c_minus = c2 * w + c1 * (1 - w) <= m
    local_maxima[pts] = c_plus & c_minus

    #
    #---- If use_quantiles is set then calculate the thresholds to use
    #
    if use_quantiles:
        high_threshold = np.percentile(magnitude, 100.0 * high_threshold)
        low_threshold = np.percentile(magnitude, 100.0 * low_threshold)

    #
    #---- Create two masks at the two thresholds.
    #
    high_mask = local_maxima & (magnitude >= high_threshold)
    low_mask = local_maxima & (magnitude >= low_threshold)

    #
    # Segment the low-mask, then only keep low-segments that have
    # some high_mask component in them
    #
    strel = np.ones((3, 3), bool)
    labels, count = label(low_mask, strel)
    if count == 0:
        return low_mask

    sums = (np.array(ndi.sum(high_mask, labels,
                             np.arange(count, dtype=np.int32) + 1),
                     copy=False,
                     ndmin=1))
    good_label = np.zeros((count + 1, ), bool)
    good_label[1:] = sums > 0
    output_mask = good_label[labels]
    return output_mask
import matplotlib.pyplot as plt

np.random.seed(1)
n = 10
l = 256
im = np.zeros((l, l))
points = l * np.random.random((2, n**2))
im[(points[0]).astype(np.int), (points[1]).astype(np.int)] = 1
im = ndimage.gaussian_filter(im, sigma=l / (4. * n))

mask = im > im.mean()

label_im, nb_labels = ndimage.label(mask)

# Find the largest connected component
sizes = ndimage.sum(mask, label_im, range(nb_labels + 1))
mask_size = sizes < 1000
remove_pixel = mask_size[label_im]
label_im[remove_pixel] = 0
labels = np.unique(label_im)
label_im = np.searchsorted(labels, label_im)

# Now that we have only one connected component, extract it's bounding box
slice_x, slice_y = ndimage.find_objects(label_im == 4)[0]
roi = im[slice_x, slice_y]

plt.figure(figsize=(4, 2))
plt.axes([0, 0, 1, 1])
plt.imshow(roi)
plt.axis('off')