def FilterMaxima(self, Minimum=None):
     if Minimum == None:
         Minimum = self.ManipulatedData.min()
     Seed = self.ManipulatedData - Minimum
     Mask = self.ManipulatedData
     self.Dilated = reconstruction(Seed, Mask, method="dilation")
     self.ManipulatedData = self.ManipulatedData - self.Dilated
def detectOpticDisc(image):
    kernel = octagon(10, 10)
    thresh = threshold_otsu(image[:,:,1])
    binary = image > thresh
    print binary.dtype
    luminance = convertToHLS(image)[:,:,2]
    t = threshold_otsu(luminance)
    t = erosion(luminance, kernel)
    
    
    labels = segmentation.slic(image[:,:,1], n_segments = 3)
    out = color.label2rgb(labels, image[:,:,1], kind='avg')
    skio.imshow(out)
    
    x, y = computeCentroid(t)
    print x, y
    rows, cols, _ = image.shape
    p1 = closing(image[:,:,1],kernel)
    p2 = opening(p1, kernel)
    p3 = reconstruction(p2, p1, 'dilation')
    p3 = p3.astype(np.uint8)
    #g = dilation(p3, kernel)-erosion(p3, kernel)
    #g = rank.gradient(p3, disk(5))
    g = cv2.morphologyEx(p3, cv2.MORPH_GRADIENT, kernel)
    #markers = rank.gradient(p3, disk(5)) < 10
    markers = drawCircle(rows, cols, x, y, 85)
    #markers = ndimage.label(markers)[0]
    #skio.imshow(markers)
    g = g.astype(np.uint8)
    #g = cv2.cvtColor(g, cv2.COLOR_GRAY2RGB)
    w = watershed(g, markers)
    print np.max(w), np.min(w)
    w = w.astype(np.uint8)
    #skio.imshow(w)
    return w
def dilation(data):
    """
    Use dilation to define the background. Not working too well...
    """
    image = gaussian_filter(data, 1)

    h = 1
    seed = np.copy(image) - h
    mask = image
    dilated = reconstruction(seed, mask, method='dilation')
    dilated = data - dilated

    fileIO.writeFITS(dilated, 'dilation.fits', int=False)

    #plot the image
    fig = plt.figure(figsize=(18, 10))
    ax1 = fig.add_subplot(121)
    ax2 = fig.add_subplot(122)

    ax1.set_title('Data')
    ax2.set_title('Background')

    im1 = ax1.imshow(np.log10(data), origin='lower', vmin=2., vmax=3.5, interpolation='none')
    im2 = ax2.imshow(dilated, origin='lower', interpolation='none')
    c1 = plt.colorbar(im1, ax=ax1, orientation='horizontal')
    c2 = plt.colorbar(im2, ax=ax2, orientation='horizontal')
    c1.set_label('$\log_{10}$(Counts [ADU])')
    c2.set_label('Dilation')
    plt.savefig('dilation.png')
    plt.close()

    return dilated.ravel()
Beispiel #4
0
def imfill(image):
    """
    Replicates the imfill function available within MATLAB.
    Based on the example provided in http://scikit-image.org/docs/dev/auto_examples/plot_holes_and_peaks.html#example-plot-holes-and-peaks-py.

    :param image):
        A 2D numpy array containing "holes". Darker pixels surrounded by brighter pixels.

    :return:
        A 2D numpy array of type Float with the "holes" from image filled.

    """

    seed = image.copy()

    # Define seed points and the start points for the erosion process.
    seed[1:-1, 1:-1] = image.max()

    # Define the mask; Probably unneeded.
    mask = image

    # Fill the holes
    filled = morphology.reconstruction(seed, mask, method='erosion')

    return filled
def get_stomata(max_proj_image, min_obj_size=200, max_obj_size=1000):
    """Performs image segmentation from a max_proj_image.
     Disposes of objects in range min_obj_size to
    max_obj_size

    :param max_proj_image: the maximum projection image
    :type max_proj_image: numpy.ndarray, uint16
    :param min_obj_size: minimum size of object to keep
    :type min_obj_size: int
    :param max_obj_size: maximum size of object to keep
    :type max_obj_size: int
    :returns: list of [ [coordinates of kept objects - list of slice objects],
                        binary object image - numpy.ndarray,
                        labelled object image - numpy.ndarray
                     ]

    """

    # pore_margin = 10
    # max_obj_size = 1000
    # min_obj_size = 200
    # for prop, value in segment_options:
    #     if prop == 'pore_margin':
    #         pore_margin = value
    #     if prop == 'max_obj_size':
    #         max_obj_size = value
    #     if prop == 'min_obj_size':
    #         min_obj_size = value
    #
    # print(pore_margin)
    # print(max_obj_size)
    # print(min_obj_size)

    #rescale_min = 50
    #rescale_max= 100
    #rescaled = exposure.rescale_intensity(max_proj_image, in_range=(rescale_min,rescale_max))
    rescaled = max_proj_image
    seed = np.copy(rescaled)
    seed[1:-1, 1:-1] = rescaled.max()
    #mask = rescaled
    #if gamma != None:
    #    rescaled = exposure.adjust_gamma(max_proj_image, gamma)
    #filled = reconstruction(seed, mask, method='erosion')
    closed = dilation(rescaled)
    seed = np.copy(closed)
    seed[1:-1, 1:-1] = closed.max()
    mask = closed


    filled = reconstruction(seed, mask, method='erosion')
    label_objects, nb_labels = ndimage.label(filled)
    sizes = np.bincount(label_objects.ravel())
    mask_sizes = sizes
    mask_sizes = (sizes > min_obj_size) & (sizes < max_obj_size)
    #mask_sizes = (sizes > 200) & (sizes < 1000)
    mask_sizes[0] = 0
    big_objs = mask_sizes[label_objects]
    stomata, _ = ndimage.label(big_objs)
    obj_slices = ndimage.find_objects(stomata)
    return [obj_slices, big_objs, stomata]
 def morpho_rec2(self, img, size=10):
     # internal gradient of the cells: 
     se = morphology.diamond(size)
     dil = morphology.dilation(img, se)
     rec = morphology.reconstruction(dil, img, method='erosion').astype(np.dtype('uint8'))
             
     return rec
 def h_minima(self, img, h):
     img_shift = img.copy()
     img_shift[img_shift >= 255 - h] = 255-h
     img_shift = img_shift + h
     rec = morphology.reconstruction(img_shift, img, method='erosion').astype(np.dtype('uint8'))
     diff = rec - img
     return diff
def bin_to_color(RGB_image, bin_image, feat_vec, marge=None, do_label=True):
    bin_image_copy = bin_image.copy()
    res = np.zeros(shape=(bin_image.shape[0], bin_image.shape[1], 3))
    if marge is not None:
        seed = np.zeros_like(bin_image_copy)
        seed[marge:-marge, marge:-marge] = 1
        mask = bin_image_copy.copy()
        mask[ mask > 0 ] = 1
        mask[marge:-marge, marge:-marge] = 1
        reconstructed = reconstruction(seed, mask, 'dilation')
        bin_image_copy[reconstructed == 0] = 0
    if do_label:
        bin_image_copy = label(bin_image_copy)

    if len(np.unique(bin_image_copy)) != 2:
        if len(np.unique(bin_image_copy)) == 1:
            if 0 in bin_image_copy:
                print "Return blank matrix."
                return bin_image_copy
            else:
                print "Error, must give a bin image."
    RegProp = regionprops(bin_image_copy)
    for i in range(len(RegProp)):
        mini_reg = RegProp[i]
        bin_image_copy[mini_reg.coords] = feat_vec[i]
    return bin_image_copy
def bin_analyser(RGB_image, bin_image, list_feature, marge=None, pandas_table=False, do_label=True):
    bin_image_copy = bin_image.copy()

    p = 0
    for feat in list_feature:
        p += feat.size

    if marge is not None and marge != 0:
        seed = np.zeros_like(bin_image_copy)
        seed[marge:-marge, marge:-marge] = 1
        mask = bin_image_copy.copy()
        mask[ mask > 0 ] = 1
        mask[marge:-marge, marge:-marge] = 1
        reconstructed = reconstruction(seed, mask, 'dilation')
        bin_image_copy[reconstructed == 0] = 0
    if do_label:
        bin_image_copy = label(bin_image_copy)

    if len(np.unique(bin_image_copy)) != 2:
        if len(np.unique(bin_image_copy)) == 1:
            if 0 in bin_image_copy:
                print "Return blank matrix. Change this shit"
                white_npy = np.zeros(shape=(1, p))
                if not pandas_table:
                    return white_npy
                else:
                    names = GetNames(list_feature) 
                    return pd.DataFrame(white_npy, columns=names)
            else:
                print "Error, must give a bin image."
    
    GrowRegion_N = NeededGrownRegion(list_feature)
    img = {0: bin_image_copy}
    RegionProp = {0: regionprops(bin_image_copy)}
    for val in GrowRegion_N:
        if val != 0:
            img[val] = GrowRegion(bin_image_copy, val)
            RegionProp[val] = regionprops(img[val])
    
    n = len(RegionProp[0])

    TABLE = np.zeros(shape=(n,p))
    for i in range(n):
        offset_ALL = 0
        for j, feat in enumerate(list_feature):
            tmp_regionprop = RegionProp[feat._return_n_extension()][i]
            off_tmp = feat.size      
            TABLE[i, (j + offset_ALL):(j + offset_ALL + off_tmp)] = feat._apply_region(tmp_regionprop ,RGB_image)

            offset_ALL += feat.size - 1

    if pandas_table:
        names = GetNames(list_feature)
        return pd.DataFrame(TABLE, columns=names)
    else:
        return TABLE
 def homogenize(self, img):
     img_sub = img.astype(np.dtype('float')) - self.settings.homogenize_settings['h']
     img_sub[img_sub<0] = 0
     img_sub = img_sub.astype(img.dtype)
     
     # seed and then mask
     print 'img: ', np.min(img), np.max(img)
     print 'img_sub: ', np.min(img_sub), np.max(img_sub)
     temp = morphology.reconstruction(img_sub, img)
     res = img - temp.astype(img.dtype)
     return res
