f,ax = plt.subplots() ax.imshow(arr, cmap=cm.gray, interpolation='none') plt.show() def make_img(num_obj=100, obj_rad=5, nr=1024, nc=1024): arr = np.zeros((nr,nc)) kerLen = 2*obj_rad (X,Y) = np.mgrid[-1:1:1j*kerLen, -1:1:1j*kerLen] ker = (np.sqrt(X*X+Y*Y) <= 0.9) rand_pos = np.random.rand(num_obj, 2) for (x,y) in rand_pos: xstart = int(x*(nc-kerLen)) ystart = int(y*(nr-kerLen)) arr[xstart:xstart+kerLen, ystart:ystart+kerLen] += ker return arr #Creating an Image. image = make_img(num_obj=6, obj_rad=10, nr=128, nc=128) my_imshow(image) # To separate the circles. We generate markers at the maxima of the distance to the background: from skimage.feature import peak_local_max distance = ndi.distance_transform_edt(image) local_maxi = peak_local_max(distance, labels=image,footprint=np.ones((3, 3)),indices=False) markers = ndi.label(local_maxi)[0] #Finally,run the watershed on the image and markers: from skimage.segmentation import watershed labels = watershed(-distance, markers, mask=image) my_imshow(labels)
def analyze_bubbles(img, scale=1, frame=0): """ Process an image to detect the bubbles (bright on dark assumed) Parameters ---------- img : np.array image to process scale : float, optional Scaling factor in px/mm. Default is 1 px/mm frame : int, optional Frame number of the image for inclusion in the dataframe. Default is 0 Returns ------- DataFrame {'Frame', Label', 'Area', 'Eccentricity', 'Bbox Area'} Frame (int): Frame number of the image Label (int): Identifier for each bubble Area (int): area of the detected bubble (mm2) Eccentricity (float): eccentricity of the region Bbox Area (int): area of the bounding box (mm2) """ try: #Convert to grayscale img_gray = img_as_ubyte(rgb2gray(img)) #Threshold the image (otsu) to get the bubbles img_bin = img_gray > threshold_minimum(img_gray) #Close holes in bubbles img_closed = closing(img_bin) #Compute distance to background dist = ndi.distance_transform_edt(img_closed) #Stretch contrast of the distance image dist_cont = exposure.rescale_intensity(dist, in_range='image') #Find local maximas in distance image and make them markers for the watershed local_maxi = peak_local_max(dist_cont, indices=False, footprint=np.ones((10, 10))) markers, num_max = ndi.label(local_maxi) #Run a watershed algorithm to separate the bubbles img_segmented = watershed(-dist_cont, markers, mask=img_closed, watershed_line=True) #Label the segmented image img_labeled, num_sec = ndi.label(img_segmented) #Get the properties of the labeled regions and construct a dataframe reg = regionprops(img_labeled, coordinates='rc') if len(reg) > 0: columns = ['Frame', 'Label', 'Area', 'Eccentricity', 'Bbox Area'] df = pd.DataFrame(columns=columns, dtype=np.float64) df = df.append([{ 'Frame': frame, 'Label': i.label, 'Area': i.area / (scale**2), 'Eccentricity': i.eccentricity, 'Bbox Area': i.bbox_area / (scale**2) } for i in reg]) return df else: return None except: return None
def getVoronoiStyle(seg_file, max_voro_area, voro_imfile, voro_imfile_2, voro_outfile, voro_transfile): temp = np.asarray(np.load(seg_file, allow_pickle=True)).item() masks = temp['masks'] im = np.zeros_like(np.array(masks)) fro = pd.DataFrame( measure.regionprops_table(masks, properties=['label', 'centroid'])) points_mask = np.array(fro[['centroid-0', 'centroid-1']].to_numpy()) vor = Voronoi(points_mask) my_dpi = im.shape[1] plt.rcParams['figure.dpi'] = my_dpi plt.rcParams['figure.figsize'] = (im.shape[0] / my_dpi, im.shape[1] / my_dpi) fig = plt.figure() for simplex in vor.ridge_vertices: simplex = np.asarray(simplex) if np.all(simplex >= 0): plt.plot(vor.vertices[simplex, 0], vor.vertices[simplex, 1], 'k-', c='black', linewidth=.2) center = points_mask.mean(axis=0) for pointidx, simplex in zip(vor.ridge_points, vor.ridge_vertices): simplex = np.asarray(simplex) if np.any(simplex < 0): i = simplex[simplex >= 0][0] # finite end Voronoi vertex t = points_mask[pointidx[0]] - points_mask[pointidx[1]] # tangent t = t / np.linalg.norm(t) n = np.array([-t[1], t[0]]) # normal midpoint = points_mask[pointidx].mean(axis=0) far_point = vor.vertices[i] + np.sign(np.dot(midpoint - center, n)) * n * 100 plt.plot([vor.vertices[i, 0], far_point[0]], [vor.vertices[i, 1], far_point[1]], 'k-', c='black', linewidth=.2) plt.xlim([0, im.shape[0]]) plt.ylim([0, im.shape[1]]) plt.axis('off') fig.tight_layout(pad=0) plt.savefig( voro_imfile, dpi=my_dpi, #bbox_inches='tight',#dpi=my_dpi, transparent=False, pad_inches=0, facecolor='white') plt.close() im2 = io.imread(voro_imfile) voro = (im2[:, :, 0]) voro = voro[1:-1, 1:-1] voro = np.pad(voro, pad_width=1, mode='constant') distance = ndi.distance_transform_edt(voro) coords = peak_local_max(distance, footprint=np.ones((1, 1)), labels=voro) mask = np.zeros(distance.shape, dtype=bool) mask[tuple(coords.T)] = True markers, _ = ndi.label(mask) labels = segmentation.watershed(-distance, markers, mask=voro) labels = morphology.remove_small_objects(labels, min_size=40, connectivity=1, in_place=False) labels = morphology.dilation(labels, morphology.square(3)) segmasks = masks segmasks = morphology.dilation(segmasks, morphology.square(3)) sizeOfSegs = pd.DataFrame( measure.regionprops_table(labels, properties=['label', 'area'])) bigMasks = np.array( sizeOfSegs[sizeOfSegs['area'] >= max_voro_area]['label']) newVorMask = np.copy(labels)[::-1, :] red = [ getOverlap(row, segmasks=segmasks, fro=fro, dilation=11) for row in range(fro.shape[0]) ] newVorMask = np.sum(red) np.save(voro_outfile, newVorMask.T, allow_pickle=True, fix_imports=True) io.imsave(voro_imfile_2, segmentation.find_boundaries(newVorMask).T) oldAssign = pd.DataFrame( measure.regionprops_table(masks, properties=['label', 'centroid'])) newAssign = pd.DataFrame( measure.regionprops_table(newVorMask, properties=['label', 'centroid'])) Clps2Voro = pd.DataFrame() for nlab in range(newAssign.shape[0]): tmpMtx = (newVorMask == newAssign['label'][nlab]) for olab in range(oldAssign.shape[0]): if (tmpMtx[int(np.round(oldAssign['centroid-1'][olab])), int(np.round(oldAssign['centroid-0'][olab]))]): Clps2Voro = Clps2Voro.append( pd.DataFrame( [newAssign['label'][nlab], oldAssign['label'][olab]]).T) Clps2Voro = Clps2Voro.rename(columns={0: "voro_label", 1: "clps_label"}) Clps2Voro = Clps2Voro.reset_index(drop=True) Clps2Voro.to_csv(voro_transfile)
from skimage.color import label2rgb from skimage import data coins = data.coins() # Make segmentation using edge-detection and watershed. edges = sobel(coins) # Identify some background and foreground pixels from the intensity values. # These pixels are used as seeds for watershed. markers = np.zeros_like(coins) foreground, background = 1, 2 markers[coins < 30.0] = background markers[coins > 150.0] = foreground ws = watershed(edges, markers) seg1 = label(ws == foreground) # Make segmentation using SLIC superpixels. seg2 = slic(coins, n_segments=117, max_iter=160, sigma=1, compactness=0.75, multichannel=False, start_label=0) # Combine the two. segj = join_segmentations(seg1, seg2) # Show the segmentations.
def seg(img): # xg = img[:,:,1] xg = np.copy(img[:, :, 1]) cv2.imshow('img', xg) cv2.waitKey() cv2.destroyAllWindows() mask = np.copy(xg) m1 = mask.mean() mask[mask > m1] = m1 # [xt > m1] m2 = mask.mean() mask[mask > m2] = m2 # [xt>m2] m3 = mask.mean() mask[mask < m3] = 0 # tmp = np.copy(mask) # tmp[tmp >= m3] = 255 mask[mask >= m3] = 1 n = mask.sum() # cv2.imshow('img', tmp) # cv2.waitKey() # cv2.destroyAllWindows() xin = xg * mask xout = xin m1 = xout.sum() / n xout[xout > m1] = m1 m2 = xout.sum() / n xout[xout > m2] = m2 m3 = xout.sum() / n xout[xout > m3] = 0 # tmp = np.copy(xout) # tmp[tmp > 0] = 255 xout[xout > 0] = 2 # # tmp = cv2.morphologyEx(tmp, cv2.MORPH_OPEN, kernel) # cv2.imshow('om', tmp) # cv2.waitKey() # cv2.destroyAllWindows() a, b = np.histogram(xg.flatten(), bins=20, range=[15, 255]) idx = a.argmax() range_S = b[idx] range_B = b[-1] canny = cv2.Canny(xg, 20, 60) * mask # canny = cv2.dilate(canny, kernel, iterations=1) kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) canny = cv2.morphologyEx(canny, cv2.MORPH_CLOSE, kernel, iterations=2) canny = cv2.erode(canny, kernel, iterations=1) # cv2.imshow('canny', canny ) # cv2.waitKey() # cv2.destroyAllWindows() closed = np.zeros_like(canny) closed[mask == 0] = 1 closed[(xg >= range_S) * (xg <= range_B)] = 1 closed[(xg <= b[idx - 1 if idx >= 2 else 0])] = 1 closed[canny > 0] = 2 # tmp = np.copy(canny) # tmp[mask == 0] = 1 # tmp[(xg >= range_S) *(xg <= range_B)] = 128 # tmp[(xg <= b[idx-1 if idx >=2 else 0])] = 128 # tmp[canny>0] = 255 # cv2.imshow('closed', tmp) # cv2.waitKey() # cv2.destroyAllWindows() # xout fused = np.zeros_like(closed) fused[(closed == 2) * (xout == 2)] = 2 fused[(closed == 2) * (xout == 0)] = 2 fused[(closed == 1) * (xout == 0)] = 1 fused[(closed == 1) * (xout == 2)] = 0 # tmp = np.copy(fused) # tmp[fused ==2] = 255 # tmp[fused ==1] = 128 # tmp[fused ==0] = 0 # cv2.imshow('closed', tmp) # cv2.waitKey() # cv2.destroyAllWindows() # image_segmented = watershed(xg, markers = closed)#, beta=1,beta=20, mode='bf' # image_segmented = random_walker(fused, closed)#, beta=1,beta=20, mode='bf' image_segmented = watershed(fused, markers=closed) #, beta=1,beta=20, mode='bf' image_segmented[image_segmented == 1] = 0 image_segmented = image_segmented.astype(np.uint8) image_segmented[image_segmented > 1] = 255 # closed = cv2.erode(image_segmented, None, iterations=2) cv2.imshow('img res', image_segmented) cv2.waitKey() cv2.destroyAllWindows() return image_segmented
# min_distance: Número mínimo de pixels que separam os picos # https://scikit-image.org/docs/stable/api/skimage.feature.html#skimage.feature.peak_local_max print('-' * 50) print('Número de Picos') print(np.unique(max_local, return_counts=True)) print('-' * 50) marcadores, n_marcadores = ndimage.label(max_local, structure=np.ones((3, 3))) # Realiza marcação dos picos # https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.label.html # https://en.wikipedia.org/wiki/Connected-component_labeling print('Análise de conectividade - Marcadores') print(np.unique(marcadores, return_counts=True)) print('-' * 50) img_ws = watershed(-img_dist, marcadores, mask=mascara) # https://scikit-image.org/docs/dev/api/skimage.segmentation.html#skimage.segmentation.watershed # https://en.wikipedia.org/wiki/Watershed_(image_processing) # https://scikit-image.org/docs/dev/auto_examples/segmentation/plot_watershed.html print('Imagem Segmentada - Watershed') print(np.unique(img_ws, return_counts=True)) print("Número de Batatas: ", len(np.unique(img_ws)) - 1) print('-' * 50) img_final = np.copy(img_rgb) img_final[img_ws != 3] = [0, 0, 0] # Acessando a batata 3 ######################################################################################################################## plt.figure('Watershed') plt.subplot(2, 3, 1) plt.imshow(img_rgb)
def S3NucleiSegmentationWatershed(nucleiPM, nucleiImage, logSigma, TMAmask, nucleiFilter, nucleiRegion): nucleiContours = nucleiPM[:, :, 1] nucleiCenters = nucleiPM[:, :, 0] mask = resize(TMAmask, (nucleiImage.shape[0], nucleiImage.shape[1]), order=0) > 0 if nucleiRegion == 'localThreshold': Imax = peak_local_max(extrema.h_maxima(255 - nucleiContours, logSigma[0]), indices=False) Imax = label(Imax).astype(np.int32) foregroundMask = watershed(nucleiContours, Imax, watershed_line=True) P = regionprops( foregroundMask, np.amax(nucleiCenters) - nucleiCenters - nucleiContours) prop_keys = ['mean_intensity', 'label', 'area'] def props_of_keys(prop, keys): return [prop[k] for k in keys] mean_ints, labels, areas = np.array( Parallel(n_jobs=6)(delayed(props_of_keys)(prop, prop_keys) for prop in P)).T del P maxArea = (logSigma[1]**2) * 3 / 4 minArea = (logSigma[0]**2) * 3 / 4 passed = np.logical_and.reduce( (np.logical_and(areas > minArea, areas < maxArea), np.less(mean_ints, 50))) foregroundMask *= np.isin(foregroundMask, labels[passed]) np.greater(foregroundMask, 0, out=foregroundMask) foregroundMask = label(foregroundMask, connectivity=1).astype(np.int32) elif nucleiRegion == 'bypass': foregroundMask = nucleiPM[:, :, 0] P = regionprops(foregroundMask, nucleiImage) prop_keys = ['mean_intensity', 'label', 'area'] def props_of_keys(prop, keys): return [prop[k] for k in keys] mean_ints, labels, areas = np.array( Parallel(n_jobs=6)(delayed(props_of_keys)(prop, prop_keys) for prop in P)).T del P maxArea = (logSigma[1]**2) * 3 / 4 minArea = (logSigma[0]**2) * 3 / 4 passed = np.logical_and(areas > minArea, areas < maxArea) foregroundMask *= np.isin(foregroundMask, labels[passed]) np.greater(foregroundMask, 0, out=foregroundMask) foregroundMask = label(foregroundMask, connectivity=1).astype(np.int32) else: if len(logSigma) == 1: nucleiDiameter = [logSigma * 0.5, logSigma * 1.5] else: nucleiDiameter = logSigma logMask = nucleiCenters > 150 win_view_setting = WindowView(nucleiContours.shape, 2000, 500) nucleiContours = win_view_setting.window_view_list(nucleiContours) padding_mask = win_view_setting.padding_mask() mask = win_view_setting.window_view_list(mask) maxArea = (logSigma[1]**2) * 3 / 4 minArea = (logSigma[0]**2) * 3 / 4 foregroundMask = np.array( Parallel(n_jobs=6)( delayed(contour_pm_watershed)(img, sigma=logSigma[1] / 30, h=logSigma[1] / 30, tissue_mask=tm, padding_mask=m, min_area=minArea, max_area=maxArea) for img, tm, m in zip(nucleiContours, mask, padding_mask))) del nucleiContours, mask foregroundMask = win_view_setting.reconstruct(foregroundMask) foregroundMask = label(foregroundMask, connectivity=1).astype(np.int32) if nucleiFilter == 'IntPM': int_img = nucleiCenters elif nucleiFilter == 'Int': int_img = nucleiImage print(' ', datetime.datetime.now(), 'regionprops') P = regionprops(foregroundMask, int_img) def props_of_keys(prop, keys): return [prop[k] for k in keys] prop_keys = ['mean_intensity', 'area', 'solidity', 'label'] mean_ints, areas, solidities, labels = np.array( Parallel(n_jobs=6)(delayed(props_of_keys)(prop, prop_keys) for prop in P)).T del P MITh = threshold_otsu(mean_ints) minSolidity = 0.8 passed = np.logical_and.reduce( (np.greater(mean_ints, MITh), np.logical_and(areas > minArea, areas < maxArea), np.greater(solidities, minSolidity))) # set failed mask label to zero foregroundMask *= np.isin(foregroundMask, labels[passed]) np.greater(foregroundMask, 0, out=foregroundMask) foregroundMask = label(foregroundMask, connectivity=1).astype(np.int32) return foregroundMask
image = img_as_ubyte(data.camera()) # denoise image denoised = rank.median(image, disk(2)) # find continuous region (low gradient - # where less than 10 for this image) --> markers # disk(5) is used here to get a more smooth image markers = rank.gradient(denoised, disk(5)) < 10 markers = ndi.label(markers)[0] # local gradient (disk(2) is used to keep edges thin) gradient = rank.gradient(denoised, disk(2)) # process the watershed labels = watershed(gradient, markers) # display results fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(8, 8), sharex=True, sharey=True) ax = axes.ravel() ax[0].imshow(image, cmap=plt.cm.gray) ax[0].set_title("Original") ax[1].imshow(gradient, cmap=plt.cm.nipy_spectral) ax[1].set_title("Local Gradient") ax[2].imshow(markers, cmap=plt.cm.nipy_spectral) ax[2].set_title("Markers")
def separate_watershed( vdf_temp, min_distance=1, min_size=1, max_size=np.inf, max_number_of_grains=np.inf, marker_radius=1, threshold=False, exclude_border=False, plot_on=False, ): """Separate segments from one VDF image using edge-detection by the sobel transform and the watershed segmentation implemented in scikit-image. See [1,2] for examples from scikit-image. Parameters ---------- vdf_temp : np.array One VDF image. min_distance: int Minimum distance (in pixels) between markers for them to be considered separate markers for the watershed segmentation. min_size : float Grains with size (i.e. total number of pixels) below min_size are discarded. max_size : float Grains with size (i.e. total number of pixels) above max_size are discarded. max_number_of_grains : int Maximum number of grains included in the returned separated grains. If it is exceeded, those with highest peak intensities will be returned. marker_radius : float If 1 or larger, each marker for watershed is expanded to a disk of radius marker_radius. marker_radius should not exceed 2*min_distance. threshold : bool If True, a mask is calculated by thresholding the VDF image by the Li threshold method in scikit-image. If False (default), the mask is the boolean VDF image. exclude_border : int or True, optional If non-zero integer, peaks within a distance of exclude_border from the boarder will be discarded. If True, peaks at or closer than min_distance of the boarder, will be discarded. plot_on : bool If True, the VDF, the mask, the distance transform and the separated grains will be plotted in one figure window. Returns ------- sep : np.array Array containing segments from VDF images (i.e. separated grains). Shape: (image size x, image size y, number of grains) References ---------- [1] http://scikit-image.org/docs/dev/auto_examples/segmentation/ plot_watershed.html [2] http://scikit-image.org/docs/dev/auto_examples/xx_applications/ plot_coins_segmentation.html#sphx-glr-auto-examples-xx- applications-plot-coins-segmentation-py """ # Create a mask from the input VDF image. if threshold: th = threshold_li(vdf_temp) mask = np.zeros_like(vdf_temp) mask[vdf_temp > th] = True else: mask = vdf_temp.astype("bool") # Calculate the Eucledian distance from each point in the mask to the # nearest background point of value 0. distance = distance_transform_edt(mask) # If exclude_boarder is given, the edge of the distance is removed # by erosion. The distance image is used to find markers, and so the # erosion is done to avoid that markers are located at the edge # of the mask. if exclude_border > 0: distance_mask = binary_erosion(distance, structure=disk(exclude_border)) distance = distance * distance_mask.astype("bool") # Find the coordinates of the local maxima of the distance transform. local_maxi = peak_local_max( distance, indices=False, min_distance=1, num_peaks=max_number_of_grains, exclude_border=exclude_border, threshold_rel=None, ) maxi_coord1 = np.where(local_maxi) # Discard maxima that are found at pixels that are connected to a # smaller number of pixels than min_size. Used as markers, these would lead # to segments smaller than min_size and should therefore not be # considered when deciding which maxima to use as markers. if min_size > 1: labels_check = label(mask)[0] delete_indices = [] for i in np.arange(np.shape(maxi_coord1)[1]): index = np.transpose(maxi_coord1)[i] label_value = labels_check[index[0], index[1]] if len(labels_check[labels_check == label_value]) < min_size: delete_indices.append(i) local_maxi[index[0], index[1]] = False maxi_coord1 = np.delete(maxi_coord1, delete_indices, axis=1) # Cluster the maxima by DBSCAN based on min_distance. For each # cluster, only the maximum closest to the average maxima position is # used as a marker. if min_distance > 1 and np.shape(maxi_coord1)[1] > 1: clusters = DBSCAN( eps=min_distance, metric="euclidean", min_samples=1, ).fit(np.transpose(maxi_coord1)) local_maxi = np.zeros_like(local_maxi) for n in np.arange(clusters.labels_.max() + 1): maxi_coord1_n = np.transpose(maxi_coord1)[clusters.labels_ == n] com = np.average(maxi_coord1_n, axis=0).astype("int") index = distance_matrix([com], maxi_coord1_n).argmin() index = maxi_coord1_n[index] local_maxi[index[0], index[1]] = True # Use the resulting maxima as markers. Each marker should have a # unique label value. For each maximum, generate markers with the same # label value in a radius given by marker_radius centered at the # maximum position. This is done to make the segmentation more robust # to local changes in pixel values around the marker. markers = label(local_maxi)[0] if marker_radius >= 1: disk_mask = disk(marker_radius) for mm in np.arange(1, np.max(markers) + 1): im = np.zeros_like(markers) im[np.where(markers == mm)] = markers[np.where(markers == mm)] markers_temp = convolve2d(im, disk_mask, boundary="fill", mode="same", fillvalue=0) markers[np.where(markers_temp)] = mm markers = markers * mask # Find the edges of the VDF image using the Sobel transform. elevation = sobel(vdf_temp) # 'Flood' the elevation (i.e. edge) image from basins at the marker # positions. Find the locations where different basins meet, i.e. # the watershed lines (segment boundaries). Only search for segments # (labels) in the area defined by mask. labels = watershed(elevation, markers=markers, mask=mask) sep = np.zeros( (np.shape(vdf_temp)[0], np.shape(vdf_temp)[1], (np.max(labels))), dtype="int32") n, i = 1, 0 while (np.max(labels)) > n - 1: sep_temp = labels * (labels == n) / n sep_temp = np.nan_to_num(sep_temp) # Discard a segment if it is too small or too large, or else add # it to the list of separated segments. if (np.sum(sep_temp, axis=(0, 1)) < min_size) or np.sum( sep_temp, axis=(0, 1)) > max_size: sep = np.delete(sep, ((n - i) - 1), axis=2) i = i + 1 else: sep[:, :, (n - i) - 1] = sep_temp n = n + 1 # Put the intensity from the input VDF image into each segmented area. vdf_sep = np.broadcast_to(vdf_temp.T, np.shape(sep.T)) * (sep.T == 1) if plot_on: # pragma: no cover # If segments have been discarded, make new labels that do not # include the discarded segments. if np.max(labels) != (np.shape(sep)[2]) and (np.shape(sep)[2] != 0): labels = sep[:, :, 0] for i in range(1, np.shape(sep)[2]): labels = labels + sep[..., i] * (i + 1) # If no separated particles were found, set all elements in # labels to 0. elif np.shape(sep)[2] == 0: labels = np.zeros(np.shape(labels)) seps_img_sum = np.zeros_like(vdf_temp).astype("float64") for lbl, vdf in zip(np.arange(1, np.max(labels) + 1), vdf_sep): mask_l = np.zeros_like(labels).astype("bool") _idx = np.where(labels == lbl) mask_l[_idx] = 1 seps_img_sum += vdf_temp * mask_l / np.max(vdf_temp[_idx]) seps_img_sum[_idx] += lbl maxi_coord = np.where(local_maxi) fig, axes = plt.subplots(2, 3, sharex=True, sharey=True) ax = axes.ravel() ax[0].imshow(vdf_temp, cmap=plt.cm.magma_r) ax[0].axis("off") ax[0].set_title("VDF") ax[1].imshow(mask, cmap=plt.cm.gray_r) ax[1].axis("off") ax[1].set_title("Mask") ax[2].imshow(distance, cmap=plt.cm.gray_r) ax[2].axis("off") ax[2].set_title("Distance and markers") ax[2].imshow(masked_where(markers == 0, markers), cmap=plt.cm.gist_rainbow) ax[2].plot(maxi_coord1[1], maxi_coord1[0], "k+") ax[2].plot(maxi_coord[1], maxi_coord[0], "gx") ax[3].imshow(elevation, cmap=plt.cm.magma_r) ax[3].axis("off") ax[3].set_title("Elevation") ax[4].imshow(labels, cmap=plt.cm.gnuplot2_r) ax[4].axis("off") ax[4].set_title("Labels") ax[5].imshow(seps_img_sum, cmap=plt.cm.magma_r) ax[5].axis("off") ax[5].set_title("Segments") return vdf_sep
def bacteria_watershed_old( segs, maxsize=1000, #uint16((5*2)/(pix2mic**2)) ### max area minsize=200, #uint16((0.5*0.1)/(pix2mic**2)) ### min area absolwidth=1, thr_strength=2., phase_contrast=None, fix_thr=None): min_av_width = 1 segs2 = {} # here images after watershed thresh_array = [] # for ch_n, img0 in segs.items(): # thresh_array.append(skfilt.threshold_minimum(img0.flatten())) # med, mad = get_med_and_mad(thresh_array) # threshold_int = med+3*mad for ch_n, img0 in segs.items(): factor = 1. if phase_contrast is None: img = -image2gray(segs[0]) if phase_contrast is True: img = image2gray(segs[0]) med, mad = get_med_and_mad(img) if fix_thr is None: th3 = cv.adaptiveThreshold( img, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 101, # block size of the adaptive thr thr_strength * mad) # constant value subtracted else: th3 = deepcopy(img) th3[img > fix_thr] = 1 th3[img <= fix_thr] = 0 #threshold_int = skfilt.threshold_minimum(img0.flatten()) #if skfilt.threshold_minimum(img0.flatten())> threshold_int: #bw0 = img0 > threshold_int+10*factor bw0 = (th3 == 0) #else: # bw0 = img0 > threshold_int; bw1 = ndi.morphology.binary_erosion(bw0, structure=ones((5, 5)), iterations=1) bw2 = ndi.morphology.binary_dilation(bw0) bw3 = bw2 ^ bw1 ### only the borders # perform distance transform on filtered image (distance from the nearest 0) dist = ndi.distance_transform_edt(bw1) markers = np.zeros(img0.shape, dtype=bool) markers[dist >= absolwidth] = True markers = ndi.label(markers)[0] markers = markers + 1 # bw3 = bw2 ^ (dist >= absolwidth); ### only the borders markers[bw3] = 0 # Perform watershed # edit by Nicola if phase_contrast is None: segmentation = watershed(-img0, markers) if phase_contrast is True: segmentation = watershed(img0, markers) # segmentation = watershed(img0, markers) segmentation = ndi.binary_fill_holes(segmentation != 1) # label image labeled_bacteria, nbac = ndi.label(segmentation) ### now filter bacteria for size and width dist = ndi.distance_transform_edt(labeled_bacteria > 0) newbac = np.zeros(labeled_bacteria.shape, dtype=labeled_bacteria.dtype) stats = dict( num_rejected_av_width=0, num_rejected_area=0, ) label = 0 for region in regionprops(labeled_bacteria): masked_bac = labeled_bacteria == region.label skel = skeletonize(masked_bac) av_width_skel = np.mean(dist[skel]) if av_width_skel < min_av_width: stats["num_rejected_av_width"] += 1 continue if maxsize > region.area > minsize: label += 1 newbac[labeled_bacteria == region.label] = label if region.area > maxsize: stats["num_rejected_area"] += 1 # if stats["num_rejected_area"]>0: segs2[ch_n] = newbac return segs2, thresh_array
def bacteria_watershed( segs, maxsize=1000, #uint16((5*2)/(pix2mic**2)) ### max area minsize=200, #uint16((0.5*0.1)/(pix2mic**2)) ### min area absolwidth=1, thr_strength=2., phase_contrast=None, fix_thr=None): min_av_width = 1 segs2 = {} # here images after watershed thresh_array = [] # for ch_n, img0 in segs.items(): # thresh_array.append(skfilt.threshold_minimum(img0.flatten())) # med, mad = get_med_and_mad(thresh_array) # threshold_int = med+3*mad for ch_n, img0 in segs.items(): if fix_thr is None: thresh = skfilt.threshold_li( np.concatenate([s.flatten() for s in segs.values()])) else: thresh_thr = fix_thr bw0 = img0 > thresh bw1 = ndi.morphology.binary_erosion(bw0) bw2 = ndi.morphology.binary_dilation(bw0) bw3 = bw2 ^ bw1 # perform distance transform on filtered image dist = ndi.distance_transform_edt(bw2) # create markers for watershed markers = np.zeros(img0.shape, dtype=bool) markers[dist >= absolwidth] = True markers = ndi.label(markers)[0] #markers[markers>=1]= markers[markers>=1]+1 #markers[bw3] = 0 # Perform watershed labeled_bacteria = skseg.watershed(-dist, markers, mask=bw2) #labeled_bacteria = ndi.binary_fill_holes(segmentation)# != 1) ### now filter bacteria for size and width dist = ndi.distance_transform_edt(labeled_bacteria > 0) newbac = np.zeros(labeled_bacteria.shape, dtype=labeled_bacteria.dtype) stats = dict( num_rejected_av_width=0, num_rejected_area=0, ) label = 0 for region in regionprops(labeled_bacteria): masked_bac = labeled_bacteria == region.label skel = skeletonize(masked_bac) av_width_skel = np.mean(dist[skel]) if av_width_skel < min_av_width: stats["num_rejected_av_width"] += 1 continue if maxsize > region.area > minsize: label += 1 newbac[labeled_bacteria == region.label] = label if region.area > maxsize: stats["num_rejected_area"] += 1 # if stats["num_rejected_area"]>0: segs2[ch_n] = newbac return segs2, thresh_array
def split_bacteria_in_well( bacteria_label_image, intensity_image, min_skel_length=50, threshold_stat=None, debug=None, ): """ Split bacteria in a single well image based on statistical thresholding of width and intensity along the skeleton Parameters ------ bacteria_label_image : ndarray (2D) Labelled image of detected bacteria intensity_image : ndarray (2d) Intensity image of current well min_skel_length : float (optional) Minimum skeleton length for a region to be considered for splitting returns ------ split_bac : Dictionary The key is the well coordinates and the value is a labelled image of detected bacteria """ max_label = 0 stats = [] dist = ndi.distance_transform_edt(bacteria_label_image > 0) output_labels = bacteria_label_image.copy() for prop in regionprops(bacteria_label_image): region_mask = bacteria_label_image == prop.label #skel, dist = skmorph.medial_axis(region_mask, return_distance=True) skel = skmorph.skeletonize(region_mask) if skel.sum() < min_skel_length: max_label += 1 output_labels[region_mask] = max_label continue skelprop = regionprops(skel.astype(int))[0] posy, posx = skelprop.coords.T skel_intensity = intensity_image[skel] skel_dist = dist[skel] threshold_int = threshold_mad(skel_intensity, 1) threshold_dist = threshold_mad(skel_dist, 1) breaks = skel_intensity < threshold_int #Nicola: 9.5.20 (debug["med_int"] - debug["mad_int"]) breaks_dist = skel_dist < threshold_dist # Nicola 9.5.20 debug["med_dist"] breaks[~breaks_dist] = False skel_breaks = skel.copy() skel_breaks[skel] = breaks break_labels, n_breaks = ndi.label(skel_breaks) sizes = ndi.sum(skel_breaks, break_labels, index=np.arange(1, n_breaks + 1)) for label, break_size in enumerate(sizes, start=1): # if break_size < min_break_size: if break_size < 0: skel_breaks[break_labels == label] = False bacteria_markers, n_bacteria_markers = ndi.label(skel ^ skel_breaks, structure=np.ones( (3, 3), dtype=bool)) num_removed = 0 for label in range(1, n_bacteria_markers + 1): bwnow = bacteria_markers == label if bwnow.sum() >= min_skel_length: continue bacteria_markers[bwnow] = 0 num_removed += 1 if num_removed == n_bacteria_markers: max_label += 1 output_labels[region_mask] = max_label continue bacteria_markers, num_final = ndi.label(bacteria_markers > 0, structure=np.ones((3, 3), dtype=bool)) bacterianow = watershed(-dist, bacteria_markers, mask=region_mask) bacterianow[bacterianow > 0] += max_label output_labels[region_mask] = bacterianow[region_mask] max_label += num_final return output_labels
def split_bacteria_in_well_strong( bacteria_label_image, intensity_image, min_skel_length=50, ): """ Split bacteria in a single well image based on peaks intensity along the skeleton Parameters ------ bacteria_label_image : ndarray (2D) Labelled image of detected bacteria intensity_image : ndarray (2d) Intensity image of current well min_skel_length : float (optional) Minimum skeleton length for a region to be considered for splitting returns ------ split_bac : Dictionary The key is the well coordinates and the value is a labelled image of detected bacteria """ max_label = 0 stats = [] dist = ndi.distance_transform_edt(bacteria_label_image > 0) output_labels = bacteria_label_image.copy() for prop in regionprops(bacteria_label_image): region_mask = bacteria_label_image == prop.label #skel, dist = skmorph.medial_axis(region_mask, return_distance=True) skel = skmorph.skeletonize(region_mask) if skel.sum() < min_skel_length: max_label += 1 output_labels[region_mask] = max_label continue skelprop = regionprops(skel.astype(int))[0] posy, posx = skelprop.coords.T skel_x = uint8(posx.mean()) # find intensity profile along bacteria axis image_skel = intensity_image[posy[0]:posy[-1] + 1, skel_x - 2:skel_x + 2] #temp_image[~thinned]= nan skel_intensity = nanmean(image_skel, axis=1) # find distance profile along bacteria axis dist = ndi.distance_transform_edt(bacteria_label_image > 0) image_skel_dist = dist[posy[0]:posy[-1], skel_x - 2:skel_x + 2] skel_dist = nanmean(image_skel_dist, axis=1) skel_intensity_gf = gaussian_filter(skel_intensity, 2) skel_dist_gf = gaussian_filter(skel_dist, 2) xs_int, ph = find_peaks(-skel_intensity_gf, prominence=0.10, distance=min_skel_length) xs_dist, ph = find_peaks(-skel_dist_gf, prominence=0.10, distance=min_skel_length) joined_conditions = abs(xs_dist - xs_int[:, newaxis]) < 3 ## breaks_point = repeat(xs_dist[np.newaxis, :], len(xs_int), axis=0)[joined_conditions] breaks = zeros_like(skel_intensity) breaks[breaks_point] = 1 skel_breaks = skel.copy() #remove the point in the skel skel_breaks[skel] = breaks # this is the sure background break_labels, n_breaks = ndi.label(skel_breaks) sizes = ndi.sum(skel_breaks, break_labels, index=np.arange(1, n_breaks + 1)) for label, break_size in enumerate(sizes, start=1): # if break_size < min_break_size: if break_size < 0: skel_breaks[break_labels == label] = False bacteria_markers, n_bacteria_markers = ndi.label(skel ^ skel_breaks, structure=np.ones( (3, 3), dtype=bool)) num_removed = 0 for label in range(1, n_bacteria_markers + 1): bwnow = bacteria_markers == label if bwnow.sum() >= min_skel_length: continue bacteria_markers[bwnow] = 0 num_removed += 1 if num_removed == n_bacteria_markers: max_label += 1 output_labels[region_mask] = max_label continue bacteria_markers, num_final = ndi.label(bacteria_markers > 0, structure=np.ones((3, 3), dtype=bool)) bacterianow = watershed(-dist, bacteria_markers, mask=region_mask) bacterianow[bacterianow > 0] += max_label output_labels[region_mask] = bacterianow[region_mask] max_label += num_final return output_labels
def segmentation(img, local_maxi, labels, meta, directory, plot=True, save=False): only_clusters = np.zeros(img.shape, dtype=np.int) for pos, new in zip(local_maxi, labels): if new > 0: only_clusters[int(pos[0]), int(pos[1])] = new elif new == 0: only_clusters[int(pos[0]), int(pos[1])] = max(labels) + 1 only_clusters = dilation(only_clusters, disk(10)) binary = _binarize(img) dist_water = ndi.distance_transform_edt(binary) segmentation_ws = watershed(-img, only_clusters, mask = binary) ganglion_prop = regionprops(segmentation_ws) if plot == True: if segmentation_ws.size > 250000000: x,y=img.shape #Array splitting img_1 = img[0:x, 0:int(y/2)] img_2 = img[0:x, int(y/2)+1:y] seg_ws1 = segmentation_ws[0:x, 0:int(y/2)] seg_ws2 = segmentation_ws[0:x, int(y/2)+1:y] seg_ws = [seg_ws1, seg_ws2] img_list = [img_1, img_2] for i in range(2): image_label_overlay = label2rgb(seg_ws[i], image=img_list[i].astype('uint16'), bg_label=0) fig,ax = plt.subplots(1,1, figsize=(16,16)) ax.imshow(image_label_overlay, interpolation='nearest') ax.axis('off') for prop in regionprops(seg_ws[i]): ax.annotate(prop.label, (prop.centroid[1]-5, prop.centroid[0]), color='green', fontsize=8,weight = "bold") if save: try: filename = meta['Name']+str(i+1)+'.pdf' plt.savefig(directory+'/'+filename, transparent=True) except IOError: plt.savefig(filename, transparent=True) else: image_label_overlay = label2rgb(segmentation_ws, image=img.astype('uint16'), bg_label=0) fig,ax = plt.subplots(1,1, figsize=(16,16)) ax.imshow(image_label_overlay, interpolation='nearest') ax.axis('off') for prop in ganglion_prop: ax.annotate(prop.label, (prop.centroid[1]-5, prop.centroid[0]), color='green', fontsize=8,weight = "bold") if save: try: filename = meta['Name']+'.pdf' plt.savefig(directory+'/'+filename, transparent=True) except IOError: plt.savefig(filename, transparent=True) return(ganglion_prop)
def extract_binary_masks_blob( A, neuron_radius: float, dims: Tuple[int, ...], num_std_threshold: int = 1, minCircularity: float = 0.5, minInertiaRatio: float = 0.2, minConvexity: float = .8) -> Tuple[np.array, np.array, np.array]: """ Function to extract masks from data. It will also perform a preliminary selectino of good masks based on criteria like shape and size Args: A: scipy.sparse matrix contains the components as outputed from the CNMF algorithm neuron_radius: float neuronal radius employed in the CNMF settings (gSiz) num_std_threshold: int number of times above iqr/1.349 (std estimator) the median to be considered as threshold for the component minCircularity: float parameter from cv2.SimpleBlobDetector minInertiaRatio: float parameter from cv2.SimpleBlobDetector minConvexity: float parameter from cv2.SimpleBlobDetector Returns: masks: np.array pos_examples: neg_examples: """ params = cv2.SimpleBlobDetector_Params() params.minCircularity = minCircularity params.minInertiaRatio = minInertiaRatio params.minConvexity = minConvexity # Change thresholds params.blobColor = 255 params.minThreshold = 0 params.maxThreshold = 255 params.thresholdStep = 3 params.minArea = np.pi * ((neuron_radius * .75)**2) params.filterByColor = True params.filterByArea = True params.filterByCircularity = True params.filterByConvexity = True params.filterByInertia = True detector = cv2.SimpleBlobDetector_create(params) masks_ws = [] pos_examples = [] neg_examples = [] for count, comp in enumerate(A.tocsc()[:].T): logging.debug(count) comp_d = np.array(comp.todense()) gray_image = np.reshape(comp_d, dims, order='F') gray_image = (gray_image - np.min(gray_image)) / \ (np.max(gray_image) - np.min(gray_image)) * 255 gray_image = gray_image.astype(np.uint8) # segment using watershed markers = np.zeros_like(gray_image) elevation_map = sobel(gray_image) thr_1 = np.percentile(gray_image[gray_image > 0], 50) iqr = np.diff(np.percentile(gray_image[gray_image > 0], (25, 75))) thr_2 = thr_1 + num_std_threshold * iqr / 1.35 markers[gray_image < thr_1] = 1 markers[gray_image > thr_2] = 2 edges = watershed(elevation_map, markers) - 1 # only keep largest object label_objects, _ = scipy.ndimage.label(edges) sizes = np.bincount(label_objects.ravel()) if len(sizes) > 1: idx_largest = np.argmax(sizes[1:]) edges = (label_objects == (1 + idx_largest)) edges = scipy.ndimage.binary_fill_holes(edges) else: logging.warning('empty component') edges = np.zeros_like(edges) masks_ws.append(edges) keypoints = detector.detect((edges * 200.).astype(np.uint8)) if len(keypoints) > 0: pos_examples.append(count) else: neg_examples.append(count) return np.array(masks_ws), np.array(pos_examples), np.array(neg_examples)
############# # LABEL DETECTION ############# # Make segmentation using edge-detection and watershed. elevation = sobel(stars_gray) plt.figure() plt.imshow(elevation, cmap=plt.cm.gray) # Identify some background and foreground pixels from the intensity values. # Unsure region is labeled 0 markers = np.zeros_like(stars_gray) markers[stars_gray < 30.0] = 1 #background markers[stars_gray > 150.0] = 2 #foreground stars_segmented = watershed(mask, markers) #seg1 = label(ws == foreground) #regions_seg = regionprops(seg1) #fig_label, ax_label = plt.subplots(1,1) #color1 = label2rgb(seg1, image=stars_gray, bg_label=0) #ax_label.imshow(edges,cmap=plt.cm.nipy_spectral) #ax_label.set_title('Sobel+Watershed') plt.figure() plt.imshow(stars_segmented, cmap=plt.cm.gray) stars_segmented = ndi.binary_fill_holes(stars_segmented - 1) labeled_stars_segmented, _ = ndi.label(stars_segmented) image_label_overlay = label2rgb(labeled_stars_segmented, image=stars_gray, bg_label=0)
def main(bq, prob_map_dir, outdir, testing_data_dir, min_distance, label_threshold, black_threshold): table_service = bq.service('table') try: import tables except ImportError: logging.warn("pytables services not available") #some hyperparameters minimum = 50 directory = prob_map_dir blk_threshold = 0.05 min_dis = min_distance label_thresh = label_threshold files = os.listdir(directory) original_input = testing_data_dir + os.listdir(testing_data_dir)[0] output_files = [] with tifffile.TiffFile(original_input) as tiff: imMeta = tiff.is_imagej for file in files: print file #slice_ind = seeds_slice_id # input('Please input the slice number for seeds:') blk_threshold = black_threshold #input('Please input the threhold for black voxels') #slice_ind = slice_ind-1 path = os.path.join(directory, file) img = sitk.ReadImage(path) img = sitk.GetArrayFromImage(img) img = img.astype('float32') seg_new = img / np.amax(img) slice_ind = slice_det(seg_new) seg_new[seg_new < blk_threshold] = 0 mid_slice = seg_new[slice_ind] mask_mid = peak_local_max(-mid_slice, min_distance=min_dis, indices=False, exclude_border=1) #plt.imshow(mid_slice,cmap='gray') #plt.show() mask_mid = mask_mid * 1 mask_mid = binary_opening(1 - mask_mid) mask_mid = binary_closing(mask_mid) distance = ndi.distance_transform_edt(1 - mask_mid) #mask_mid = peak_local_max(distance,min_distance=30,indices=False,threshold_rel=0.2) mask_mid_bin = np.zeros_like(distance) mask_mid_bin[distance > label_thresh] = 1 masks = label(mask_mid_bin) #masks_img = sitk.GetImageFromArray((masks*255).astype('uint8')) #sitk.WriteImage(masks_img,'/home/tom/result/'+filename+'det.png') uni, counts = np.unique(masks, return_counts=True) for i in uni: if counts[i] < minimum: masks[masks == i] = 0 uni, counts = np.unique(masks, return_counts=True) mask_temp = masks masks = mask_temp #plt.imshow(masks) #plt.show() #mask = watershed(seg_new[slice_ind],masks) #one_cell = np.zeros_like(seg_new) #one_cell[slice_ind] = mask #masks = propagate(seg_new,one_cell,slice_ind) mask_3d = np.zeros_like(seg_new) mask_3d[slice_ind] = masks #last = np.zeros((512,512)) #first = np.zeros((512,512)) #last[400:402,259:262]=30 #first[375:380,245:250]=1 #mask_3d[5]=last #mask_3d[18*5]=last #mask_3d[0]=first #masks_img = sitk.GetImageFromArray((masks*255).astype('uint8')) #sitk.WriteImage(masks_img,'/home/tom/result/'+'seeds.png') #masks = random_walker(seg_new,mask_3d,beta=10,mode='bf') masks = watershed(seg_new, mask_3d, watershed_line=True) #CRF #distance_one_cell = ndi.distance_transform_edt(one_cell) #distance_one_cell[distance_one_cell>15] = np.amax(distance_one_cell) #distance_one_cell = distance_one_cell/np.amax(distance_one_cell) #prob_map = np.multiply(1-prob_map,one_cell) #pro = CRFProcessor.CRF3DProcessor() #seg_new = np.transpose(prob_map,(1,2,0)) #labels = np.zeros((512,512,12,2)) #seg_new[seg_new>0.01] = 1 #labels[:,:,:,0] = seg_new #labels[:,:,:,1] = 1-seg_new #distance_one_cell = np.transpose(distance_one_cell,(1,2,0)) #result = pro.set_data_and_run(seg_new,labels) #result = np.transpose(result,(2,0,1)) #print np.unique(result) #plt.imshow(mask_mid_bin) #plt.show() #masks = resize(masks,(masks.shape[0]/5,masks.shape[1],masks.shape[2]),mode='constant') #masks_img = sitk.GetImageFromArray((masks).astype('uint8')) #file_name = os.path.splitext(file)[0] #outfile = os.path.join(outdir,file_name+'-seg.tif') #sitk.WriteImage(masks_img,outfile) with tifffile.TiffWriter('source/result/' + file + 'seg.tif') as tif: for i in range(masks.shape[0]): tif.save(masks[i], extratags=[(270, 's', 1, imMeta)]) labeled_image = label_segmentation('source/result/' + file + 'seg.tif') num_cells = len(np.unique(masks)) - 1 coordinates = seg_img_coord(masks) #for label in np.unique(seg): adj_table = compute_cell_adjacent_table(masks) adj_table_done = tuple([(k, v) for k, v in adj_table.items()]) #df = pd.DataFrame(adj_table) #df.to_csv("result/adj_table.csv") center = cell_center(masks) points = compute_conjunction_points(masks, adj_table) points_done = tuple([(k, [x for xs in v for x in xs]) for k, v in points.items()]) #np.savetxt("result/points.csv", points, delimiter=",") cell_vol = cell_volumn(masks) cell_vol_done = tuple([(k, v) for k, v in cell_vol.items()]) #df1 = pd.DataFrame(cell_volumn(masks)) #df1.to_csv("result/cell_volumn.csv") output_files.append('source/result/' + file + 'seg.tif') tfu = adj_table.values() b = np.full([len(tfu), len(max(tfu, key=lambda x: len(x)))], fill_value=np.nan) for i, j in enumerate(tfu): b[i][0:len(j)] = j with h5py.File('source/hdf/PlantCellSegmentation.h5', 'w') as hf: grp0 = hf.create_group("Cell Labels") grp1 = hf.create_group("Surface Coordinates") grp2 = hf.create_group("Cell Center") grp3 = hf.create_group("Cell Volume") grp4 = hf.create_group("Adjacency Table") grp5 = hf.create_group("Segmented Image") grp2.create_dataset("Cell Center", data=(np.array((center.values())))) grp3.create_dataset("Cell Volume", data=(np.array((cell_vol.values())))) grp4.create_dataset("Adjacency Table", data=b) grp0.create_dataset("Cell Labels", data=np.array((center.keys()))) grp5.create_dataset("Segmented Image", data=masks, compression='gzip', compression_opts=9) for ix in range(num_cells): grp1.create_dataset("Cell Label: {}".format(ix), compression='gzip', compression_opts=9, data=(np.array( (coordinates.values())))[ix]) #outtable_xml_adj_table = table_service.store_array(adj_table_done, name='adj_table') #outtable_xml_points = table_service.store_array(points_done, name='points') #outtable_xml_cell_vol = table_service.store_array(cell_vol_done, name='cell_vol') #print(output_files) return output_files, adj_table, points, cell_vol, coordinates, center
def generate_labels(data, labels_dir, masks_dir): tile_id, polygons = data out_mask_path = os.path.join(masks_dir, tile_id + ".png") # if os.path.exists(out_mask_path): # return try: labels = np.zeros((3072, 3072), np.int16) label = 1 for feat in polygons: if feat == "LINESTRING EMPTY" or feat == "POLYGON EMPTY": continue feat = feat.replace("POLYGON ((", "").replace( "POLYGON Z ((", "").replace("), (", "|").replace("),(", "|").replace("(", "").replace(")", "") feat_polygons = feat.split("|") for i, polygon in enumerate(feat_polygons): polygon_coords = [] for xy in polygon.split(","): xy = xy.strip() x, y, *_ = xy.split(" ") x = float(x) y = float(y) polygon_coords.append([x, y]) coords = np.round(np.array(polygon_coords) * 3).astype( np.int32) fillPoly(labels, [coords], label if i == 0 else 0) label += 1 labels, _, _ = relabel_sequential(labels) small_labels = np.zeros_like(labels) eroded_labels = np.zeros_like(labels) big_labels = np.zeros_like(labels) very_big_labels = np.zeros_like(labels) for prop in measure.regionprops(labels): y1, x1, y2, x2 = prop.bbox if prop.minor_axis_length > 8: very_big_labels[y1:y2, x1:x2][prop.image > 0] = 1 elif prop.minor_axis_length > 4: big_labels[y1:y2, x1:x2][prop.image > 0] = 1 else: small_labels[y1:y2, x1:x2][prop.image > 0] = 1 eroded_lbl = binary_erosion(prop.image, iterations=1) eroded_labels[y1:y2, x1:x2][eroded_lbl > 0] = prop.label cv2.imwrite(os.path.join(labels_dir, tile_id + ".tif"), labels.astype(np.uint16)) binary_image = binary_dilation((labels > 0), iterations=2).astype(np.uint8) tmp = watershed(binary_image, mask=binary_image, markers=eroded_labels, watershed_line=True) ws_line = (binary_image ^ (tmp > 0)) * (1 - small_labels) fat_ws_line = (binary_dilation(ws_line, iterations=1) > 0) * (1 - big_labels) * (1 - small_labels) labels[ws_line > 0] = 0 labels[fat_ws_line > 0] = 0 labels, _, _ = relabel_sequential(labels) out = create_mask(labels).astype(np.uint8) out = Image.fromarray(out) out.save(out_mask_path, optimize=True) except Exception as e: traceback.print_exc() print(tile_id)
def generate_trimap(model, image_path, kernel_size=10, device='cuda', dispart_mode=None): model = model.to(device).eval() #img = Image.open(image_path) img = image_path trf = T.Compose([ T.ToTensor(), T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) inp = trf(img).unsqueeze(0).to(device) if device == 'cuda': torch.cuda.empty_cache() with torch.no_grad(): om = model(inp)['out'][0] om = torch.softmax(om.squeeze(), 0) om = om.detach().cpu().numpy() del inp if device == 'cuda': torch.cuda.empty_cache() label_colors = np.array([ (0, 0, 0), # 0=background # 1=aeroplane, 2=bicycle, 3=bird, 4=boat, 5=bottle (128, 0, 0), (0, 128, 0), (128, 128, 0), (0, 0, 128), (128, 0, 128), # 6=bus, 7=car, 8=cat, 9=chair, 10=cow (0, 128, 128), (128, 128, 128), (64, 0, 0), (192, 0, 0), (64, 128, 0), # 11=dining table, 12=dog, 13=horse, 14=motorbike, 15=person (192, 128, 0), (64, 0, 128), (192, 0, 128), (64, 128, 128), (192, 128, 128), # 16=potted plant, 17=sheep, 18=sofa, 19=train, 20=tv/monitor (0, 64, 0), (128, 64, 0), (0, 192, 0), (128, 192, 0), (0, 64, 128) ]) r = np.zeros_like(om[0, :, :]).astype(np.uint8) r_ = np.zeros_like(om[0, :, :]).astype(np.uint8) g = np.zeros_like(om[0, :, :]).astype(np.uint8) g_ = np.zeros_like(om[0, :, :]).astype(np.uint8) b = np.zeros_like(om[0, :, :]).astype(np.uint8) b_ = np.zeros_like(om[0, :, :]).astype(np.uint8) for l in range(0, 21): idx = om[l, :, :] > 0.05 idx_ = om[l, :, :] > 0.95 r[idx] = label_colors[l, 0] g[idx] = label_colors[l, 1] b[idx] = label_colors[l, 2] r_[idx_] = label_colors[l, 0] g_[idx_] = label_colors[l, 1] b_[idx_] = label_colors[l, 2] rgb = np.stack([r, g, b], axis=2) rgb_ = np.stack([r_, g_, b_], axis=2) rgb_gray = cv2.cvtColor(rgb, cv2.COLOR_BGR2GRAY) _, rgb_bw = cv2.threshold(rgb_gray, 10, 255, cv2.THRESH_BINARY) rgb_fg_gray = cv2.cvtColor(rgb_, cv2.COLOR_BGR2GRAY) _, rgb_fg_bw = cv2.threshold(rgb_fg_gray, 10, 255, cv2.THRESH_BINARY) #img = np.array(Image.open(image_path)) img = np.array(image_path) #img_fz = felzenszwalb(img, scale=100, sigma=0.5, min_size=50) #img_fz = felzenszwalb(img, scale=100, sigma=0.5, min_size=50) #img_slic = slic(img, n_segments=250, compactness=10, sigma=1) img_quick = quickshift(img, kernel_size=1, max_dist=6, ratio=0.5, sigma=0) gradient = sobel(rgb2gray(img)) img_watershed = watershed(gradient, markers=250, compactness=0.001) if dispart_mode == 'fg': temp = rgb_fg_bw / 255 seg_ = dispart(temp.astype('int16'), img_quick) seg_ = seg_ * 255 pixels = 2 * kernel_size + 1 kernel = np.ones((pixels, pixels), np.uint8) dilation = cv2.dilate(rgb_bw, kernel, iterations=1) trimap = np.zeros_like(rgb_bw) # bg trimap[dilation == 255] = 127 # confusion trimap[seg_ == 255] = 255 #fg return trimap if dispart_mode == 'bg': temp = rgb_bw / 255 seg_ = dispart(temp.astype('int16'), img_quick) seg_ = seg_ * 255 pixels = 2 * kernel_size + 1 kernel = np.ones((pixels, pixels), np.uint8) dilation = cv2.dilate(seg_, kernel, iterations=1) trimap = np.zeros_like(seg_) # bg trimap[dilation == 255] = 127 # confusion trimap[rgb_fg_bw == 255] = 255 #fg return trimap if dispart_mode == 'fg_bg': temp = rgb_fg_bw / 255 seg_fg = dispart(temp.astype('int16'), img_quick) seg_fg = seg_fg * 255 temp = rgb_bw / 255 seg_bg = dispart(temp.astype('int16'), img_quick) seg_bg = seg_bg * 255 pixels = 2 * kernel_size + 1 kernel = np.ones((pixels, pixels), np.uint8) dilation = cv2.dilate(seg_bg, kernel, iterations=1) trimap = np.zeros_like(seg_bg) # bg trimap[dilation == 255] = 127 # confusion trimap[seg_fg == 255] = 255 #fg return trimap else: pixels = 2 * 10 + 1 kernel = np.ones((pixels, pixels), np.uint8) dilation = cv2.dilate(rgb_bw, kernel, iterations=1) remake = np.zeros_like(rgb_bw) remake[dilation == 255] = 127 remake[rgb_fg_bw == 255] = 255 return remake
myGrid=np.linspace( xmin, xmax, num=xx[condition_label].shape[0])) xsnap = list(map(snap_fun, data[:, 0])) snap_fun = partial(p_utils.snapInd, myGrid=np.linspace( ymin, ymax, num=yy[condition_label].shape[1])) ysnap = list(map(snap_fun, data[:, 1])) points[condition_label] = np.ravel_multi_index( [xsnap, ysnap], xx[condition_label].shape) #points[condition_label] = geo.MultiPoint(np.array([xsnap,ysnap]).T) F[condition_label], kFactor = getFed(data, xx=xx[condition_label], yy=yy[condition_label]) wtr[condition_label] = watershed(1 - F[condition_label], mask=F[condition_label] > 0.000001) uwtr = np.unique(wtr[condition_label]) entropy = np.full(len(uwtr) + 1, 1, dtype='float') esig[condition_label] = sig / (len(uwtr) * len(types_ce)) vsig[condition_label] = sig / (1 * len(types_cv)) entropy_outs[condition_label] = np.full(len(CV), 1, dtype='float') cluster_outs[condition_label] = np.full(len(CV), 0, dtype='int') significant_outs[condition_label] = np.full(len(CV), False) e_routs = pd.DataFrame(columns=types_ce, dtype=float) e_ImgOuts[condition_label] = np.zeros(wtr[condition_label].shape) p_routs[condition_label] = {}
def fill_segments(mask, objects, stem_objects=None, label="default"): """Fills masked segments from contours. Inputs: mask = Binary image, single channel, object = 1 and background = 0 objects = List of contours Returns: filled_img = Filled mask :param mask: numpy.ndarray :param objects: list :param stem_objects: numpy.ndarray :param label: str :return filled_img: numpy.ndarray """ h, w = mask.shape markers = np.zeros((h, w)) objects_unique = objects.copy() if stem_objects is not None: objects_unique.append(np.vstack(stem_objects)) labels = np.arange(len(objects_unique)) + 1 for i, l in enumerate(labels): cv2.drawContours(markers, objects_unique, i, int(l), 5) # Fill as a watershed segmentation from contours as markers filled_mask = watershed(mask == 0, markers=markers, mask=mask != 0, compactness=0) # Count area in pixels of each segment ids, counts = np.unique(filled_mask, return_counts=True) if stem_objects is None: outputs.add_observation( sample=label, variable='segment_area', trait='segment area', method='plantcv.plantcv.morphology.fill_segments', scale='pixels', datatype=list, value=counts[1:].tolist(), label=(ids[1:] - 1).tolist()) else: outputs.add_observation( sample=label, variable='leaf_area', trait='segment area', method='plantcv.plantcv.morphology.fill_segments', scale='pixels', datatype=list, value=counts[1:].tolist(), label=(ids[1:] - 1).tolist()) outputs.add_observation( sample=label, variable='stem_area', trait='segment area', method='plantcv.plantcv.morphology.fill_segments', scale='pixels', datatype=list, value=counts[1:].tolist(), label=(ids[1:] - 1).tolist()) rgb_vals = color_palette(num=len(labels), saved=False) filled_img = np.zeros((h, w, 3), dtype=np.uint8) for l in labels: for ch in range(3): filled_img[:, :, ch][filled_mask == l] = rgb_vals[l - 1][ch] _debug(visual=filled_img, filename=os.path.join(params.debug_outdir, str(params.device) + "_filled_img.png")) return filled_img
def label_cell(nuclei_pred, cell_pred): """Label the cells and the nuclei. Keyword arguments: nuclei_pred -- a 3D numpy array of a prediction from a nuclei image. cell_pred -- a 3D numpy array of a prediction from a cell image. Returns: A tuple containing: nuclei-label -- A nuclei mask data array. cell-label -- A cell mask data array. 0's in the data arrays indicate background while a continous strech of a specific number indicates the area for a specific cell. The same value in cell mask and nuclei mask refers to the identical cell. NOTE: The nuclei labeling from this function will be sligthly different from the values in :func:`label_nuclei` as this version will use information from the cell-predictions to make better estimates. """ def __wsh( mask_img, threshold, border_img, seeds, threshold_adjustment=0.35, small_object_size_cutoff=10, ): img_copy = np.copy(mask_img) m = seeds * border_img # * dt img_copy[m <= threshold + threshold_adjustment] = 0 img_copy[m > threshold + threshold_adjustment] = 1 img_copy = img_copy.astype(np.bool) img_copy = remove_small_objects( img_copy, small_object_size_cutoff).astype(np.uint8) mask_img[mask_img <= threshold] = 0 mask_img[mask_img > threshold] = 1 mask_img = mask_img.astype(np.bool) mask_img = remove_small_holes(mask_img, 1000) mask_img = remove_small_objects(mask_img, 8).astype(np.uint8) markers = ndi.label(img_copy, output=np.uint32)[0] labeled_array = segmentation.watershed(mask_img, markers, mask=mask_img, watershed_line=True) return labeled_array nuclei_label = __wsh( nuclei_pred[..., 2] / 255.0, 0.4, 1 - (nuclei_pred[..., 1] + cell_pred[..., 1]) / 255.0 > 0.05, nuclei_pred[..., 2] / 255, threshold_adjustment=-0.25, small_object_size_cutoff=500, ) # for hpa_image, to remove the small pseduo nuclei nuclei_label = remove_small_objects(nuclei_label, 2500) nuclei_label = measure.label(nuclei_label) # this is to remove the cell borders' signal from cell mask. # could use np.logical_and with some revision, to replace this func. # Tuned for segmentation hpa images threshold_value = max( 0.22, filters.threshold_otsu(cell_pred[..., 2] / 255) * 0.5) # exclude the green area first cell_region = np.multiply( cell_pred[..., 2] / 255 > threshold_value, np.invert(np.asarray(cell_pred[..., 1] / 255 > 0.05, dtype=np.int8)), ) sk = np.asarray(cell_region, dtype=np.int8) distance = np.clip(cell_pred[..., 2], 255 * threshold_value, cell_pred[..., 2]) cell_label = segmentation.watershed(-distance, nuclei_label, mask=sk) cell_label = remove_small_objects(cell_label, 5500).astype(np.uint8) selem = disk(6) cell_label = closing(cell_label, selem) cell_label = __fill_holes(cell_label) # this part is to use green channel, and extend cell label to green channel # benefit is to exclude cells clear on border but without nucleus sk = np.asarray( np.add( np.asarray(cell_label > 0, dtype=np.int8), np.asarray(cell_pred[..., 1] / 255 > 0.05, dtype=np.int8), ) > 0, dtype=np.int8, ) cell_label = segmentation.watershed(-distance, cell_label, mask=sk) cell_label = __fill_holes(cell_label) cell_label = np.asarray(cell_label > 0, dtype=np.uint8) cell_label = measure.label(cell_label) cell_label = remove_small_objects(cell_label, 5500) cell_label = measure.label(cell_label) cell_label = np.asarray(cell_label, dtype=np.uint16) nuclei_label = np.multiply(cell_label > 0, nuclei_label) > 0 nuclei_label = measure.label(nuclei_label) nuclei_label = remove_small_objects(nuclei_label, 2500) nuclei_label = np.multiply(cell_label, nuclei_label > 0) return nuclei_label, cell_label
import matplotlib.pyplot as plt import numpy as np from skimage.data import astronaut from skimage.color import rgb2gray from skimage.filters import sobel from skimage.segmentation import felzenszwalb, slic, quickshift, watershed from skimage.segmentation import mark_boundaries from skimage.util import img_as_float img = img_as_float(astronaut()[::2, ::2]) segments_fz = felzenszwalb(img, scale=100, sigma=0.5, min_size=50) segments_slic = slic(img, n_segments=250, compactness=10, sigma=1) segments_quick = quickshift(img, kernel_size=3, max_dist=6, ratio=0.5) gradient = sobel(rgb2gray(img)) segments_watershed = watershed(gradient, markers=250, compactness=0.001) print("Felzenszwalb's number of segments: %d" % len(np.unique(segments_fz))) print('SLIC number of segments: %d' % len(np.unique(segments_slic))) print('Quickshift number of segments: %d' % len(np.unique(segments_quick))) fig, ax = plt.subplots(2, 2, sharex=True, sharey=True, subplot_kw={'adjustable': 'box-forced'}) fig.set_size_inches(8, 3, forward=True) fig.tight_layout() ax[0, 0].imshow(mark_boundaries(img, segments_fz)) ax[0, 0].set_title("Felzenszwalbs's method") ax[0, 1].imshow(mark_boundaries(img, segments_slic)) ax[0, 1].set_title('SLIC') ax[1, 0].imshow(mark_boundaries(img, segments_quick))
###################### Q5.3 filtre dynamique ###################### # img_rec = reconstruction(255 - img_ui,255 - img_ui + 20, selem=diamond(1)) # ui_min_reg = (img_rec != 255 - img_ui + 20) ##################### Q5.4 filtre conbine ############################ imgradient = dilation(img_ui, disk(2)) - erosion(img_ui, disk(2)) im_rec = reconstruction(dilation(imgradient, disk(2)), imgradient, method='erosion') img_rec = reconstruction(255 - im_rec, 255 - im_rec + 20, selem=diamond(1)) ## ici h = 20 ui_min_reg = (img_rec != 255 - im_rec + 20) seeds = label(ui_min_reg, neighbors=8) # Etiquetage des minima ui_ws = watershed(img_ui, seeds) # LPE par defaut : Marqueur = Minima Regionaux ws_display = color.label2rgb(ui_ws, img_ui) # Affichage avec matplotlib plt.subplot(131) plt.imshow(img_ui, cmap='gray', vmin=0.0, vmax=255.0) plt.title('Originale') plt.subplot(132) plt.imshow(ui_min_reg, cmap='gray', vmin=0.0, vmax=1.0) plt.title('Minima regionaux') plt.subplot(133) plt.imshow(ws_display) plt.title('Ligne de Partage des Eaux') plt.show() ############################ Q6 ##################
def _skimage_ws(self, NEED_WL): return segmentation.watershed( self.skimage_dist, self.markers, connectivity=ndimage.generate_binary_structure(3, 3), watershed_line=NEED_WL)
def wscat(catdir, catname, path, tile, savedir=False): # load full catalog allobjs = np.loadtxt(catdir + '/cosmos_full_cat.dat', skiprows=1) #cosmos_full_cat objra = allobjs[:, 2] objdec = allobjs[:, 3] # load sfg catalogs table = ascii.read(catdir + catname) #cosmos_sfgcat_extended_update try: catalogs = np.array([ table['z'], table['id'], table['x'], table['y'], table['ra'], table['dec'] ]).T except KeyError: catalogs = np.array([ table['zphot'], table['id'], table['x'], table['y'], table['ra'], table['dec'] ]).T _ids = list( catalogs[:, 1] ) #np.loadtxt('{}.dat'.format(catname), skiprows=1, usecols=[0]) # _ids = list(_ids) idsdec = [ os.path.basename(_dir).split('-')[1].split('_')[0] for _dir in glob.glob('./{}/a{}/_id-*'.format(path, tile)) ] idx = [_ids.index(float(_iddec)) for _iddec in idsdec] catalogs = catalogs[idx] catra = catalogs[:, 4] catdec = catalogs[:, 5] _ids = list(catalogs[:, 1]) # load tile image hdu = fits.open('../images/{}/{}-ultravista_Ks.fits'.format(tile, tile)) imgks = hdu[0].data header = hdu[0].header hdu.close() wcs = pywcs.WCS(header) # check extend of tile image tmparray = np.arange(31, 4096 - 31) ra, dec = wcs.all_pix2world(tmparray, tmparray, 1, ra_dec_order=True) minra = min(ra) maxra = max(ra) mindec = min(dec) maxdec = max(dec) # return idx of sfgs within tile image ra_idx = np.where((catra > minra) & (catra < maxra))[0] dec_idx = np.where((catdec > mindec) & (catdec < maxdec))[0] dec_idx = set(dec_idx) idx = list(set(ra_idx).intersection(set(dec_idx))) # change ra and dec to pixel coordinate of tile image catx, caty = wcs.all_world2pix(catra[idx], catdec[idx], 1, ra_dec_order=True) catalogs = catalogs[idx, :] catalogs[:, 2] = catx catalogs[:, 3] = caty catalogs = catalogs[:] for i, (_id, x, y) in enumerate(zip(catalogs[:, 1], catalogs[:, 2], catalogs[:, 3])): print(tile, i, _id) size = 26 scale = 3 tmpobjs = np.array( return_objcoord(wcs, [int(y), int(x)], size, [objra, objdec], scale=scale)) localpeaks = peaks(tmpobjs, (2 * size * scale, 2 * size * scale)) markers = ndi.label(localpeaks)[0] matchimg = imgks[int(y) - size:int(y) + size, int(x) - size:int(x) + size] matchimg = rescale( matchimg, 156. / 52., mode='reflect', multichannel=False) * (52. / 156.)**2 # tmpdir = glob.glob('./selectedgal/resolved_sfgs/a{}/_id-{}*'.format(tile, int(_id)))[0] # matchimg = fits.open('{}/subaru-zp_lambd-000100.0/g_1.fits'.format(tmpdir))[0].data # matchimg = rescale(matchimg, 156./52., mode='reflect', multichannel=False)*(52./156.)**2 tmpsig = 3. while True: masked = matchimg.copy() filtered = sigma_clip(matchimg, sigma=tmpsig, masked=True) distance = filtered.data filtered = filtered.mask masked[filtered == False] = np.nan idx = np.argmin((tmpobjs[:, 1] - 78)**2 + (tmpobjs[:, 0] - 78)**2) if not np.isnan(masked[int(tmpobjs[idx, 0]), int(tmpobjs[idx, 1])]): # idx 0 is y, 1 is x labels = watershed(-distance / np.sum(distance), markers, compactness=0.1, mask=filtered) #-masked/np.sum(masked) segmap = labels.copy() segmap[abs(segmap - segmap[int(tmpobjs[idx, 0]), int(tmpobjs[idx, 1])]) > 0] = 0. segmap = ndi.binary_fill_holes(segmap).astype(float) # plt.imshow(matchimg*segmap) # plt.scatter(tmpobjs[:,1],tmpobjs[:,0], marker='x', color='r') # plt.show() edges = roberts(segmap) edges[edges > 0] = 1 ex = np.where(edges == 1)[1] ey = np.where(edges == 1)[0] fit = fitEllipse(ex, ey, segmap) tmpx, tmpy, a, b, phi = fit.getparams() if not np.any(np.isnan([a, b, phi])): break elif tmpsig < 2: break tmpsig -= 0.5 ell = fit.plotEllipse(a, b, phi) # print (_id, a, b, phi) # nrow = 1 # ncol = 4 # imscale = 2.5 # fig = plt.figure(figsize=((ncol+1)*imscale, (nrow+1)*imscale)) # gs = gridspec.GridSpec(nrow, ncol, wspace=0.0, hspace=0.0, top=1.-0.5/(nrow+1),\ # bottom=0.5/(nrow+1), left=0.5/(ncol+1), right=1-0.5/(ncol+1)) # # ax = plt.subplot(gs[0]) # ax.imshow(matchimg, origin='lower') # # ax = plt.subplot(gs[1]) # ax.imshow(masked, origin='lower') # ax.scatter(tmpobjs[:,1],tmpobjs[:,0], marker='x', color='r') # # ax = plt.subplot(gs[2]) # ax.imshow(segmap, cmap=plt.cm.nipy_spectral, origin='lower') # ax.scatter(tmpobjs[:,1],tmpobjs[:,0], marker='x', color='r') # # ax = plt.subplot(gs[3]) # ax.imshow(edges, origin='lower') # ax.scatter(tmpx+ell[0,:], tmpy+ell[1,:], color='g', s=2) # plt.show() if not os.path.isdir('./{}/a{}/watershed_segmaps'.format(path, tile)): os.makedirs('./{}/a{}/watershed_segmaps'.format(path, tile)) if savedir and not np.any(np.isnan([a, b, phi])): hdr = fits.Header() hdr['XC'] = tmpx hdr['YC'] = tmpy hdr['SEMIMAJ'] = a hdr['SEMIMIN'] = b hdr['AXISUNIT'] = 'arcsecond' hdr['PA'] = phi hdr['PAUNIT'] = 'rad' hdr['SEGMAP'] = 'Based on Ks' hdu = fits.PrimaryHDU(segmap, hdr) hdu.writeto('./{}/a{}/watershed_segmaps/_id-{}.fits'.format( path, tile, int(_id)), overwrite=True) elif np.any(np.isnan([a, b, phi])): filename = glob.glob('./{}/a{}/_id-{}*'.format( path, tile, int(_id)))[0] shutil.move( filename, filename.replace(os.path.basename(filename), 'badphot/' + os.path.basename(filename)))
def Segmentation(img = io.imread(fullpath), Levels = 2, Level1 = "QuickShift", Level2 = "RAG_Merging", useBounday = False, Debug = False): # Level1 if Level1 == "QuickShift": labels1 = segmentation.quickshift(img, kernel_size=3, max_dist=10, ratio=0.7)#.slic(img, compactness=30, n_segments=400) elif Level1 == "SLIC": labels1 = segmentation.slic(img, compactness=30, n_segments=400) elif Level1 == "felzenszwalb": labels1 = segmentation.felzenszwalb(img, scale=100, sigma=0.5, min_size=50) elif Level1 == "Watershed": gradient = sobel(rgb2gray(img)) labels1 = segmentation.watershed(gradient, markers=250, compactness=0.001) out1 = color.label2rgb(labels1, img, kind='avg') if Levels == 1: if Debug: io.imshow(out1) print(labels1) return out1,labels1 # Level2 if Level2 == "NormalizedCut": g = graph.rag_mean_color(img, labels1, mode='similarity') labels2 = graph.cut_normalized(labels1, g) elif Level2 == "RAG_Thresholding": g = graph.rag_mean_color(img, labels1) labels2 = graph.cut_threshold(labels1, g, 29) elif Level2 == "RAG_Merging": g = graph.rag_mean_color(img, labels1) labels2 = graph.merge_hierarchical(labels1, g, thresh=35, rag_copy=False, in_place_merge=True, merge_func=merge_mean_color, weight_func=_weight_mean_color) out2 = color.label2rgb(labels2, img, kind='avg') if useBounday: out1 = segmentation.mark_boundaries(out1, labels1, (1, 0, 0)) out2 = segmentation.mark_boundaries(out2, labels2, (1, 1, 0)) if Debug: print(labels1) print(labels2) fig, ax = plt.subplots(nrows=3, sharex=True, sharey=True, figsize=(10, 12)) print('level1 segments: {}'.format(len(np.unique(labels1)))) print('level2 segments: {}'.format(len(np.unique(labels2)))) ax[0].imshow(img) ax[1].imshow(out1) ax[2].imshow(out2) for a in ax: a.axis('off') plt.tight_layout() return out1,out2
def _process_frame(self, frame): # load volume #d2_data = ND2Reader(self.nd2_file) with ND2Reader(self.nd2_file) as nd2_data: v = get_nd2_vol(nd2_data, self.conf['object_channel'], frame) self.inspect_steps[0] = dict(name='original_volume', data=v) v = array_to_int8(v) # denoise images vi = vol_to_images(v) vi_dn = list(map(denoise, vi)) v_dn = images_to_vol(vi_dn) v_dn = array_to_int8(v_dn) self.inspect_steps[1] = dict(name='denoised_volume', data=v_dn) #th, v_th = voting_threshold(v, adjust=8) # difference of gaussian v_dni = vol_to_images(v_dn) dog = create_dog_func(self.conf['dog_sigma1'], self.conf['dog_sigma2']) v_dg = images_to_vol(list(map(dog, v_dni))) self.inspect_steps[2] = dict(name='dog_volume', data=v_dg) # threshold v_dg_th = v_dg > self.conf['threshold'] v_dg = array_to_int8(v_dg) self.inspect_steps[3] = dict(name='threshold_volume', data=v_dg_th) # watershed and create labels local_maxi = peak_local_max( v_dg, indices=False, min_distance=self.conf['peak_min_dist'], labels=v_dg_th) markers, num_objects = ndi.label(local_maxi, structure=np.ones((3, 3, 3))) #v_labels = watershed(-v_dg, markers, mask=v_dg_th) v_labels = watershed(-v_dg, markers, mask=v_dg_th, compactness=1) self.inspect_steps[4] = dict(name='labels_volume', data=v_labels) # add to labels dask array to list self.labels[frame] = da.array(v_labels) # extract info from labels labels_idx = np.arange(1, v_labels.max()) label_pos = ndi.measurements.center_of_mass( v_dg_th, v_labels, labels_idx) df = pd.DataFrame(label_pos) #collect data for inspection if self.conf['process_type'] == 'single_thread': self.inspect_steps[0] = dict(name='original_volume', data=v) self.inspect_steps[1] = dict(name='denoised_volume', data=v_dn) self.inspect_steps[2] = dict(name='dog_volume', data=v_dg) self.inspect_steps[3] = dict(name='threshold_volume', data=v_dg_th) self.inspect_steps[4] = dict(name='labels_volume', data=v_labels) #makes a dataframe with all coordinates df.columns = ['x', 'y', 'z'] # adjust xs, ys to centrer roi if self.conf['center_roi']: adjust_x = self.conf['nd2info']['roi_x'] adjust_y = self.conf['nd2info']['roi_y'] else: adjust_x = 0 adjust_y = 0 df['xs'] = df['x'] * self.conf['nd2info']['px_microns'] - adjust_x df['ys'] = df['y'] * self.conf['nd2info']['px_microns'] - adjust_y df['zs'] = df['z'] * self.conf['z_dist'] if self.conf['rotate']: #theta = np.radians(self.conf['rotate_angle']) #df['xxs'] = df['xs']*np.cos(theta) + df['ys']*np.sin(theta) #df['yys'] = df['ys']*np.cos(theta) - df['xs']*np.sin(theta) rot = Rot.from_euler('z', -self.conf['rotate_angle'], degrees=True) xyz = df[['xs', 'ys', 'zs']].to_numpy() xyz_rot = rot.apply(xyz) df['xs'], df['ys'] = xyz_rot[:, 0], xyz_rot[:, 1] df.insert(0, 'frame', frame) df.insert(1, 'time', frame / self.conf['nd2info']['frame_rate']) df.insert(0, 'path', self.nd2_file) df['size'] = ndi.measurements.sum(v_dg_th, v_labels, labels_idx) df['int_mean'] = ndi.measurements.mean(v, v_labels, labels_idx) df['int_max'] = ndi.measurements.maximum(v, v_labels, labels_idx) #df['c']=c intensity_channels = self.conf['intensity_channels'] for c in intensity_channels: v_int = get_nd2_vol(nd2_data, c, frame) #v_int=ndimage.zoom(imf.get_vol(t=t, c=c2), (1,1,4),order=0) df['c' + str(c) + '_mean'] = ndi.measurements.mean( v_int, v_labels, labels_idx) df['c' + str(c) + '_max'] = ndi.measurements.maximum( v_int, v_labels, labels_idx) return df
#imsave(amb_cc_save_fp, amb_cc) print(f"amb cc max: {np.max(amb_cc)}") print(f"amb cc n: {len(np.unique(amb_cc))}") ################## ### WATERSHED ################## from skimage.measure import label from skimage.morphology import remove_small_objects from skimage.segmentation import watershed print('doing watershed') ws_w_small = watershed(image=boundary, markers=amb_cc, mask=area_bin.astype(np.uint16)) print('removing small') ws_removed = remove_small_objects(ws_w_small, min_size=1500) ws_removed = ws_removed.astype(np.uint16) print('watershed done, saving') ws_save_fp = ws_save_name + ".tiff" imsave(ws_save_fp, ws_removed, check_contrast=False, compress=True) print('finished') ######################## ### CONVERT TO H5
def compute_cell_bmap(cell_probs): output = cell_probs #output=output/np.max(output) #np.save('/Users/bharath/research/temp.npy',output) output2 = output[::2, ::2] local_maxi = peak_local_max(output2, indices=False, min_distance=5) markers = ndi.label(local_maxi, structure=np.ones((3, 3)))[0] maxscores = {} #markers[output2<0.01] = -1 #segments = random_walker(output2, markers, tol=0.01) segments = watershed(-output2, markers, mask=output2 > 0.01) segments = resize(segments, output.shape, order=0, preserve_range=True) for l in np.unique(segments): maxscores[l] = np.max(output[segments == l]) gx = convolve2d(segments, np.array([[1, 0, -1]]), mode='same') gx[0, :] = 0 gx[-1, :] = 0 gx[:, 0] = 0 gx[:, -1] = 0 gy = convolve2d(segments, np.array([[1, 0, -1]]).T, mode='same') gy[0, :] = 0 gy[-1, :] = 0 gy[:, 0] = 0 gy[:, -1] = 0 gmag = np.sqrt(gx**2 + gy**2) gmag = gmag > 0 D = {} P = {} y, x = np.where(gmag) for i in range(y.size): nearby_labels = np.unique(segments[y[i] - 1:y[i] + 2, x[i] - 1:x[i] + 2]) t = tuple(nearby_labels) if t in D.keys(): D[t].append([y[i], x[i]]) P[t].append(cell_probs[y[i], x[i]]) else: D[t] = [[y[i], x[i]]] P[t] = [cell_probs[y[i], x[i]]] bmap = np.zeros(cell_probs.shape) for t in D.keys(): min_peak = np.min([maxscores[k] for k in t if k != 0]) coords = np.array(D[t]) #if 2-way boundary: if len(t) < 3: score = np.mean(np.array(P[t])) else: perms = permutations(t, 2) perms = [np.mean(P[t]) for t in perms if t in P.keys()] score = np.min(perms) if 0 in t: bmap[coords[:, 0], coords[:, 1]] = 1 else: bmap[coords[:, 0], coords[:, 1]] = min_peak - score bmap[0, :] = 1 bmap[-1, :] = 1 bmap[:, 0] = 1 bmap[:, -1] = 1 return bmap
import numpy as np from skimage.data import astronaut from skimage.color import rgb2gray from skimage.filters import sobel from skimage.segmentation import felzenszwalb, slic, quickshift, watershed from skimage.segmentation import mark_boundaries from skimage.util import img_as_float img = img_as_float(astronaut()[::2, ::2]) segments_fz = felzenszwalb(img, scale=100, sigma=0.5, min_size=50) segments_slic = slic(img, n_segments=250, compactness=10, sigma=1) segments_quick = quickshift(img, kernel_size=3, max_dist=6, ratio=0.5) gradient = sobel(rgb2gray(img)) segments_watershed = watershed(gradient, markers=250, compactness=0.001) print("Felzenszwalb number of segments: {}".format(len(np.unique(segments_fz)))) print('SLIC number of segments: {}'.format(len(np.unique(segments_slic)))) print('Quickshift number of segments: {}'.format(len(np.unique(segments_quick)))) fig, ax = plt.subplots(2, 2, figsize=(10, 10), sharex=True, sharey=True) ax[0, 0].imshow(mark_boundaries(img, segments_fz)) ax[0, 0].set_title("Felzenszwalbs's method") ax[0, 1].imshow(mark_boundaries(img, segments_slic)) ax[0, 1].set_title('SLIC') ax[1, 0].imshow(mark_boundaries(img, segments_quick)) ax[1, 0].set_title('Quickshift') ax[1, 1].imshow(mark_boundaries(img, segments_watershed)) ax[1, 1].set_title('Compact watershed')
def model_predict(img_path): #print(img_path) image = cv2.imread(img_path) #print(image.size) R = image[:, :, 0] G = image[:, :, 1] B = image[:, :, 2] temp = ((len(R) - 2) * (len(R[0]) - 2)) avg = [None] * temp cov = [None] * temp avg1 = [None] * temp cov1 = [None] * temp avg2 = [None] * temp cov2 = [None] * temp #Kanal Red z = 0 w = 0 for x in range(1, len(R) - 1): for y in range(1, len(R[0]) - 1): avg[z] = (float(R[x - 1][y + 1]) + float(R[x][y + 1]) + float(R[x + 1][y + 1]) + float(R[x + 1][y]) + float(R[x + 1][y - 1]) + float(R[x][y - 1]) + float(R[x - 1][y - 1]) + float(R[x - 1][y])) / 8 z = z + 1 for x in range(1, len(R) - 1): for y in range(1, len(R[0]) - 1): cov[w] = numpy.sqrt(((avg[w] - float(R[x - 1][y + 1]))**2 + (avg[w] - float(R[x][y + 1]))**2 + (avg[w] - float(R[x + 1][y + 1]))**2 + (avg[w] - float(R[x + 1][y]))**2 + (avg[w] - float(R[x + 1][y - 1]))**2 + (avg[w] - float(R[x][y - 1]))**2 + (avg[w] - float(R[x - 1][y - 1]))**2 + (avg[w] - float(R[x - 1][y]))**2) / 8) w = w + 1 #Kanal Green z = 0 w = 0 for x in range(1, len(G) - 1): for y in range(1, len(G[0]) - 1): avg1[z] = (float(G[x - 1][y + 1]) + float(G[x][y + 1]) + float(G[x + 1][y + 1]) + float(G[x + 1][y]) + float(G[x + 1][y - 1]) + float(G[x][y - 1]) + float(G[x - 1][y - 1]) + float(G[x - 1][y])) / 8 z = z + 1 for x in range(1, len(G) - 1): for y in range(1, len(G[0]) - 1): cov1[w] = numpy.sqrt(((avg1[w] - float(G[x - 1][y + 1]))**2 + (avg1[w] - float(G[x][y + 1]))**2 + (avg1[w] - float(G[x + 1][y + 1]))**2 + (avg1[w] - float(G[x + 1][y]))**2 + (avg1[w] - float(G[x + 1][y - 1]))**2 + (avg1[w] - float(G[x][y - 1]))**2 + (avg1[w] - float(G[x - 1][y - 1]))**2 + (avg1[w] - float(G[x - 1][y]))**2) / 8) w = w + 1 #Kanal Blue z = 0 w = 0 for x in range(1, len(B) - 1): for y in range(1, len(B[0]) - 1): avg2[z] = (float(B[x - 1][y + 1]) + float(B[x][y + 1]) + float(B[x + 1][y + 1]) + float(B[x + 1][y]) + float(B[x + 1][y - 1]) + float(B[x][y - 1]) + float(B[x - 1][y - 1]) + float(B[x - 1][y])) / 8 z = z + 1 for x in range(1, len(B) - 1): for y in range(1, len(B[0]) - 1): cov2[w] = numpy.sqrt(((avg2[w] - float(B[x - 1][y + 1]))**2 + (avg2[w] - float(B[x][y + 1]))**2 + (avg2[w] - float(B[x + 1][y + 1]))**2 + (avg2[w] - float(B[x + 1][y]))**2 + (avg2[w] - float(B[x + 1][y - 1]))**2 + (avg2[w] - float(B[x][y - 1]))**2 + (avg2[w] - float(B[x - 1][y - 1]))**2 + (avg2[w] - float(B[x - 1][y]))**2) / 8) w = w + 1 matrix2 = numpy.empty([1, temp, 6]) for y in range(0, temp): matrix2[0][y] = [ avg[y] / 2, cov[y], avg1[y] / 2, cov1[y], avg2[y] / 2, cov2[y] ] X = matrix2[0] #print(X) pkl_filename = "models/kmeans_model.pkl" with open(pkl_filename, 'rb') as file: pickle_model = pickle.load(file) y_kmeans = pickle_model.predict(X) #kmeans = KMeans(n_clusters=5, random_state=0).fit(model) #y_kmeans = kmeans.predict(X) #Redrawing the matrix matrix3 = numpy.empty([len(R) - 2, len(R[0]) - 2]) t = 0 for x in range(0, len(matrix3)): for y in range(0, len(matrix3[0])): matrix3[x][y] = y_kmeans[t] t = t + 1 #Redrawing Targeted Color matrix4 = numpy.empty([len(R) - 2, len(R[0]) - 2]) t = 0 for x in range(0, len(matrix4)): for y in range(0, len(matrix4[0])): if (y_kmeans[t] == 2): matrix4[x][y] = 1 else: matrix4[x][y] = 0 t = t + 1 kernel = numpy.ones((3, 3), numpy.uint8) erosi = cv2.erode(matrix4, kernel, iterations=1) D = ndimage.distance_transform_edt(erosi) localMax = peak_local_max(D, indices=False, min_distance=10, labels=erosi) # perform a connected component analysis on the local peaks, # using 8-connectivity, then appy the Watershed algorithm markers = ndimage.label(localMax, structure=numpy.ones((3, 3)))[0] labels = watershed(-D, markers, mask=erosi) print("[INFO] {} unique segments found".format( len(numpy.unique(labels)) - 1)) total_label = format(len(numpy.unique(labels)) - 1) plt.imsave('static/img_conv/testbc2.png', erosi, cmap='gray') #return render_template('index.html', name = 'new_plot', filename ='testbc2.png') return total_label