def shadow_morphology(image):
    image_shape = image.shape
    _image = np.zeros((image_shape[0], image_shape[1]))
    _image = image
    seed = np.copy(_image)
    seed[1:-1, 1:-1] = image.max()
    mask = _image

    filled = reconstruction(seed, mask, method='erosion')
    result = filled - _image
    return result
    def local_maxima(self, img, h=1):
        img_sub = img.astype(np.dtype('float')) - h
        img_sub[img_sub<0] = 0
        img_sub = img_sub.astype(img.dtype)
        
        # seed and then mask
        temp = morphology.reconstruction(img_sub, img)
        res = img - temp.astype(img.dtype)
        res[res>0] = 255        
        res = res.astype(np.dtype('uint8'))

        return res    
Beispiel #13
0
def temblob(image,ind):

	"""
	Laplacian of gaussian blob detection for TEM images
	"""

	org = image[4:-256,4:-4]


	with warnings.catch_warnings():
		warnings.simplefilter("ignore")
		warnings.warn("user", UserWarning)

		igray = img_as_ubyte(rgb2gray(org))
		iinv = np.invert(igray)


	igaus = img_as_float(iinv)
	igaus = gaussian_filter(igaus, 1)
	h = 0.5
	sd = igaus - h
	msk = igaus
	dilat = reconstruction(sd, msk, method='dilation')
	hdome = igaus - dilat

	if ind == 'AgNP':
		kwargs = {}
		kwargs['threshold'] = 0.01
		kwargs['overlap'] = 0.4
		kwargs['min_sigma'] = 25
		kwargs['max_sigma'] = 50
		kwargs['num_sigma'] = 25
		calib = 500/(969-26)
		
	elif ind == 'AuNP':
		kwargs = {}
		kwargs['threshold'] = 0.01
		kwargs['overlap'] = 0.4
		kwargs['min_sigma'] = 18
		kwargs['max_sigma'] = 23
		kwargs['num_sigma'] = 5
		calib = 200/(777-23)
		
	else:
		warnmsg='Unable to identify keyword: {:}'.format(ind)
		warnings.warn(warnmsg, UserWarning)

	blobs = blob_log(hdome, **kwargs)
	diam = 2*sqrt(2)*blobs[:,-1]
	npdiam = [ind]
	npdiam.extend(calib*diam)

	return(npdiam)
Beispiel #14
0
def change_color(table, bin, color_vec, indice, res):
    x_cent, y_cent = table[indice, 3:5]
    X, Y = int(x_cent), int(y_cent)
    only_cell = np.zeros_like(bin)
    if bin[X, Y] != 1:
        X, Y = find_closest_cc(X, Y, bin)


    only_cell[X, Y] = 1
    only_cell = reconstruction(only_cell, bin)
    x, y = np.where(only_cell == 1)
    res[x, y] = color_vec
def bg_sub_signPreserveNorm(imageFile, path, extent, extension):
    vec = signPreserveNorm(imageFile, path, extent, extension)
    image = np.reshape(vec, (20,20), order="F")

    image = gaussian_filter(image, 1)
    seed = np.copy(image)
    seed[1:-1, 1:-1] = image.min()
    mask = image

    dilated = reconstruction(seed, mask, method='dilation')
    
    return np.ravel(image - dilated, order="F")
def opening_by_reconstruction(img, se):
    diffImg = True
    orig_img = img.copy()
    last_rec = img.copy()
    while diffImg:
        er_img = morphology.erosion(img, se)
        img = morphology.reconstruction(er_img, orig_img)
        if np.array_equal(last_rec, img):
            diffImg = False
        else:
            last_rec = img.copy()
    return last_rec
def HreconstructionErosion(prob_img, h):

    def making_top_mask(x, lamb=h):
	   return min(255, x + lamb)

    f = np.vectorize(making_top_mask)
    shift_prob_img = f(prob_img)

    seed = shift_prob_img
    mask = prob_img
    recons = reconstruction(
        seed, mask, method='erosion').astype(np.dtype('ubyte'))
    return recons
Beispiel #18
0
def ifcb_segment(img):
    Y = img_as_float(img)
    # step 1. local variance
    Yv = rescale_intensity(generic_filter(Y, np.var, footprint=disk(3)))
    # step 2. threshold local variance, aggressively
    Ye = Yv > (threshold_otsu(Yv) / 2.)
    # step 3. dark areas
    Yt = Y < threshold_otsu(Y)
    thin_blob = Ye | Yt
    # step 4. morphological reconstruction
    seed = np.copy(thin_blob)
    seed[1:-1,1:-1] = 1
    four=np.disk(1).astype(np.bool)
    return reconstruction(seed,thin_blob,method='erosion',selem=four)
def analyze_image():  
    
    global sin_par, dipole, multiple, contours
    
    # Change to the gray image
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        
    # Adaptive Thresholding
    block_size = 201
    img_binary = threshold_adaptive(img_gray, block_size, offset=7)    
    img_binary = img_binary.astype(dtype='uint8')*255
    
    # Remove the salt and pepper noise
    img_binary = cv2.medianBlur(img_binary,7)    
    
    # Fill the hole
    img_binary = 255-img_binary # Change the white/black for filling the hole     
    seed = np.copy(img_binary)
    seed[1:-1, 1:-1] = img_binary.max()
    mask = img_binary
    filled = reconstruction(seed, mask, method='erosion')
    filled = filled.astype(dtype = 'uint8')

    # Find the contours
    # For terminal use    
#    image, contours, hierarchy = cv2.findContours(filled,
#                                 cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)         
    # For Anaconda use    
    hierarchy, contours, hierarchy = cv2.findContours(filled,
                                  cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)        

    
    # Calculate the area (= len) of each contour
    area = np.zeros(len(contours))
    area_contour = np.zeros(len(contours))

    for kk in range(0,len(contours)):
        area[kk] = len(contours[kk])
        area_contour[kk] = cv2.contourArea(contours[kk])
  
    single = np.where((area_contour>200)&(area_contour<=624))[0]
    dipole = np.where((area_contour>624)&(area_contour<=936))[0]
    multiple = np.where(area_contour>936)[0]    
    
    # Analyze the single particle     
    sin_par = analyze_single(single,filled)
    
    # Draw the contours
    refreshFigure_contours(img,sin_par,dipole,multiple,contours)    
Beispiel #20
0
def remove_bg(args):
    """
    Remove background from reconstructions.
    """
    data, args, ind_start, ind_end = args
    
    for m in range(ind_end-ind_start):
        img = data[m, :, :]
        
        # first remove background.
        seed = np.copy(img)
        seed[1:-1, 1:-1] = img.min()
        img -= reconstruction(seed, img, method='dilation')
        
        data[m, :, :] = img
    return ind_start, ind_end, data
def subtract_background(img):
    """ Subtract background"""

    # Convert to float: Important for subtraction later which won't work with uint8
    """ image 1 """
    image = gaussian_filter(image, 1)

    seed = np.copy(image)
    seed[1:-1, 1:-1] = image.min()
    mask = image

    dilated = reconstruction(seed, mask, method='dilation')

    img_background_subtracted = image - dilated

    return(img_background_subtracted)
def shadow_morphology_land(image, csl_nir=csl_nir):
    image_shape = image.shape
    _image = np.zeros((image_shape[0]+2, image_shape[1]+2))
    _image[1:-1, 1:-1] = image
    print(image_shape, _image.shape)
    seed = np.copy(_image)
    seed[1:-1, 1:-1] = image.max()
    nir_low, nir_high = utils.calculate_percentile(csl_nir, 17.5), utils.calculate_percentile(csl_nir, 82.5)
    print(image.max(), image.mean(), nir_low, image.min())
    seed[0:1, :] = image.max() #image.mean() # nir_low
    seed[-1:, :] = image.max() #image.mean() # nir_low
    seed[:, 0:1] = image.max() #image.mean() # nir_low
    seed[:, -1:] = image.max() #image.mean() # nir_low
    mask = _image
    filled = reconstruction(seed, mask, method='erosion')
    result = filled - _image
    return result[1:-1, 1:-1] #, result, seed, mask
def fillholes(img, selem=None):
    """
    Fill holes in the grayscale input image using specified structuring element.

    args:
        img (ndarray): input image

    kwargs:
        selem (ndarray): structuring element (default = disk of radius 50)

    returns:
        ndarray: output image

    """
    if selem is None:
        selem = morphology.disk(50)
    seed = filters.rank.maximum(img, selem)
    return morphology.reconstruction(seed, img, method='erosion')
def create_word_mask(roi, threshold=None, rel_height=0.5):
    if threshold is None:
        threshold = threshold_otsu(roi)

    # binarize
    bw = roi > threshold

    # remove small objects
    lbl, _ = ndi.label(bw)
    sizes = np.bincount(lbl.ravel())
    mask_sizes = sizes > 20
    mask_sizes[0] = 0
    bwc = mask_sizes[lbl]

    # dilate
    bwcd = ndi.binary_dilation(bwc, diamond(1))

    # morphological reconstruction from the center part
    # to make sure that the mask contains that every considered object
    # is in fact anchored there
    x = bwc.sum(0)
    x[x < x.max() * 0.1] = 0
    nzx = x.nonzero()
    x_lb = nzx[0].min()
    x_ub = nzx[0].max()

    y = bwc.sum(1)
    y[y < y.max() * rel_height] = 0
    nzy = y.nonzero()
    y_lb = nzy[0].min()
    y_ub = nzy[0].max()
    if y_lb == y_ub:
        y_lb -= 3
        y_ub += 3

    seed = np.zeros(bwcd.shape, dtype=bool)
    seed[y_lb:y_ub, x_lb:x_ub] = True
    seed &= bwcd

    rec = reconstruction(seed, bwcd)

    return np.array(rec, dtype=bool)
def remove_spurs(mask, min_distance=9):
    '''
    Remove spurious mask features with reconstruction.
    '''

    # Distance transform of the mask
    dist_trans = nd.distance_transform_edt(mask)

    # We don't want to return local maxima within the minimum distance
    # Use reconstruction to remove.
    seed = dist_trans + min_distance
    reconst = mo.reconstruction(seed, dist_trans, method='erosion') - \
        min_distance

    if CV2_FLAG:
        return cv2.morphologyEx((reconst > 0).astype("uint8"),
                                cv2.MORPH_DILATE,
                                mo.disk(min_distance).astype("uint8")).astype(bool)
    else:
        return mo.dilation(reconst > 0, selem=mo.disk(min_distance))
Beispiel #26
0
def skeletonize_and_reconstruct(image, dfunc=None, sfunc=None):
    """
    Deconstruct image into skeleton and distance mask.  Alter the skeleton
    and/or distance mask and then reconstruct a new morphology.  With no
    altering functions passed, this function will not modify the image.

    :param image: data
    :type image: :py:class:`numpy.ndarray`

    :param dfunc: function that alters distance mask
    :type dfunc: func

    :param sfunc: function that alters skeleton
    :type sfunc: func

    :return: modified image data
    :rtype: :py:class:`numpy.ndarray`
    """
    image = (image > image.mean())
    # compute skeleton
    s0 = morphology.skeletonize(image)

    # compute mask
    d0 = ndimage.distance_transform_edt(image)

    # alter the mask
    if not dfunc is None:
        d0 = dfunc(image, s0, d0)

    # alter the skeleton
    if not sfunc is None:
        s0 = dfunc(image, s0, d0)

    # fix d-matrix
    d0[d0 <= s0] = s0[d0 <= s0]

    # recomute morphology
    r0 = morphology.reconstruction(s0, d0)

    # threshold
    return r0 > r0.mean()
Beispiel #27
0
def clean(image, threshold=0.1, niter=20, selem=np.ones((3,3))):
    """
    Clean the image through a series of steps:
    
      1. normalize
      2. erode
      3. threshold (trim)
      4. measure (connected components)
    
    Parameters
    ----------
    :image, 2D nd.array: 2D array of intensity data
    :threshold, float or iterable of floats: values to use for identifying
        peaks. All values should be in the range (0, 1), exclusive. If a
        single float is specified, *niter* should be specified.
    :niter, int: Number of times *threshold* should be applied. Default: 20.
        This has no effect if *threshold* is an iterable.
    :selem, 2D array: mask to use for the erosion step
    
    Returns
    -------
    The cleaned image: a 2D nd.array the same size/shape as the original.
    """
    filtered = normalized(image)
    try:
        niter = len(threshold)
    except TypeError:
        threshold = niter*[threshold]
    for trim in threshold:
        # erosion
        seed = np.copy(filtered)
        seed[:-1, :-1] = filtered.max()
        filtered = reconstruction(seed, filtered, method='erosion', selem=selem)
        # threshold
        filtered -= trim
        # identify the remaining connected regions and normalize each separately
        labelMasks = threshold_masks(filtered, 0.0, direction='gt')
        for m in labelMasks:
            filtered[m] = normalized(filtered[m])
    return filtered
Beispiel #28
0
def show_eyeballs(work_im):
    work_im = invert(work_im)
    work_im = gaussian_filter(work_im, 1.2)

    seed = np.copy(work_im)
    seed[1:-1, 1:-1] = work_im.min()
    mask = work_im

    dilated = reconstruction(seed, mask, method='dilation')

    image = work_im - dilated

    blobs_dog = None
    try:
        blobs_dog = blob_dog(image, min_sigma=5, max_sigma=10, threshold=.6)
    except:
        return None
    if blobs_dog.shape[0] == 0 or blobs_dog.shape[0] == 0:
        return None
    blobs_dog[:, 2] = blobs_dog[:, 2] * sqrt(2)

    return blobs_dog
Beispiel #29
0
def remove_background(args):
    """
    Remove background from reconstructed data.

    We use morphological reconstruction to create
    a background image, which we can subtract from
    the original image to isolate bright features.

    Parameters
    ----------
    data : ndarray, float32
        3-D reconstructed data with dimensions:
        [slices, pixels, pixels]

    Returns
    -------
    output : ndarray
        Background removed data.

    References
    ----------
    - `http://scikit-image.org/docs/dev/auto_examples/plot_regional_maxima.html \
    <http://scikit-image.org/docs/dev/auto_examples/plot_regional_maxima.html>`_
    """
    # Arguments passed by multi-processing wrapper
    ind, dshape, inputs = args

    # Function inputs
    data = mp.tonumpyarray(mp.shared_arr, dshape)  # shared-array

    for m in ind:
        img = data[m, :, :]

        # first remove background.
        seed = np.copy(img)
        seed[1:-1, 1:-1] = img.min()
        img -= reconstruction(seed, img, method='dilation')

        data[m, :, :] = img
Beispiel #30
0
def autemblob(image):

	"""
	Laplacian of gaussian blob detection for TEM images
	"""

	org = image[4:-256,4:-4]


	with warnings.catch_warnings():
		warnings.simplefilter("ignore")
		warnings.warn("user", UserWarning)

		igray = img_as_ubyte(rgb2gray(org))
		iinv = np.invert(igray)


	igaus = img_as_float(iinv)
	igaus = gaussian_filter(igaus, 1)
	h = 0.5
	sd = igaus - h
	msk = igaus
	dilat = reconstruction(sd, msk, method='dilation')
	hdome = igaus - dilat

	kwargs = {}
	kwargs['threshold'] = 0.01
	kwargs['overlap'] = 0.4
	kwargs['min_sigma'] = 18
	kwargs['max_sigma'] = 30
	kwargs['num_sigma'] = 12
	calib = 200/(777-23)

	blobs = blob_log(hdome, **kwargs)
	diam = 2*sqrt(2)*blobs[:,-1]
	npdiam = calib*diam

	return(npdiam)
Beispiel #31
0
def openrec(I, selem=m.disk(1)):
    B = m.erosion(I, selem=selem)
    F = m.reconstruction(B, I)
    return F
    dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 0)
    ret, sure_fg = cv2.threshold(dist_transform, 0.04 * dist_transform.max(),
                                 255, 0)

    labels_ws = watershed(-dist_transform, C_Core, mask=C_binary8)
    C_binary8_second = np.where(labels_ws > 0, C_binary8, 0)
    C_flag = np.where(labels_ws == 0, 0, labels_ws)
    #%
    #% Second round - divide the previous mask into 2 blobs
    ##################################################################
    seed = np.copy(C_binary8_second)
    seed[1:-1, 1:-1] = C_binary8_second.max()
    mask = C_binary8_second

    # fill all holes the do distance transform
    C_binary8_filled = reconstruction(seed, mask, method='erosion')
    C_binary8_filled8 = C_binary8_filled.astype(np.uint8)
    dist_transform_second = cv2.distanceTransform(C_binary8_filled8,
                                                  cv2.DIST_L2, 0)

    # Maximum them find maxima
    maximum_fil_result = ndimage.maximum_filter(dist_transform_second, size=1)

    min_distance_val = 1
    flag = 0
    #    maximum_fil_result = maximum_fil_result[I_idx[0]-200:I_idx[0]+200,I_idx[1]-200:I_idx[1]+200]
    while flag == 0:
        maximum_coordinates = peak_local_max(maximum_fil_result,
                                             min_distance=min_distance_val,
                                             indices=True)
        min_distance_val += 1
Beispiel #33
0
def THR(ivtNV, kernel, oroNV=None, high_terrain=600, verbose=True):
    '''Perform THR filtering process on 3d data

    Args:
        ivtNV (NCVAR): 3D or 4D input IVT data, with dimensions
            (time, lat, lon) or (time, level, lat, lon).
        kernel (list or tuple): list/tuple of integers specifying the shape of
            the kernel/structuring element used in the gray erosion process.

    Keyword Args:
        oroNV (NCVAR or None): 2D array, surface orographic data in meters.
            This optional surface height info is used to perform a separate
            reconstruction computation for areas with high elevations, and
            the results can be used to enhance the continent-penetration
            ability of landfalling ARs. Sensitivity in landfalling ARs is
            enhanced, other areas are not affected. Needs to have compatible
            (lat, lon) shape as <ivt>.
            If None, omit this process and treat areas with different heights
            all equally.

            New in v2.0.
        high_terrain (float): minimum orographic height (in m) to define as high
            terrain area, within which a separate reconstruction is performed.
            Only used if <oroNV> is not None.

            New in v2.0.
        verbose (bool): print some messages or not.

    Returns:
        ivtNV (NCVAR): 3D or 4D array, input <ivt>.
        ivtrecNV (NCVAR): 3D or 4D array, the reconstruction component from the
            THR process.
        ivtanoNV (NCVAR): 3D or 4D array, the difference between input <ivt>
            and <ivtrecNV>.
    '''

    ivt=ivtNV.data
    ndim=np.ndim(ivt)
    ivt=np.squeeze(ivt)

    #-------------------3d ellipsoid-------------------
    ele=funcs.get3DEllipse(*kernel)

    #################### use a cube to speed up ##############
    # empirical
    if kernel[0]>=16 or kernel[1]>=6:
        ele=np.ones(ele.shape)
    ##########################################################

    # reconstruction element: a 6-connectivity element
    rec_ele=np.zeros([3,3,3])
    rec_ele[0,1,1]=1
    rec_ele[1,:,1]=1
    rec_ele[1,1,:]=1
    rec_ele[2,1,1]=1

    if verbose:
        print('\n# <THR>: Computing erosion ...')

    lm=morphology.erosion(ivt, selem=ele)

    if verbose:
        print('\n# <THR>: Computing reconstruction ...')

    ivtrec=morphology.reconstruction(lm, ivt, method='dilation', selem=rec_ele)

    # perform an extra reconstruction over land
    if oroNV is not None:
        orodata=np.squeeze(oroNV.data)
        oro_rs=np.where(orodata>=high_terrain, 1, 0)
        oro_rs=oro_rs[None,...]
        oro_rs=np.repeat(oro_rs, len(ivt), axis=0)

        ivtrec_oro=morphology.reconstruction(lm*oro_rs, ivt, method='dilation',
                selem=rec_ele)
        ivtano=np.ma.maximum(ivt-ivtrec, (ivt-ivtrec_oro)*oro_rs)
    else:
        ivtano=ivt-ivtrec

    ivtrec=ivt-ivtano

    axislist=ivtNV.axislist

    #---------If inputs are 4d, also return 4d---------
    if ndim==4:
        ivt=ivt[:,None,...]
        ivtrec=ivtrec[:,None,...]
        ivtano=ivtano[:,None,...]

    ivtrecNV=funcs.NCVAR(ivtrec, 'ivt_rec', axislist, {'name': 'ivt_rec',
        'long_name': '%s, THR reconstruction' %(getattr(ivt, 'long_name', '')),
        'standard_name': '%s, THR reconstruction' %(getattr(ivt, 'long_name', '')),
        'units': getattr(ivt, 'units', '')})

    ivtanoNV=funcs.NCVAR(ivtano, 'ivt_ano', axislist, {'name': 'ivt_ano',
        'long_name': '%s, THR anomaly' %(getattr(ivt, 'long_name', '')),
        'standard_name': '%s, THR anomaly' %(getattr(ivt, 'long_name', '')),
        'units': getattr(ivt, 'units', '')})

    return ivtNV, ivtrecNV, ivtanoNV
def fill_image(in_image):
    seed = np.copy(in_image)
    seed[1:-1, 1:-1] = in_image.max()
    mask = in_image
    return reconstruction(seed, mask, method='erosion')
Beispiel #35
0
    def avg_over_trials(self):
        self.shaped = []
        single = int(self.period * self.framerate)
        self.shaped = np.reshape(self.divided, [
            self.nrepetitions, single, self.imageData.shape[1],
            self.imageData.shape[2]
        ])
        self.shapedavg = np.mean(self.shaped[1:], axis=0)
        pg.image(self.shapedavg)

        self.stddev = np.std(self.shaped[1:], axis=0)

        pg.image(np.log(self.stddev))
        image77 = np.copy(self.shapedavg)
        image77[np.where(np.log(self.stddev) < -5)] = 0
        # pg.image(image77, 'image77')
        # pg.image(np.sum(image77[1:16],axis=0),title='stim 1 max locus')
        # pg.image(np.sum(image77[121:136],axis=0),title='stim 2 max locus')

        image1 = np.sum(image77[1:21], axis=0)
        seed1 = np.copy(image1)
        seed1[1:-1, 1:-1] = image1.min()
        rec1 = reconstruction(seed1, image1, method='dilation')

        image2 = np.sum(image77[121:141], axis=0)
        seed2 = np.copy(image2)
        seed2[1:-1, 1:-1] = image2.min()
        rec2 = reconstruction(seed2, image2, method='dilation')

        # print 'shape of shapedavg, ', np.shape(self.shapedavg)
        self.filtshapedavg = scipy.ndimage.gaussian_filter(self.shapedavg,
                                                           sigma=[0, 3, 3],
                                                           order=0,
                                                           mode='reflect',
                                                           truncate=4.0)
        stim1 = self.shapedavg[1:16]
        stim2 = self.shapedavg[121:136]
        mpl.figure(1)
        mpl.imshow(np.amax(self.shapedavg, axis=0), cmap=matplotlib.cm.gray)
        top1 = np.mean(np.sum(stim1,
                              axis=0)) + 3 * np.std(np.sum(stim1, axis=0))
        top2 = np.mean(np.sum(stim2,
                              axis=0)) + 3 * np.std(np.sum(stim2, axis=0))
        print 'top: ', (top1, top2)
        loci1 = np.where(np.sum(stim1, axis=0) > top1)
        loci2 = np.where(np.sum(stim2, axis=0) > top2)
        # print 'loci1 dim:', np.shape(loci1)
        mpl.hold('on')
        mpl.plot(loci1[1], loci1[0], 'co')
        mpl.plot(loci2[1], loci2[0], 'rx')
        # pg.image(self.shapedavg, title = 'average over repetitions')
        mpl.figure(2)
        mpl.subplot(2, 3, 1)
        mpl.imshow(np.amax(self.shapedavg, axis=0),
                   cmap=matplotlib.cm.gray,
                   interpolation='nearest')
        mpl.colorbar()
        mpl.title('Average image')
        mpl.subplot(2, 3, 2)
        # mpl.imshow(np.amax(self.filtshapedavg,axis=0),cmap=matplotlib.cm.gray,interpolation=None)
        # mpl.subplot(2,3,4)
        mpl.imshow(np.amax(stim1, axis=0),
                   cmap=matplotlib.cm.Blues,
                   interpolation=None)
        mpl.title('Stim 1 (integral over time)')
        # maxamp = np.amax(stim1)
        # shstim1.set_clim = (0.0, maxamp)
        mpl.colorbar()

        mpl.subplot(2, 3, 3)
        mpl.imshow(np.amax(stim2, axis=0),
                   cmap=matplotlib.cm.Reds,
                   interpolation=None)
        mpl.title('Stim 2 (integral over time')
        mpl.colorbar()

        mpl.subplot(2, 3, 4)
        # mpl.hold('on')
        # mpl.title('Stim1, Stim2 overlaid')
        mpl.imshow(np.sum(stim1, axis=0),
                   cmap=matplotlib.cm.Blues,
                   interpolation=None)
        mpl.colorbar()
        mpl.subplot(2, 3, 5)

        mpl.imshow(np.sum(stim2, axis=0),
                   cmap=matplotlib.cm.Reds,
                   interpolation=None,
                   alpha=0.5)
        mpl.colorbar()

        # image1 = np.sum(stim1,axis=0)
        # seed1 = np.copy(image1)
        # seed1[1:-1, 1:-1] = image1.min()
        # rec1 = reconstruction(seed1,image1,method='dilation')

        # # mpl.subplot(2,3,6)
        # # mpl.imshow(image1-rec1,cmap=matplotlib.cm.Blues)

        # image2 = np.sum(stim2,axis=0)
        # seed2 = np.copy(image2)
        # seed2[1:-1, 1:-1] = image2.min()
        # rec2 = reconstruction(seed2,image2,method='dilation')

        # # mpl.subplot(2,3,3)
        # # mpl.imshow(image2-rec2,cmap=matplotlib.cm.Reds)
        # # mpl.figure(2)
        # # mpl.hold('on')

        # mpl.imshow(np.amax(self.shapedavg,axis=0),cmap=matplotlib.cm.gray, interpolation='nearest')
        # mpl.subplot(2,3,5)
        # mpl.imshow(image2-rec2,cmap=matplotlib.cm.Reds)
        # mpl.colorbar()
        # mpl.subplot(2,3,6)
        # mpl.imshow(image1-rec1,cmap=matplotlib.cm.Blues)
        # mpl.colorbar()
        # mpl.imshow(np.sum(stim1,axis=0),cmap=matplotlib.cm.Blues,interpolation=None)
        # mpl.imshow(np.sum(stim2,axis=0),cmap=matplotlib.cm.Reds,interpolation=None)
        # mpl.hold('off')
        # mpl.figure(3)
        # loci3 = np.where(image1>.8)
        # loci4 = np.where(image2>.8)
        # mpl.imshow(np.amax(self.shapedavg,axis=0),cmap=matplotlib.cm.gray)
        # mpl.hold('on')
        # mpl.plot(loci1[1],loci1[0],'ko')
        # mpl.plot(loci2[1],loci2[0],'rx')
        # mpl.title('std dev correction')

        return
def remove_segmented_nuc(image, mask, nuclei_size=2000):
    """Remove the nuclei we have already segmented in an image.

    1) We only keep the segmented nuclei. The missed ones and the background
    are set to 0 and removed from the original image, using a dilated mask.
    2) We reconstruct the missing nuclei by small dilatation. As we used the
    original image as a mask (the maximum allowed value at each pixel), the
    background pixels remain unchanged. However, pixels from the missing
    nuclei are partially reconstructed by the dilatation. This reconstructed
    image only differs from the original one where the nuclei have been missed.
    3) We subtract the reconstructed image from the original one.
    4) From the few pixels kept and restored from the missing nuclei, we build
    a binary mask (dilatation, small object removal).
    5) We apply this mask to the original image to get the original pixel
    intensity of the missing nuclei.
    6) We remove pixels with a too low intensity (using Otsu thresholding).

    Parameters
    ----------
    image : np.ndarray, np.uint
        Original image with shape (y, x).
    mask : np.ndarray,
        Result of the segmentation (with instance differentiation or not).
    nuclei_size : int
        Threshold above which we detect a nuclei.

    Returns
    -------
    unsegmented_nuclei : np.ndarray
        Image with shape (y, x) and the same dtype of the original image.
        Nuclei previously detected in the mask are removed.

    """
    # TODO fix the dtype of the mask
    # TODO start from the original image to manage the potential rescaling
    # TODO improve the threshold
    # TODO correct the word dilatation -> dilation
    # check parameters
    stack.check_array(image, ndim=2, dtype=[np.uint8, np.uint16])
    stack.check_array(mask,
                      ndim=2,
                      dtype=[np.uint8, np.uint16, np.int64, bool])

    # cast mask in np.int64 if it is binary
    if mask.dtype == bool or mask.dtype == np.uint16:
        mask = mask.astype(np.int64)

    # store original dtype
    original_dtype = image.dtype

    # dilate the mask
    s = disk(10, bool)
    dilated_mask = binary_dilation(mask, selem=s)

    # remove the unsegmented nuclei from the original image
    diff = image.copy()
    diff[dilated_mask == 0] = 0

    # reconstruct the missing nuclei by dilation
    s = disk(1)
    image_reconstructed = reconstruction(diff, image, selem=s)
    image_reconstructed = image_reconstructed.astype(original_dtype)

    # substract the reconstructed image from the original one
    image_filtered = image.copy()
    image_filtered -= image_reconstructed

    # build the binary mask for the missing nuclei
    missing_mask = image_filtered > 0
    missing_mask = remove_small_objects(missing_mask, nuclei_size)
    s = disk(20, bool)
    missing_mask = binary_dilation(missing_mask, selem=s)

    # get the original pixel intensity of the unsegmented nuclei
    unsegmented_nuclei = image.copy()
    unsegmented_nuclei[missing_mask == 0] = 0
    if original_dtype == np.uint8:
        unsegmented_nuclei[unsegmented_nuclei < 40] = 0
    else:
        unsegmented_nuclei[unsegmented_nuclei < 10000] = 0

    return unsegmented_nuclei
Beispiel #37
0
def main():
    parser=argparse.ArgumentParser(description='Image-file processing to identify total number of droplets',
                                 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('input_image', type=str, 
                      help='input image file')
    parser.add_argument('template_image', type=str, 
                      help='template image file')
    parser.add_argument('--outfile', type=str,
                      help='output image name.  Will default to input_image_processed.png')
    parser.add_argument('--cutoff_area', type=int,
                      help='rectangle size. only detected rectangles above this size will be displayed')
    parser.add_argument('--include', action='store_true', dest="include_edge", 
                      help='Include edge or boundary or border droplets; incomplete droplets found on the edge of the picture will be included too.')
    parser.add_argument("--exclude", action="store_false", dest="include_edge",
                      help='Exclude edge or boundary or border droplets; incomplete droplets found on the edge of the picture will be excluded.')
    parser.add_argument('--threshold', type=float, default=0.6,
                      help='thresholding parameter, tweak from 0 to 1 and visually examine results, depends on the image, default is 0.6')


    args=parser.parse_args()
    
    if args.outfile==None:
        args.outfile=''.join([path.splitext(args.input_image)[0],"_border_",str(args.include_edge),'_processed']) ## leaving out the file extension; adding it later just before writing out the image file

    filename=args.input_image
    rectsize=args.cutoff_area


    print "...."
    print "image file being processed..."
    print "..."
    
   
    from skimage import img_as_float
    image = io.imread(filename, flatten=True) # conver 3d to 2d image by using flatten=True
    image = img_as_float(image)
    #io.imshow(image)   ## check the image
    #io.show()   ## check the image

    from skimage.color import rgb2gray
    img_gray = rgb2gray(image)
    #io.imshow(img_gray)   ## check the image
    #io.show()   ## check the image
    
    image = gaussian_filter(image, 1)
    seed = np.copy(image)
    seed[1:-1, 1:-1] = image.min()
    mask = image
    
    dilated = reconstruction(seed, mask, method='dilation')
    

    """    
    fig, (ax0, ax1, ax2) = plt.subplots(nrows=1,
                                        ncols=3,
                                        figsize=(8, 2.5),
                                        sharex=True,
                                        sharey=True)
    
    ax0.imshow(image, cmap='gray')
    ax0.set_title('original image')
    ax0.axis('off')
    ax0.set_adjustable('box-forced')
    
    ax1.imshow(dilated, vmin=image.min(), vmax=image.max(), cmap='gray')
    ax1.set_title('dilated')
    ax1.axis('off')
    ax1.set_adjustable('box-forced')
    
    ax2.imshow(image - dilated, cmap='gray')
    ax2.set_title('image - dilated')
    ax2.axis('off')
    ax2.set_adjustable('box-forced')
    
    fig.tight_layout()
    """

    
    print "...."
    print "background correction..."
    print "..."
    
    h = 0.4
    seed = image - h
    dilated = reconstruction(seed, mask, method='dilation')
    hdome = image - dilated
    #io.imshow(hdome)   ## check the image
    #io.show()   ## check the image

    
    """
    fig, (ax0, ax1, ax2) = plt.subplots(nrows=1, ncols=3, figsize=(8, 2.5))
    yslice = 197
    
    ax0.plot(mask[yslice], '0.5', label='mask')
    ax0.plot(seed[yslice], 'k', label='seed')
    ax0.plot(dilated[yslice], 'r', label='dilated')
    ax0.set_ylim(-0.2, 2)
    ax0.set_title('image slice')
    ax0.set_xticks([])
    ax0.legend()
    
    ax1.imshow(dilated, vmin=image.min(), vmax=image.max(), cmap='gray')
    ax1.axhline(yslice, color='r', alpha=0.4)
    ax1.set_title('dilated')
    ax1.axis('off')
    
    ax2.imshow(hdome, cmap='gray')
    ax2.axhline(yslice, color='r', alpha=0.4)
    ax2.set_title('image - dilated')
    ax2.axis('off')
    
    fig.tight_layout()
    plt.show()
    """    
    
    
    print "...."
    print "edge detection..."
    print "..."
    
    im = hdome
    edges1 = feature.canny(image, sigma=3)
    edges2 = feature.canny(im, sigma=3)
    #io.imshow(edges1)   ## check the image
    #io.show()   ## check the image
    #io.imshow(edges2)   ## check the image
    #io.show()   ## check the image



    """
    # display results
    fig, (ax1, ax2, ax3) = plt.subplots(nrows=1, ncols=3, figsize=(8, 3),
                                        sharex=True, sharey=True)
    ax1.imshow(im, cmap=plt.cm.gray)
    ax1.axis('off')
    ax1.set_title('Original image', fontsize=10)
    
    ax2.imshow(edges1, cmap=plt.cm.gray)
    ax2.axis('off')
    ax2.set_title('Canny filter on original image, $\sigma=3$', fontsize=10)
    
    ax3.imshow(edges2, cmap=plt.cm.gray)
    ax3.axis('off')
    ax3.set_title('Canny filter on background subtracted image, $\sigma=3$', fontsize=10)
    
    fig.tight_layout()
    plt.show()
    """    
        

 
#    
### check how good are the original and processed images by selecting corresponding image here
#   
    image=image
    #image=edges2
    #image=hdome
    
    ## apply threshold
    thresh = threshold_otsu(image)
    bw = closing(image > thresh, square(2))
    #io.imshow(bw)   ## check the image
    #io.show()   ## check the image
    
    
    print "... are we including incomplete droplets at the edge of image?..."
    print ".............................................................", args.include_edge
    if args.include_edge is False:
        ## remove artifacts connected to image border
        cleared = clear_border(bw)    ## use this option to avoid the incomplete droplets at boundary/edge of picture frame
    else:
        cleared = bw  ## use this to use all droplets in the image; even incomplete ones at the boundary/edge of pciture frame
    
    
    #io.imshow(cleared)   ## check the image
    #io.show()   ## check the image
        
    
    # label image regions
    label_image = label(cleared)
    image_label_overlay = label2rgb(label_image, image=image)
    #io.imshow(image_label_overlay)   ## check the image
    #io.show()   ## check the image
    
    
    fig, ax = plt.subplots(figsize=(10, 6))
    #ax.imshow(label_image)
    #ax.imshow(image_label_overlay)


    targetimagefile=args.input_image
    templateimagefile=args.template_image
    thresholdval=args.threshold

    beads_count=0
    droplet_count=0
    outfile=0
    for region in regionprops(label_image):
        # take regions with large enough areas; should correspond to droplets        
        if region.area >= rectsize:
            # draw rectangle around segmented droplets
            droplet_count=droplet_count+1
            minr, minc, maxr, maxc = region.bbox
            rect = mpatches.Rectangle((minc, minr), maxc - minc, maxr - minr,
                                      fill=False, edgecolor='yellow', linewidth=2)
            #print region.bbox
            try:
                crop_image = image[minr-50:maxr+50, minc-50:maxc+50]  ## offset the bounding box in all directions; seems better this way based on visual examination
            except ValueError:  #raised if this subtraction takes it out of bounds
                pass
            finally:
                crop_image = image[minr:maxr, minc:maxc]
            #io.imshow(crop_image)   ## check the image
            #io.show()   ## check the image
            outfile=outfile+1
            ## improve this and instead of passing file names of whole images to the findtemplate function
            ## pass the cropped image that already exists here
            ## for now, not changing too drastically on something that works
            ## slow tweaks ensuring what works functionally well doesnt break down
            beads=findtemplate(templateimagefile, targetimagefile, region.bbox, outfile, thresholdval)
        
            ax.add_patch(rect)
              
    ax.set_axis_off()
    plt.tight_layout()
    outfile=args.outfile + "_totaldroplets-" + str(droplet_count) + ".png"
    print "...saving image file...."
    print outfile
    print "........................"
    plt.savefig(outfile)
    #plt.show()      ## activate this if you want to examine how the processed images are turning out and stop/start with different input parameters; key one being --cutoff_area

 
    
    print "...total droplets identified in the image:"
    print droplet_count
    print "..."
Beispiel #38
0
def join_segments_helper(L, Lines, combinedLines, segments2Join, max_scale,
                         pixelList):
    mask = Lines
    length = len(segments2Join)
    LabelNum = False
    minX = np.inf
    minY = np.inf
    maxX = 0
    maxY = 0
    for i in range(len(segments2Join)):
        X = pixelList[segments2Join[i]].coords
        minX = min(np.amin(X[:, 0]), minX)
        minY = min(np.amin(X[:, 1]), minY)
        maxX = max(np.amax(X[:, 0]), maxX)
        maxY = max(np.amax(X[:, 1]), maxY)
    # tested
    CroppedLines = Lines[minY:maxY + 1, minX:maxX + 1]

    for i in range(length - 1):
        bw1 = CroppedLines == pixelList[segments2Join[i]].label
        bw2 = CroppedLines == pixelList[segments2Join[i + 1]].label
        # TODO talk to baret, no quasi-euclidean transformation avaliable https://www.mathworks.com/help/images/ref/bwdist.html
        D1 = ndimage.distance_transform_edt(bw1 == 0)
        D2 = ndimage.distance_transform_edt(bw2 == 0)
        D = np.round((D1 + D2) * 32) / 32
        paths = matlabic_minima(D)
        paths = skeletonize(paths)

        tempMask = dilate(paths, ksize=10, i=1)

        mask = np.full(L.shape, False)

        mask[minY:maxY + 1, minX:maxX + 1] = tempMask
        AdjacentIndices = np.unique(combinedLines[mask])

        rows_to_remove = np.argwhere(AdjacentIndices == 0)
        mask_for_removal = np.ones(AdjacentIndices.shape)
        mask_for_removal[rows_to_remove] = False
        AdjacentIndices = AdjacentIndices[mask_for_removal.astype(np.bool)]

        if (len(AdjacentIndices) > 1) or (not np.any(np.logical_and(mask, L))):
            LabelNum = False
        else:
            mask = np.logical_and(mask, np.logical_not(combinedLines))
            bw1 = Lines == pixelList[segments2Join[i]].label
            bw2 = Lines == pixelList[segments2Join[i + 1]].label
            try:
                t = reconstruction(np.logical_or(bw1, bw2),
                                   np.logical_or(
                                       combinedLines == AdjacentIndices, mask),
                                   method='dilation')
            except Exception as e:
                t = reconstruction(np.logical_or(bw1, bw2),
                                   np.logical_or(
                                       combinedLines == AdjacentIndices, mask),
                                   method='dilation')
            fitting = approximate_using_piecewise_linear_pca(
                t.astype(np.int), 1, [], 0)
            if fitting[0] < 0.8 * max_scale:
                LabelNum = AdjacentIndices
            else:
                LabelNum = False
    return mask, LabelNum
Beispiel #39
0

# Edge detection
print("Edge detection")
sobel = filters.sobel(Contrast_image)
io.imshow(sobel)
plt.figure()

# Gradient magnitude 

Sobel_gradient_array = filters.rank.gradient(sobel,disk(1))

# Compute the opening-by-reconstruction (erode)
print("Compute the opening-by-reconstruction (erode)")
Image_erosion = erosion(Contrast_image,disk(1))
Image_by_reconstruction_opening = reconstruction(Image_erosion,Contrast_image)
io.imshow(Image_by_reconstruction_opening)
plt.figure()

# Compute the closing-by-reconstruction (dilation)
print("Compute the closing-by-reconstruction (dilation)")
Image_dilation = dilation(Image_by_reconstruction_opening,disk(1))
Image_by_reconstruction_closing = reconstruction(util.invert(Image_dilation),util.invert(Image_by_reconstruction_opening))
Image_by_reconstruction_closing = util.invert(Image_by_reconstruction_closing)
io.imshow(Image_by_reconstruction_closing)
plt.figure()

# Regional max

print("REGIONAL MAX")
Beispiel #40
0
 def extract_maxima_positions(cls, image):
     seed_min = image - 1
     dilated = reconstruction(seed_min, image, method='dilation')
     cleaned_image = image - dilated
     return np.where(cleaned_image > 0)[::-1]
Original=sobel(Original)

Original=np.copy(Original)

#Dilation
Dilation= dilation(Original)

#show_images([Original,Dilation ],["Original","Dilation"])

#Filling
seed = np.copy(Dilation)
seed[1:-1,1:-1] = Dilation.max()
mask = Dilation

filled = reconstruction(seed, mask, method='erosion')
filled = filled >0.14
#show_images([filled])




#Erosion
filled = np.copy(filled)
rosion = erosion(filled)
rosion = erosion(rosion)


#show_images([filled,rosion])

Beispiel #42
0
def place_field(firing_map, **kwargs):
    '''
    Locate place fields on a firing map.

    Identifies place fields in 2D firing map. Placefields are identified by
    using an adaptive threshold. The idea is that we start with a peak value as
    the threshold. Then we gradually decrease the threshold until the field
    area doesn't change any more or the area explodes (this means the threshold
    is too low).

    Parameters
    ----------
    firing_map: np.ndarray or np.ma.MaskedArray
        smoothed rate map.
        If supplied as an np.ndarray, it is assumed that the map takes values
        of np.nan at locations of zero occupancy. If supplied as an np.ma.MaskedArray,
        it is assumed that the map is masked at locations of zero occupancy
    
    Other Parameters
    ----------------
    min_bins: int
        Fields containing fewer than this many bins will be discarded. Default 9
    min_peak: float
        Fields with a peak firing rate lower than this absolute value will
        be discarded. Default 1 Hz
    min_mean: float
        Fields with a mean firing rate lower than this absolute value will
        be discarded. Default 0 Hz
    init_thresh: float
        Initial threshold to search for fields from. Must be in the range [0, 1].
        Default 0.96
    search_method: str
        Peak detection finding method. By default, use `skimage.morphology.local_maxima`
        Acceptable values are defined in `opexebo.defaults`. Not required if 
        peak_coords are provided
    peak_coords: array-like
        List of peak co-ordinates to consider instead of auto detection. [y, x].
        Default None

    Returns
    -------
    fields: list of dict
        coords: np.ndarray
            Coordinates of all bins in the firing field
        peak_coords: np.ndarray
            Coordinates peak firing rate [y,x]
        centroid_coords: np.ndarray
            Coordinates of centroid (decimal) [y,x]
        area: int
            Number of bins in firing field. [bins]
        bbox: tuple
            Coordinates of bounding box including the firing field
            (y_min, x_min, y_max, y_max)
        mean_rate: float
            mean firing rate [Hz]
        peak_rate: float
            peak firing rate [Hz]
        map: np.ndarray
            Binary map of arena. Cells inside firing field have value 1, all
            other cells have value 0
    fields_map : np.ndarray
        labelled integer image (i.e. background = 0, field1 = 1, field2 = 2, etc.)

    Raises
    ------
    ValueError
        Invalid input arguments
    NotImplementedError
        non-defined peack searching methods

    Notes
    --------
    BNT.+analyses.placefieldAdaptive

    https://se.mathworks.com/help/images/understanding-morphological-reconstruction.html

    Copyright (C) 2018 by Vadim Frolov, (C) 2019 by Simon Ball, Horst Obenhaus
    '''
    ##########################################################################
    #####                   Part 1: Handle inputs
    # Get keyword arguments
    min_bins = kwargs.get("min_bins", default.firing_field_min_bins)
    min_peak = kwargs.get("min_peak", default.firing_field_min_peak)
    min_mean = kwargs.get("min_mean", default.firing_field_min_mean)
    init_thresh = kwargs.get("init_thresh", default.initial_search_threshold)
    search_method = kwargs.get("search_method", default.search_method)
    peak_coords = kwargs.get("peak_coords", None)
    debug = kwargs.get("debug", False)

    if not 0 < init_thresh <= 1:
        raise ValueError("Keyword 'init_thresh' must be in the range [0, 1]."\
                         f" You provided {init_thresh}")
    try:
        search_method = search_method.lower()
    except AttributeError:
        raise ValueError("Keyword 'search_method' is expected to be a string"\
                         f" You provided a {type(search_method)} ({search_method})")
    if search_method not in default.all_methods:
        raise ValueError("Keyword 'search_method' must be left blank or given a"\
                         f" value from the following list: {default.all_methods}."\
                         f" You provided '{search_method}'.")

    global_peak = np.nanmax(firing_map)
    if np.isnan(global_peak) or global_peak == 0:
        if debug:
            print(f"Terminating due to invalid global peak: {global_peak}")
        return [], np.zeros_like(firing_map)

    # Construct a mask of bins that the animal never visited (never visited -> true)
    # This needs to account for multiple input formats.
    # The standard that I want to push is that firing_map is type MaskedArray
    # In this case, the cells that an animal never visited have firing_map.mask[cell]=True
    # while firing_map.data[cell] PROBABLY = 0
    # An alternative is the BNT standard, where firing_map is an ndarray
    # In this case, the cells never visited are firing_map[cell] = np.nan
    # In either case, we need to get out the following:
    # finite_firing_map is an ndarray (float) where unvisted cells have a
    # meaningfully finite value (e.g. zero, or min())
    # mask is an ndarray (bool) where unvisited cells are True, all other cells are False

    if isinstance(firing_map, np.ma.MaskedArray):
        occupancy_mask = firing_map.mask
        finite_firing_map = firing_map.data.copy()
        finite_firing_map[np.isnan(firing_map.data)] = 0

    else:
        occupancy_mask = np.zeros_like(firing_map).astype('bool')
        occupancy_mask[np.isnan(firing_map)] = True
        finite_firing_map = firing_map.copy()
        finite_firing_map[np.isnan(firing_map)] = 0

    structured_element = morphology.disk(1)
    image_eroded = morphology.erosion(finite_firing_map, structured_element)
    fmap = morphology.reconstruction(image_eroded, finite_firing_map)

    ##########################################################################
    #####                   Part 2: find local maxima
    # Based on the user-requested search method, find the co-ordinates of local maxima
    if peak_coords is None:
        if search_method == default.search_method:
            peak_coords = opexebo.general.peak_search(fmap, **kwargs)
        elif search_method == "sep":
            #fmap = finite_firing_map
            peak_coords = opexebo.general.peak_search(fmap, **kwargs)
        else:
            raise NotImplementedError("The search method you have requested (%s) is"\
                                      " not yet implemented" % search_method)

    # obtain value of found peaks
    found_peaks = finite_firing_map[peak_coords[:, 0], peak_coords[:, 1]]

    # leave only peaks that satisfy the threshold
    good_peaks = (found_peaks >= min_peak)
    peak_coords = peak_coords[good_peaks, :]

    ##########################################################################
    #####    Part 3: from local maxima get fields by expanding around maxima
    max_value = np.max(fmap)
    # prevent peaks with small values from being detected
    # SWB - This causes problems where a local peak is next to a cell that the animal never went
    # As that risks the field becoming the entire null region
    # Therefore, adding 2nd criterion to avoid adding information where none was actually known.
    fmap[np.logical_and(fmap < min_peak, fmap > 0.01)] = max_value * 1.5

    # this can be confusing, but this variable is just an index for the vector
    # peak_linear_ind
    peaks_index = np.arange(len(peak_coords))
    fields_map = np.zeros(fmap.shape, dtype=np.integer)
    field_id = 1
    for i, peak_rc in enumerate(peak_coords):
        # peak_rc == [row, col]

        # select all peaks except the current one
        other_fields = peak_coords[peaks_index != i]
        if other_fields.size > 0:
            other_fields_linear = np.ravel_multi_index(
                multi_index=(other_fields[:, 0], other_fields[:, 1]),
                dims=fmap.shape,
                order='F')
        else:
            other_fields_linear = []

        used_th = init_thresh
        res = _area_change(fmap, occupancy_mask, peak_rc, used_th,
                           used_th - 0.02, other_fields_linear)
        initial_change = res['acceleration']
        area2 = res['area2']
        first_pixels = np.nan
        if np.isnan(initial_change):
            for j in np.linspace(used_th + 0.01, 1., 4):
                # Thresholds get higher, area should tend downwards to 1
                # (i.e. only including the actual peak)
                res = _area_change(fmap, occupancy_mask, peak_rc, j, j - 0.01,
                                   other_fields_linear)
                initial_change = res['acceleration']
                area1 = res['area1']
                area2 = res['area2']
                # initial_change is the change from area1 to area 2
                # area2>area1 -> initial_change > 1
                # area2<area1 -> initial_change < 1
                # area 2 is calculated with lower threshold - should usually be larger
                first_pixels = res['first_pixels']
                if not np.isnan(initial_change) and initial_change > 0:
                    # True is both area1 and area2 are valid
                    # Weird conditonal from Vadim - initial change will EITHER:
                    # be greater than zero (can't get a negative area to give negative % change)
                    # OR be NaN (which will always yield false when compared to a number)
                    used_th = j - 0.01
                    break

            if np.isnan(initial_change) and not np.isnan(area1):
                # For the final change
                pixels = np.unravel_index(first_pixels, fmap.shape, 'F')
                fmap[pixels] = max_value * 1.5
                fields_map[pixels] = field_id
                field_id = field_id + 1

            if np.isnan(initial_change):
                # failed to extract the field
                # Do nothing and continue for-loop
                pass

        pixel_list = _expand_field(fmap, occupancy_mask, peak_rc,
                                   initial_change, area2, other_fields_linear,
                                   used_th)
        if np.any(np.isnan(pixel_list)):
            _, pixel_list, _ = _area_for_threshold(fmap, occupancy_mask,
                                                   peak_rc, used_th + 0.01,
                                                   other_fields_linear)
        if len(pixel_list) > 0:
            pixels = np.unravel_index(pixel_list, fmap.shape, 'F')
        else:
            pixels = []

        fmap[pixels] = max_value * 1.5
        fields_map[pixels] = field_id
        field_id = field_id + 1

    ##########################################################################
    #####     Part 4: Determine which, if any, fields meet filtering criteria
    regions = measure.regionprops(fields_map)

    fields = []
    fields_map = np.zeros(
        finite_firing_map.shape)  # void it as we can eliminate some fields

    for region in regions:
        field_map = finite_firing_map[region.coords[:, 0], region.coords[:, 1]]
        mean_rate = np.nanmean(field_map)
        num_bins = len(region.coords)

        peak_rate = np.nanmax(field_map)
        peak_relative_index = np.argmax(field_map)
        peak_coords = region.coords[peak_relative_index, :]

        if num_bins >= min_bins and mean_rate >= min_mean:
            field = {}
            field['coords'] = region.coords
            field['peak_coords'] = peak_coords
            field['area'] = region.area
            field['bbox'] = region.bbox
            field['centroid_coords'] = region.centroid
            field['mean_rate'] = mean_rate
            field['peak_rate'] = peak_rate
            mask = np.zeros(finite_firing_map.shape)
            mask[region.coords[:, 0], region.coords[:, 1]] = 1
            field['map'] = mask

            fields.append(field)

            fields_map[region.coords[:, 0], region.coords[:, 1]] = len(fields)
        elif debug:
            # Print out some information about *why* the field failed
            if num_bins < min_bins:
                print("Field size too small (%d)" % num_bins)
            if mean_rate < min_mean:
                print("Field mean rate too low (%.2f Hz)" % mean_rate)
        else:
            # Field too small and debugging information not needed
            # Do nothing
            pass
    #fields_map = np.ma.masked_where(occupancy_mask, fields_map)
    return (fields, fields_map)
    def process_wrapper(self, **kwargs):
        """
        Filtering regional maxima:

        From scikit image - Filtering regional maxima: Perform a morphological reconstruction of an image.

        Morphological reconstruction by dilation is similar to basic morphological dilation: high-intensity values will
        replace nearby low-intensity values. The basic dilation operator, however, uses a structuring element to
        determine how far a value in the input image can spread. In contrast, reconstruction uses two images: a “seed”
        image, which specifies the values that spread, and a “mask” image, which gives the maximum allowed value at
        each pixel. The mask image, like the structuring element, limits the spread of high-intensity values.
        Reconstruction by erosion is simply the inverse: low-intensity values spread from the seed image and are
        limited by the mask image, which represents the minimum allowed value.

        Alternatively, you can think of reconstruction as a way to isolate the connected regions of an image.
        For dilation, reconstruction connects regions marked by local maxima in the seed image: neighboring pixels
        less-than-or-equal-to those seeds are connected to the seeded region.
        Local maxima with values larger than the seed image will get truncated to the seed value.
        Real time : True

        Keyword Arguments (in parentheses, argument name):
            * Select source file type (source_file):
            * Channel (channel):
            * Offset for uneven image border (brightness_offset): Use when image border perimeter has uneven brightness
            * Overlay text on top of images (text_overlay): Draw description text on top of images
            * Activate tool (enabled): Toggle whether or not tool is active
            * Select pseudo color map (color_map):
            * use color palette (use_palette): Use color palette in postprocessing
            * Normalize channel (normalize):
            * Real time (real_time): Set if tool reacts in real time
        """

        wrapper = self.init_wrapper(**kwargs)
        if wrapper is None:
            return False

        res = False
        try:
            if self.get_value_of("enabled") == 1:
                brightness_offset = self.get_value_of("brightness_offset") / 100
                channel = self.get_value_of("channel")
                text_overlay = self.get_value_of("text_overlay") == 1
                color_map = self.get_value_of("color_map")
                _, color_map = color_map.split("_")
                normalize = self.get_value_of("normalize") == 1

                img = self.wrapper.current_image
                c = wrapper.get_channel(img, channel)
                if c is None:
                    self.do_channel_failure(channel)
                    return

                image = img_as_float(c)
                image = gaussian_filter(image, 1)

                seed = image - brightness_offset
                seed[1:-1, 1:-1] = image.min()
                mask = image

                dilated = reconstruction(seed, mask, method="dilation")
                dilated = self.to_uint8(dilated, normalize=normalize)
                if self.get_value_of("use_palette") == 1:
                    dilated = cv2.applyColorMap(dilated, int(color_map))

                self.result = dilated

                img_name = f"frm_{self.input_params_as_str()}"
                if text_overlay:
                    wrapper.store_image(
                        self.result,
                        img_name,
                        text_overlay=self.input_params_as_str(
                            exclude_defaults=False,
                            excluded_params=("progress_callback",),
                        ).replace(", ", "\n"),
                    )
                else:
                    wrapper.store_image(self.result, img_name, text_overlay=text_overlay)
            else:
                wrapper.store_image(wrapper.current_image, "source")

            res = True
        except Exception as e:
            wrapper.error_holder.add_error(
                new_error_text=f'Failed to process {self. name}: "{repr(e)}"',
                new_error_level=35,
                target_logger=logger,
            )
            res = False
        else:
            pass
        finally:
            return res
def imimposemin(I, BW, conn=None, max_value=255):
    if not I.ndim in (2, 3):
        raise Exception("'I' must be a 2-D or 3D array.")

    if BW.shape != I.shape:
        raise Exception("'I' and 'BW' must have the same shape.")

    if BW.dtype is not bool:
        BW = BW != 0

    # set default connectivity depending on whether the image is 2-D or 3-D
    if conn == None:
        if I.ndim == 3:
            conn = 26
        else:
            conn = 8
    else:
        if conn in (4, 8) and I.ndim == 3:
            raise Exception("'conn' is invalid for a 3-D image.")
        elif conn in (6, 18, 26) and I.ndim == 2:
            raise Exception("'conn' is invalid for a 2-D image.")

    # create structuring element depending on connectivity
    if conn == 4:
        selem = disk(1)
    elif conn == 8:
        selem = square(3)
    elif conn == 6:
        selem = ball(1)
    elif conn == 18:
        selem = ball(1)
        selem[:, 1, :] = 1
        selem[:, :, 1] = 1
        selem[1] = 1
    elif conn == 26:
        selem = cube(3)

    fm = I.astype(float)

    try:
        fm[BW]                 = -math.inf
        fm[np.logical_not(BW)] = math.inf
    except:
        fm[BW]                 = -float("inf")
        fm[np.logical_not(BW)] = float("inf")

    if I.dtype == float:
        I_range = np.amax(I) - np.amin(I)

        if I_range == 0:
            h = 0.1
        else:
            h = I_range*0.001
    else:
        h = 1

    fp1 = I + h

    g = np.minimum(fp1, fm)

    # perform reconstruction and get the image complement of the result
    if I.dtype == float:
        J = reconstruction(1 - fm, 1 - g, selem=selem)
        J = 1 - J
    else:
        J = reconstruction(255 - fm, 255 - g, method='dilation', selem=selem)
        J = 255 - J

    try:
        J[BW] = -math.inf
    except:
        J[BW] = -float("inf")

    return J
Beispiel #45
0
dst = np.array([[0, 0], [side - 1, 0], [side - 1, side - 1], [0, side - 1]],
               dtype='float32')

# Gets the transformation matrix for skewing the image to fit a square by comparing the 4 before and after points
m = cv2.getPerspectiveTransform(src, dst)

# Performs the transformation on the original image
sodoku = cv2.warpPerspective(img_origin, m, (int(side), int(side)))

thresh = cv2.adaptiveThreshold(sodoku, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
                               cv2.THRESH_BINARY, 5, 7)
thresh = cv2.bitwise_not(thresh)

salem = morphology.disk(1)
eroded = morphology.erosion(thresh, salem)
thresh = morphology.reconstruction(eroded, thresh)

q = 28  # q = quality
cut = 10

#invert the image (this is how MNIST digits is formatted)
array = thresh
#array = cv2.bitwise_not(array)

#this will be the width and length of each sub-image
divisor = array.shape[0] // 9

puzzle = []
for i in range(9):
    row = []
    for j in range(9):
Beispiel #46
0
def PoresWatershedSegmentationOnePhase(phaseImage,
                                       structuringElement=np.ones((3, 3, 3)),
                                       distanceType='ITKDanielson',
                                       watershedAlgo='ITK',
                                       seedMethod='hMaxima',
                                       seedParam=4):

    #Calcul de la carte de distance distanceMap

    if distanceType == 'euclidean':
        memoryType = np.float16
        distanceMap = ndimage.distance_transform_edt(phaseImage).astype(
            memoryType)
    elif distanceType == 'chamfer':
        memoryType = np.int8
        distanceMap = ndimage.distance_transform_cdt(
            phaseImage, metric='chessboard').astype(memoryType)
    elif distanceType == 'ITKDanielson':
        memoryType = np.float16
        itkimage = sitk.GetImageFromArray(
            np.logical_not(phaseImage).astype(np.uint8))
        itkdistanceMap = sitk.DanielssonDistanceMap(itkimage)
        del itkimage
        distanceMap = sitk.GetArrayFromImage(itkdistanceMap).astype(memoryType)
        del itkdistanceMap

    #Choix des marqueurs pour la segmentation (centres des pores) : H-maxima :
    #maxima de la carte de distance dont les pics sont étêtés d'une hauteur h. Utilise
    #une recontruction morphologique pour construire la carte de distance étêtée.

    hMaximaLib = 'skimage'

    if seedMethod == 'localMax':
        seedParam = int(seedParam)
        local_maxi = feature.peak_local_max(distanceMap.astype(np.float),
                                            min_distance=seedParam,
                                            indices=False)

    elif seedMethod == 'hMaxima' and hMaximaLib == 'skimage' and seedParam > 0:
        hContrast = np.asarray(seedParam).astype(memoryType)
        reconstructed = morphology.reconstruction(
            distanceMap - hContrast, distanceMap).astype(memoryType)

        local_maxi = (distanceMap - reconstructed).astype(np.bool)
        del reconstructed

    elif seedMethod == 'hMaxima' and hMaximaLib == 'ITK' and seedParam > 0:
        hContrast = np.asarray(seedParam).astype(memoryType)
        itkSeedimage = sitk.GetImageFromArray(
            (distanceMap - hContrast).astype(np.float32))
        itkMarkerImage = sitk.GetImageFromArray(distanceMap.astype(np.float32))
        itkReconstructed = sitk.ReconstructionByDilation(
            itkSeedimage, itkMarkerImage)
        del itkMarkerImage, itkSeedimage
        reconstructed = sitk.GetArrayFromImage(itkReconstructed).astype(
            memoryType)
        del itkReconstructed

        local_maxi = ((distanceMap - reconstructed) > hContrast / 10).astype(
            np.bool)
        del reconstructed

    markers = ndimage.measurements.label(local_maxi,
                                         structure=structuringElement)[0]

    del local_maxi

    #Calcul des lignes de partage de niveau

    if watershedAlgo == 'Mahotas':
        _, watershedLines = mahotas.cwatershed(
            (distanceMap.max() - distanceMap).astype(np.int8),
            markers,
            Bc=structuringElement,
            return_lines=True)
    elif watershedAlgo == 'ITK':
        itkMarkers = sitk.GetImageFromArray(markers)
        itkDistance = sitk.GetImageFromArray(distanceMap.astype(np.float))
        itkDistance = sitk.InvertIntensity(itkDistance)

        wsITK = sitk.MorphologicalWatershedFromMarkers(itkDistance,
                                                       itkMarkers,
                                                       markWatershedLine=True,
                                                       fullyConnected=True)
        del itkMarkers, itkDistance
        #        mask = itk.MaskImageFilter.IUC2IUC2IUC2.New(ws, fill)
        #        overlay = itk.LabelOverlayImageFilter.IUC2IUC2IRGBUC2.New(reader,
        #                                                                  mask,
        #                                                                  UseBackground=True)
        ws = sitk.GetArrayFromImage(wsITK).astype(np.uint8)
        del wsITK
        watershedLines = (ws == 0).astype(np.bool)
        watershedLines[np.logical_not(phaseImage)] = False
    del markers

    #Labeler des pores séparés par les lignes de partage de niveau

    pores = ndimage.measurements.label(np.logical_and(
        phaseImage, np.logical_not(watershedLines)),
                                       structure=structuringElement)[0]
    pores[np.logical_not(phaseImage)] = 0
    memoryType = utilities.BestMemoryType(pores.max())
    pores = pores.astype(memoryType)

    return pores, watershedLines, distanceMap
Beispiel #47
0
from skimage.morphology import reconstruction
from skimage.color import rgb2gray
from skimage.io import imread

# Convert to float: Important for subtraction later which won't work with uint8
#image = img_as_float(data.coins())
#image = gaussian_filter(image, 1)

image = rgb2gray(imread('Dataset/13291658032668.jpg'))
image = image.max() - image

seed = np.copy(image)
seed[1:-1, 1:-1] = image.min()
mask = image

dilated = reconstruction(seed, mask, method='dilation')

fig, (ax0, ax1, ax2, ax3) = plt.subplots(nrows=1,
                                         ncols=4,
                                         figsize=(8, 2.5),
                                         sharex=True,
                                         sharey=True)

ax0.imshow(image, cmap='gray')
ax0.set_title('original image')
ax0.axis('off')

ax1.imshow(dilated, vmin=image.min(), vmax=image.max(), cmap='gray')
ax1.set_title('dilated')
ax1.axis('off')
def fillhole(img):
    seed = np.copy(img)
    seed[1:-1, 1:-1] = np.max(img)
    mask = img
    return reconstruction(seed, mask, method='erosion').astype(np.uint8)
Beispiel #49
0
def get_dmp(bd, image_min, image_max, ses=None):
    """
    Calculates the Differential Morphological Profile

    Args:
        bd (2d array)
        image_min (int or float)
        image_max (int or float)
        ses (Optional[list]): The structuring elements.

    Returns:

    """

    if not ses:
        ses = [3, 5, 7, 9, 11]

    if bd.dtype != 'uint8':

        bd = np.uint8(
            rescale_intensity(bd,
                              in_range=(image_min, image_max),
                              out_range=(0, 255)))

    section_rows, section_cols = bd.shape

    dmp_counter = 0

    marker = bd.copy()
    previous = bd.copy()

    # The DMP holder
    # closings --> 1st len(ses) bands
    # openings --> last len(ses) bands
    dims = len(ses) * 2

    dmp_array = np.uint8(np.empty((dims, section_rows, section_cols)))

    # Morphological opening
    for se_size in ses:

        se = cv2.getStructuringElement(cv2.MORPH_RECT, (se_size, se_size))

        marker = cv2.erode(marker, se, iterations=1)

        current = reconstruction(marker, bd, method='dilation', selem=se)

        dmp_array[dmp_counter] = previous - current

        previous = current.copy()

        dmp_counter += 1

    marker = bd.copy()
    previous = bd.copy()

    # Morphological closing
    for se_size in ses:

        se = cv2.getStructuringElement(cv2.MORPH_RECT, (se_size, se_size))

        marker = cv2.dilate(marker, se, iterations=1)

        current = reconstruction(marker, bd, method='erosion', selem=se)

        dmp_array[dmp_counter] = current - previous

        previous = current.copy()

        dmp_counter += 1

    # Reshape to [samples X dimensions].
    dmp_array = dmp_array.reshape(dims, section_rows, section_cols).transpose(
        1, 2, 0).reshape(section_rows * section_cols, dims)

    # Get the derivative of the
    #   morphological openings
    #   and closings.
    return np.uint8(
        rescale_intensity(np.gradient(dmp_array, axis=1).T.reshape(
            dims, section_rows, section_cols),
                          in_range=(0, 200),
                          out_range=(0, 255)))
Beispiel #50
0
def regional_flattener(z, h):
    """Localised erosion of the image 'z' for features below a value 'h'"""
    seed = np.copy(z) + h
    mask = z
    eroded = morphology.reconstruction(seed, mask, method='erosion')
    return eroded - h
Beispiel #51
0
img = np.asarray(Image.open('./images/tree_noise.png')).astype(np.uint8)
size = np.size(img[0])
imEro43 = erosion(img, disk(3))
imr = RECONSTRUIT(imEro43, img)

# Affichage avec matplotlib
plt.subplot(131)
plt.imshow(img, cmap='gray', vmin=0.0, vmax=255.0)
plt.title('Originale')
plt.subplot(132)
plt.imshow(imr, cmap='gray', vmin=0.0, vmax=255.0)
plt.title('Ouverture par reconstruction')

imDil43 = dilation(img, disk(3))
imr = reconstruction(imDil43, img, method='erosion')

plt.subplot(133)
plt.imshow(imr, cmap='gray', vmin=0.0, vmax=255.0)
plt.title('Fermeture par reconstruction')
plt.show()

######################## Q4.3 ##########################
img = np.asarray(Image.open('./images/coffee.png')).astype(np.uint8)


def EROSION_ULTIME(img):
    imX = np.tile(img, 1)
    size = np.size(img[0])
    imEroU = np.zeros((size, size), dtype=int)
    for k in range(10):  ##répéter jusqu'à stable
Beispiel #52
0
    # make the filename
    folder_name = args[0]
    output_folder = args[1]

    #     sphere, meta_header = md.load_raw_data_with_mhd(folder_name + "/gradientgauss.mhd")

    sphere, header = md.load_raw_data_with_mhd(folder_name + "/sphere1.mhd")
    sphere = median_filter(sphere, 3)
    np_image = (sphere > threshold_otsu(sphere)) * 1

    import numpy as np
    from skimage.morphology import reconstruction

    seed = np.copy(np_image)
    seed[1:-1, 1:-1] = np_image.max()
    mask = np_image

    np_image = reconstruction(seed, mask, method='erosion')

    from scipy import ndimage
    distance = ndimage.distance_transform_edt(np_image)
    max_pos = ndimage.measurements.maximum_position(distance)

    print max_pos

    for z in range(np_image.shape[0]):

        slice = distance[z, :, :]

        misc.imsave(folder_name + '/slice{0}.tif'.format(z), slice)
Beispiel #53
0
def reconstruct(seed, mask):
    return reconstruction(seed, mask)
Beispiel #54
0
Now we need to create the seed image, where the minima represent the starting
points for erosion.  To fill holes, we initialize the seed image to the maximum
value of the original image. Along the borders, however, we use the original
values of the image. These border pixels will be the starting points for the
erosion process. We then limit the erosion by setting the mask to the values
of the original image.
"""

import numpy as np
from skimage.morphology import reconstruction

seed = np.copy(image)
seed[1:-1, 1:-1] = image.max()
mask = image

filled = reconstruction(seed, mask, method='erosion')

#imshow(filled, vmin=image.min(), vmax=image.max())
#plt.title('after filling holes')
"""
.. image:: PLOT2RST.current_figure

As shown above, eroding inward from the edges removes holes, since (by
definition) holes are surrounded by pixels of brighter value. Finally, we can
isolate the dark regions by subtracting the reconstructed image from the
original image.
"""

#imshow(image - filled)
#plt.title('holes')
"""
Beispiel #55
0
                          (255, 255, 255),
                          thickness=30)

grid_crop = morphology.remove_small_objects(grid_crop, min_size=9000)

img = morphology.dilation(
    grid_crop, morphology.square(5)
) > 0  # dilation para deixas as linhas mais largas, para que os quadrados (props) fiquem bem definidos
img1 = morphology.remove_small_objects(img, min_size=100)
img1 = morphology.remove_small_holes(img1, 110, connectivity=2)
img1 = morphology.remove_small_holes(img1, 110)

verticals = morphology.erosion(img1, morphology.rectangle(
    130, 1))  # separar as linhas verticais

img2 = morphology.reconstruction(verticals, img1)

img3 = morphology.dilation(img2, morphology.square(5)) > 0

img = ~img3

props = regionprops(morphology.label(img))

prop_list = []
crop_list = []

soma = 0
for i in props:
    soma += i.area

soma /= len(props)