def degrade_line(im, eta=0, alpha=1.7, beta=1.7, alpha_0=1, beta_0=1): """ Degrades a line image by adding noise Args: im (PIL.Image): Input image Returns: PIL.Image in mode 'L' """ im = pil2array(im) im = np.amax(im) - im im = im * 1.0 / np.amax(im) # foreground distance transform and flipping to white probability fg_dist = distance_transform_cdt(im, metric='taxicab') fg_prob = alpha_0 * np.exp(-alpha * (fg_dist**2)) + eta fg_prob[im == 0] = 0 fg_flip = np.random.binomial(1, fg_prob) # background distance transform and flipping to black probability bg_dist = distance_transform_cdt(1 - im, metric='taxicab') bg_prob = beta_0 * np.exp(-beta * (bg_dist**2)) + eta bg_prob[im == 1] = 0 bg_flip = np.random.binomial(1, bg_prob) # flip im -= fg_flip im += bg_flip # use a circular kernel of size 3 sel = np.array([[1, 1], [1, 1]]) im = binary_closing(im, sel) return array2pil(255 - im.astype('B') * 255)
def compute_error(self, true_mask: Mask, pred_mask: Mask, c: int = 5, p: float = 2): """ Compute the Baddeley Error for binary images. Note: A.J. Baddeley - "An Error Metric for Binary Images" """ # Ensure that masks have binary values true_mask = true_mask > 0 pred_mask = pred_mask > 0 # Handle masks filled with the same value xor_mask = true_mask ^ pred_mask if (~xor_mask).all(): # Masks equal return 1.0 elif xor_mask.all(): # Masks completely different return 0.0 # Compute metric true_edt = distance_transform_cdt(true_mask, metric='taxicab').astype(float) true_edt = np.minimum(true_edt, c) true_edt[true_edt < 0] = c # where a distance cannot be computed, set to maximum pred_edt = distance_transform_cdt(pred_mask, metric='taxicab').astype(float) pred_edt = np.minimum(pred_edt, c) pred_edt[pred_edt < 0] = c dist = np.abs(true_edt - pred_edt) dist /= c # c is the maximum possible distance dist = (dist**p).mean()**(1 / p) return 1.0 - dist
def __init__(self, img_mask_name, crop_sz=(64, 64), num_data=10000, transform=None): """ Args: img_mask_name: list of name pairs of image and mask data, each pair is a tuple of (img_name, mask_name) For mask, 1-positive samples, 0-negative samples crop_sz: cropping size num_data: generated sample size transform: data augmentation """ self.img_all = {} self.mask_all = {} self.seg_all = { } # segmented image, used as a reference to generate training samples by random cropping self.num_pairs = len(img_mask_name) for i in range(self.num_pairs): curr_name = img_mask_name[i] assert os.path.exists(curr_name[0]) and os.path.exists(curr_name[1]), \ 'Image or mask does not exist!' img = imread(curr_name[0]) thres = threshold_triangle(img) seg_img = np.zeros(img.shape, dtype=img.dtype) seg_img[img > thres] = 1 self.seg_all[str(i)] = seg_img img = img.astype(float) mu = img.mean(axis=(1, 2)) sigma = img.std(axis=(1, 2)) img = (img - mu.reshape(len(mu), 1, 1)) / sigma.reshape( len(sigma), 1, 1) self.img_all[str(i)] = img msk_data = np.load(curr_name[1], allow_pickle=True).tolist() mask = msk_data['masks'] mask[mask != -1] = 1 mask[mask == -1] = 0 obj_dist = distance_transform_cdt(mask, metric='chessboard') bg = np.zeros(mask.shape, dtype=mask.dtype) bg[mask == 0] = 1 bg_dist = distance_transform_cdt(bg, metric='chessboard') bg_dist[bg_dist > 4] = 4 mask_dist = (obj_dist - bg_dist).astype(float) self.mask_all[str(i)] = mask_dist self.crop_sz = crop_sz self.num_data = num_data self.transform = transform
def create_dt_mask(self, pnum, grid_size): batch_mask = np.zeros( [pnum, grid_size * grid_size], dtype=np.float32) # Initialize your array of zeros for i in range(pnum): mask = np.zeros([grid_size, grid_size], dtype=np.float32) # Initialize your array of zeros thera = 1.0 * i / pnum * 2 * 3.1416 x = np.cos(thera) y = -np.sin(thera) x = (0.7 * x + 1) / 2 y = (0.7 * y + 1) / 2 mask[np.clip(np.floor(y * (grid_size - 1)), 0, grid_size - 1).astype(int), np.clip(np.floor(x * (grid_size - 1)), 0, grid_size - 1).astype(int)] = 1 dt_mask = grid_size - distance_transform_cdt( 1 - mask, metric='taxicab').astype(np.float32) dt_mask[dt_mask < grid_size - 15] = 0 batch_mask[i] = dt_mask.reshape(-1) return batch_mask
def get_weight(polygon_targets): batch_targets = [] for b in range(polygon_targets.shape[0]): target_ins = [] for p in polygon_targets[b]: t = np.zeros(h * w + 1) t[p] = 1 if p != h * w: spatial_part = t[:-1].reshape(h, w) spatial_part = -1 * (spatial_part - 1) spatial_part = distance_transform_cdt( spatial_part, metric='taxicab').astype(np.float32) spatial_part = np.clip(spatial_part, 0, dt_threshold) spatial_part /= dt_threshold spatial_part = -1. * (spatial_part - 1.) spatial_part /= np.sum(spatial_part) spatial_part = spatial_part.flatten() t = np.concatenate([spatial_part, [0.]], axis=-1) target_ins.append(t.astype(np.float32)) batch_targets.append(target_ins) batch_targets = np.array(batch_targets).astype(np.float32) batch_targets = torch.from_numpy(batch_targets).reshape( batch_size, -1, h * w + 1).to(polygon_targets.device) return batch_targets
def load(self, index): if index < len(self.images) and index < len( self.gt_segmentations) and index < len(self.gt_boundaries): image = np.copy(self.images[index]) gt_segmentation = np.copy(self.gt_segmentations[index]) gt_boundary = np.copy(self.gt_boundaries[index]) else: image = scipy.misc.imread(self.image_filenames[index], flatten=False).astype(float) if self.equalize_histogram: histmin, histmax = get_isbi_dataset_intensity_min_max( self.image_filenames[index]) image = do_equalize_histogram(image, histmin=histmin, histmax=histmax) gt_segmentation = None gt_boundary = None if len(self.gt_filenames) > index: gt_segmentation = scipy.misc.imread(self.gt_filenames[index], flatten=False) boundary_pixels = np.ones(gt_segmentation.shape, dtype=bool) boundary_pixels[0:-1, :] &= ( gt_segmentation[0:-1, :] == gt_segmentation[1:, :]) boundary_pixels[1:, :] &= ( gt_segmentation[1:, :] == gt_segmentation[0:-1, :]) boundary_pixels[:, 0:-1] &= ( gt_segmentation[:, 0:-1] == gt_segmentation[:, 1:]) boundary_pixels[:, 1:] &= ( gt_segmentation[:, 1:] == gt_segmentation[:, 0:-1]) gt_boundary = distance_transform_cdt( boundary_pixels, metric='taxicab').astype(float) gt_boundary[gt_boundary > self.dt_bound] = self.dt_bound gt_segmentation = (gt_segmentation > 0.5) gt_segmentation = gt_segmentation.astype(float) return (image, gt_segmentation, gt_boundary)
def skeleton2graph(dendrite_id, dendrite_folder, seg, res, shrink=False): print('generate graph from skeleton ..') skel = ReadSkeletons(dendrite_folder, skeleton_algorithm='thinning', downsample_resolution=res, read_edges=True)[1] sz = seg.shape # bb = GetBbox(seg>0) bb = GetBbox(seg == int(dendrite_id)) seg_b = seg[bb[0]:bb[1] + 1, bb[2]:bb[3] + 1, bb[4]:bb[5] + 1] dt = distance_transform_cdt(seg_b, return_distances=True) new_graph, wt_dict, th_dict, ph_dict = GetGraphFromSkeleton( skel, dt=dt, dt_bb=[bb[x] for x in [0, 2, 4]], modified_bfs=modified_bfs) edge_list = GetEdgeList(new_graph, wt_dict, th_dict, ph_dict) G = nx.Graph(shape=sz) # add edge attributes G.add_edges_from(edge_list) if shrink == True: #shrink graph size edgTh = [40, 1] # threshold n0 = len(G.nodes()) G = ShrinkGraph_v2(G, threshold=edgTh) n1 = len(G.nodes()) print('#nodes: %d -> %d' % (n0, n1)) return G, skel
def getEdgeDistByMask(self, mask3D, setID, sigma=4.5): result = Preprocessor.loadThresholdMask(setID) #result = generic_gradient_magnitude(result, sobel).astype(np.float32) #result = nd.filters.gaussian_filter(result, sigma) result = morph.distance_transform_cdt(result, metric='taxicab').astype( np.float32) return result[mask3D]
def get_indeces(image_path): # Load image from path Image = io.loadmat(image_path) Label = np.zeros(Image['scanROI'].shape) Label[Image['goldROI'] == 2] = 1 Scan = Image["scanROI"] Dims = np.prod(Scan.shape) # units = np.divide(Image['scanROI'].shape, 100.0) # max = np.array([0.9854, 0.7775, 0.6922]) # min = np.array([0.4995, 0.1120, 0.0538]) # xl, yl, zl = np.around(np.multiply(Scan.shape, max)) # xu, yu, zu = np.int32(np.floor(np.multiply(Scan.shape, min))) # # cropped = np.squeeze(np.where(Label[xu:xl, yu:yl, zu:zl] >= 0)) # X = np.asarray([cropped[0] +xu, cropped[1]+yu , cropped[2] + zu]) B = morphology.distance_transform_cdt(np.absolute(Label - 1)) B = B.reshape(Dims) X = np.squeeze(np.where(B < 6)) Inds = np.asarray(np.unravel_index(X, Scan.shape, order='C')) return Inds.T, Label, Image
def CompactLabel(Label, Compaction=3): """Re-labels objects that have multiple non-contiguous portions to create a new label image where each object is contiguous. Parameters: ----------- Label : array_like A uint32 type label image generated by segmentation methods. Compaction : int Factor used in compacting objects to remove thin spurs. Refered to as 'd' in the reference below. Default value = 3. Notes: ------ Implemented from the reference below. Returns: -------- Split : array_like A uint32 label where discontiguous objects are split and relabeled. See Also: --------- AreaOpenLabel, CondenseLabel, ShuffleLabel, SplitLabel, WidthOpenLabel References: ----------- .. [1] S. Weinert et al "Detection and Segmentation of Cell Nuclei in Virtual Microscopy Images: A Minimum-Model Approach" in Nature Scientific Reports,vol.2,no.503, doi:10.1038/srep00503, 2012. """ # copy input image Compact = Label.copy() # generate distance map of label image D = mp.distance_transform_cdt(Compact > 0, metric='taxicab') # define 4-neighbors filtering kernel Kernel = np.zeros((3, 3), dtype=np.bool) Kernel[1, :] = True Kernel[:, 1] = True # sweep over distance values from d-1 to 1 for i in np.arange(Compaction-1, 0, -1): # four-neighbor maxima of distance transform MaxD = ft.maximum_filter(D, footprint=Kernel) # identify pixels whose max 4-neighbor is less than i+1 Decrement = (D == i) & (MaxD < i+1) # decrement non-compact pixels D[Decrement] -= 1 # zero label pixels where D == 0 Compact[D == 0] = 0 return Compact
def Sampling(image_path): """ :param image_path: path to image generated by get_paths :param patch_sizes: a list or array of patch sizes desired for convolution. Must be odd > 1. :param total_sample_size: sampled patches for convolution, and corresponding labels :return: sampled patches for convolution, and corresponding labels """ # Load image from path Image = io.loadmat(image_path) # Extract total number of voxels Dims = np.prod(Image['scan'].shape) # Create 1 mask image Label = (Image['Tibia'] + 2 * Image['Femur']) np.place(Label, Label > 2, [2, 1]) if Image['isright'] == 0: Scan = np.fliplr(Image["scan"]) Label = np.fliplr(Label) else: Scan = Image["scan"] Label2 = (Image['Tibia'] + Image['Femur']) B = morphology.distance_transform_cdt(np.absolute(Label2 - 1)) B = B.reshape(Dims) X = np.float32(range(np.max(B), 3, -1)) / range(4, np.max(B) + 1, 1) No_samples = 18000 Index = np.array([]) samples = np.divide(X, sum(X)) * No_samples for i in range(4, np.max(B) + 1): Index = np.int32( np.append( Index, np.random.choice(np.squeeze(np.where(B == i)), (samples[i - 4]), replace=False))) Label = Label.reshape(Dims) # Find indexes of voxels to sample Gold_ind = np.squeeze(np.where(Label == 1)) Silv_ind = np.squeeze(np.where(Label == 2)) Edge_ind = np.squeeze(np.where((B > 0) & (B <= 2))) Index = np.hstack((Gold_ind, Silv_ind, Edge_ind, Index)) np.random.shuffle(Index) Inds = np.asarray(np.unravel_index(Index, Scan.shape, order='C')) Label_Sample = Label[Index] return Scan, Label_Sample, Inds.T
def degrade_line(im, eta=0.0, alpha=1.5, beta=1.5, alpha_0=1.0, beta_0=1.0): """ Degrades a line image by adding noise. For parameter meanings consult [1]. Args: im (PIL.Image): Input image eta (float): alpha (float): beta (float): alpha_0 (float): beta_0 (float): Returns: PIL.Image in mode '1' """ logger.debug('Inverting and normalizing input image') im = pil2array(im) im = np.amax(im) - im im = im * 1.0 / np.amax(im) logger.debug('Calculating foreground distance transform') fg_dist = distance_transform_cdt(1 - im, metric='taxicab') logger.debug('Calculating flip to white probability') fg_prob = alpha_0 * np.exp(-alpha * (fg_dist**2)) + eta fg_prob[im == 1] = 0 fg_flip = np.random.binomial(1, fg_prob) logger.debug('Calculating background distance transform') bg_dist = distance_transform_cdt(im, metric='taxicab') logger.debug('Calculating flip to black probability') bg_prob = beta_0 * np.exp(-beta * (bg_dist**2)) + eta bg_prob[im == 0] = 0 bg_flip = np.random.binomial(1, bg_prob) # flip logger.debug('Flipping') im -= bg_flip im += fg_flip logger.debug('Binary closing') sel = np.array([[1, 1], [1, 1]]) im = binary_closing(im, sel) logger.debug('Converting to image') return array2pil(255 - im.astype('B') * 255)
def degrade_line(im, eta=0.0, alpha=1.5, beta=1.5, alpha_0=1.0, beta_0=1.0): """ Degrades a line image by adding noise. For parameter meanings consult [1]. Args: im (PIL.Image): Input image eta (float): alpha (float): beta (float): alpha_0 (float): beta_0 (float): Returns: PIL.Image in mode '1' """ logger.debug(u'Inverting and normalizing input image') im = pil2array(im) im = np.amax(im)-im im = im*1.0/np.amax(im) logger.debug(u'Calculating foreground distance transform') fg_dist = distance_transform_cdt(1-im, metric='taxicab') logger.debug(u'Calculating flip to white probability') fg_prob = alpha_0 * np.exp(-alpha * (fg_dist**2)) + eta fg_prob[im == 1] = 0 fg_flip = np.random.binomial(1, fg_prob) logger.debug(u'Calculating background distance transform') bg_dist = distance_transform_cdt(im, metric='taxicab') logger.debug(u'Calculating flip to black probability') bg_prob = beta_0 * np.exp(-beta * (bg_dist**2)) + eta bg_prob[im == 0] = 0 bg_flip = np.random.binomial(1, bg_prob) # flip logger.debug(u'Flipping') im -= bg_flip im += fg_flip logger.debug(u'Binary closing') sel = np.array([[1, 1], [1, 1]]) im = binary_closing(im, sel) logger.debug(u'Converting to image') return array2pil(255-im.astype('B')*255)
def Sampling(image_path): """ :param image_path: path to image generated by get_paths :param patch_sizes: a list or array of patch sizes desired for convolution. Must be odd > 1. :param total_sample_size: sampled patches for convolution, and corresponding labels :return: sampled patches for convolution, and corresponding labels """ # Load image from path Image = io.loadmat(image_path) # Extract total number of voxels Dims = np.prod(Image['scanROI'].shape) # Create 1 mask image Label = np.zeros(Image['scanROI'].shape) Label[Image['goldROI'] == 2] = 1 Scan = Image["scanROI"] #max = np.array([0.9854, 0.7775, 0.6922]) #min = np.array([0.4995, 0.1120, 0.0538]) #xl, yl, zl =np.int32(np.around(np.multiply(Scan.shape, max))) #xu, yu, zu = np.int32(np.floor(np.multiply(Scan.shape, min))) #cropped = np.squeeze(np.where(Label[xu:xl, yu:yl, zu:zl] >= 0)) #X = np.asarray([cropped[0] +xu, cropped[1]+yu , cropped[2] + zu]) # MM = np.ravel_multi_index(X, np.asarray(Scan.shape)) B = morphology.distance_transform_cdt(np.absolute(Label - 1)) B = B.reshape(Dims) # Gold_ind = np.squeeze(np.where(Label == 1 )) # X = np.float32(range(np.max(B), 1, -1))/range(2, np.max(B)+1, 1) # No_samples = np.shape(Gold_ind)[1] # A = B[MM] # Index = np.array([]) # samples = np.divide(X, sum(X))*No_samples # for i in range(2, np.max(A)): # Index = np.int32(np.append(Index, np.random.choice(np.squeeze(np.where(A == i)),(np.floor(samples)[i-1]), replace=False))) Label = Label.reshape(Dims) # Find indexes of voxels to sample Gold_ind = np.squeeze(np.where(Label == 1)) Indeg = np.int32( np.random.choice(np.squeeze(Gold_ind), 1000, replace=False)) P_ind = np.squeeze(np.where(np.logical_and(B > 0, B < 6))) Index = np.int32(np.random.choice(np.squeeze(P_ind), 1000, replace=False)) Index = np.hstack((Index, Indeg)) np.random.shuffle(Index) Inds = np.asarray(np.unravel_index(Index, Scan.shape, order='C')) Indie = Inds.reshape(3, 1, Inds.shape[1]).T Label_Sample = Label[Index] return Scan, Label_Sample, Inds.T
def roi_track_counts(fdpy,fref,fatlas,roi_no,dist_transf=True,fres=None): dpr=Dpy(fdpy,'r') T=dpr.read_tracks() dpr.close() img=nib.load(fref) affine=img.get_affine() zooms = img.get_header().get_zooms() iaffine=np.linalg.inv(affine) T2=[] #go back to volume space for t in T: T2.append(np.dot(t,iaffine[:3,:3].T)+iaffine[:3,3]) del T tcs,tes=track_counts(T2,img.get_shape(),zooms,True) atlas_img=nib.load(fatlas) atlas=atlas_img.get_data() roi=atlas.copy() roi[atlas!=roi_no]=0 if dist_transf: roi2=distance_transform_cdt(roi) roi[roi2!=roi2.max()]=0 I=np.array(np.where(roi==roi_no)).T else: I=np.array(np.where(roi==roi_no)).T """ if erosion_level>0: roi2=binary_erosion(roi,cross,erosion_level) I=np.array(np.where(roi2==True)).T else: roi2=distance_transform_cdt(roi) I=np.array(np.where(roi==roi_no)).T """ #print I.shape #nib.save(nib.Nifti1Image(roi2,affine),'/tmp/test.nii.gz') Ttes=[] for iroi in I: try: Ttes.append(tes[tuple(iroi)]) except KeyError: pass Ttes=list(set(list(chain.from_iterable(Ttes)))) T2n=np.array(T2,dtype=np.object) res=list(T2n[Ttes]) #back to world space res2=[] for t in res: res2.append(np.dot(t,affine[:3,:3].T)+affine[:3,3]) np.save(fres,np.array(res2,dtype=np.object))
def main(): H, W = MAP() A = [INPUT() for _ in range(H)] # A : 2 次元 numpy 配列. 白マス -> True, 黒マス -> False A = np.array([[(Ai[j] != "#") for j in range(W)] for Ai in A]) # distance_transform_cdt(X) : 2 次元 numpy 配列 X の要素 0 からの距離を要素に持つ 2 次元 numpy 配列を返す. # [metric] taxicab : マンハッタン距離 (4 近傍), chessboard : チェビシェフ距離 (8 近傍) print(distance_transform_cdt(A, metric="taxicab").max())
def Sampling(image_path): """ :param image_path: path to image generated by get_paths :param patch_sizes: a list or array of patch sizes desired for convolution. Must be odd > 1. :param total_sample_size: sampled patches for convolution, and corresponding labels :return: sampled patches for convolution, and corresponding labels """ # Load image from path Image = io.loadmat(image_path) # Extract total number of voxels Dims = np.prod(Image['scanROI'].shape) # Create 1 mask image Label = np.zeros(Image['scanROI'].shape) # Label[Image['classIm'] == 1] = 1 Label[Image['classIm'] == 1] = 1 if Image['isright'] == 0: Scan = np.fliplr(Image["scanROI"]) Label = np.fliplr(Label) else: Scan = Image["scanROI"] Gold_ind = np.squeeze(np.where(Label == 1)) B = morphology.distance_transform_cdt(np.absolute(Label - 1)) B = B.reshape(Dims) X = np.float32(range(np.max(B), 1, -1)) / range(2, np.max(B) + 1, 1) No_samples = Gold_ind.shape[1] Index = np.array([]) samples = np.divide(X, sum(X)) * No_samples for i in range(2, np.max(B)): Index = np.int32( np.append( Index, np.random.choice(np.squeeze(np.where(B == i)), (samples[i - 1]), replace=False))) Label = Label.reshape(Dims) # Find indexes of voxels to sample Gold_ind = np.squeeze(np.where(Label == 1)) P_ind = np.squeeze(np.where(B > 1) & (B < 5)) Index = np.hstack((Gold_ind, Index, P_ind)) print Index.shape np.random.shuffle(Index) Inds = np.asarray(np.unravel_index(Index, Scan.shape, order='C')) Label_Sample = Label[Index] return Scan, Label_Sample, Inds.T
def DistanceWithoutNormalise(bin_image): res = np.zeros_like(bin_image) for j in range(1, bin_image.max() + 1): one_cell = np.zeros_like(bin_image) one_cell[bin_image == j] = 1 one_cell = distance_transform_cdt(one_cell) res[bin_image == j] = one_cell[bin_image == j] res = res.astype('uint8') return res
def DistanceWithoutNormalise(bin_image): res = np.zeros_like(bin_image) for j in range(1, bin_image.max() + 1): one_cell = np.zeros_like(bin_image) one_cell[bin_image == j] = 1 one_cell = distance_transform_cdt(one_cell) res[bin_image == j] = one_cell[bin_image == j] res = res.astype('uint8') return res
def process(inp): (indir, outdir, basename) = inp print(inp) labelmap = np.array(Image.open(osp.join(indir, basename) ).convert("P")).astype(np.int16) labelmap = _encode_label(labelmap) depth_map = np.zeros(labelmap.shape, dtype=np.float32) dir_map = np.zeros((*labelmap.shape, 2), dtype=np.float32) for id in range(255): labelmap_i = (labelmap == id).astype(np.uint8) if labelmap_i.sum() < 100: continue if args.metric == 'euc': depth_i = distance_transform_edt(labelmap_i) elif args.metric == 'taxicab': depth_i = distance_transform_cdt(labelmap_i, metric='taxicab') else: raise RuntimeError depth_map += depth_i dir_i_before = dir_i = np.zeros_like(dir_map) dir_i = torch.nn.functional.conv2d(torch.from_numpy(depth_i).float().view( 1, 1, *depth_i.shape), sobel_ker, padding=ksize//2).squeeze().permute(1, 2, 0).numpy() # The following line is necessary dir_i[(labelmap_i == 0), :] = 0 dir_map += dir_i depth_map[depth_map > 250] = 250 depth_map = depth_map.astype(np.uint8) deg_reduce = 2 dir_deg_map = np.degrees(np.arctan2( dir_map[:, :, 0], dir_map[:, :, 1])) + 180 dir_deg_map = (dir_deg_map / deg_reduce) print(dir_deg_map.min(), dir_deg_map.max()) dir_deg_map = dir_deg_map.astype(np.uint8) io.savemat( osp.join(outdir, basename.replace("png", "mat")), {"dir_deg": dir_deg_map, "depth": depth_map, 'deg_reduce': deg_reduce}, do_compression=True, ) try: io.loadmat(osp.join(outdir, basename.replace("png", "mat")),) except Exception as e: print(e) io.savemat( osp.join(outdir, basename.replace("png", "mat")), {"dir_deg": dir_deg_map, "depth": depth_map, 'deg_reduce': deg_reduce}, do_compression=False, )
def process(inp): (indir, outdir, basename) = inp print(inp) labelmap = np.array(Image.open(osp.join(indir, basename))) depth_map = np.ones(labelmap.shape) * 0 dir_map = np.zeros((*labelmap.shape, 2)) ignore_id_list = set(range(256)) - label_list for id in ignore_id_list: labelmap[labelmap == id] = 255 labelmap_flattened = np.unique(labelmap) print(labelmap_flattened) for id in labelmap_flattened: labelmap_i = labelmap.copy() labelmap_i[labelmap != id] = 0 labelmap_i[labelmap == id] = 1 # if labelmap_i.sum() < 100: # continue if args.metric == 'euc': depth_i = distance_transform_edt(labelmap_i) elif args.metric == 'taxicab': depth_i = distance_transform_cdt(labelmap_i, metric='taxicab') else: raise RuntimeError depth_map[labelmap_i == 1] = depth_i[labelmap_i == 1] dir_i_before = dir_i = np.zeros_like(dir_map) dir_i = torch.nn.functional.conv2d( torch.from_numpy(depth_i).float().view(1, 1, *depth_i.shape), sobel_ker, padding=ksize // 2).squeeze().permute(1, 2, 0).numpy() # The following line is necessary dir_i[(labelmap_i == 0), :] = 0 dir_map += dir_i depth_map[depth_map > 250] = 250 depth_map = depth_map.astype(np.uint8) # print(np.unique(depth_map)) deg_reduce = 2 dir_deg_map = np.degrees(np.arctan2(dir_map[:, :, 0], dir_map[:, :, 1])) + 180 dir_deg_map = (dir_deg_map / deg_reduce) print(dir_deg_map.min(), dir_deg_map.max()) dir_deg_map = dir_deg_map.astype(np.uint8) dct = { "dir_deg": dir_deg_map, "depth": depth_map, 'deg_reduce': deg_reduce } safe_savemat(osp.join(outdir, basename.replace("png", "mat")), dct)
def get_skeleton(seg_fn, out_folder, bfs, res, edgTh, modified_bfs, opt): if opt == '0': # mesh -> skeleton seg = ReadH5(seg_fn, 'main') CreateSkeleton(seg, out_folder, res, res) elif opt == '1': # skeleton -> dense graph import networkx as nx print('read skel') skel = ReadSkeletons(out_folder, skeleton_algorithm='thinning', downsample_resolution=res, read_edges=True)[1] print('save node positions') node_pos = np.stack(skel.get_nodes()).astype(int) WriteH5(out_folder + 'node_pos.h5', node_pos) print('generate dt for edge width') seg = ReadH5(seg_fn, 'main') sz = seg.shape bb = GetBbox(seg > 0) seg_b = seg[bb[0]:bb[1] + 1, bb[2]:bb[3] + 1, bb[4]:bb[5] + 1] dt = distance_transform_cdt(seg_b, return_distances=True) print('generate graph') new_graph, wt_dict, th_dict, ph_dict = GetGraphFromSkeleton(skel, dt=dt, dt_bb=[bb[x] for x in [0,2,4]],\ modified_bfs=modified_bfs) print('save as a networkx object') edge_list = GetEdgeList(new_graph, wt_dict, th_dict, ph_dict) G = nx.Graph(shape=sz) # add edge attributes G.add_edges_from(edge_list) nx.write_gpickle(G, out_folder + 'graph-%s.obj' % (bfs)) elif opt == '2': # reduced graph import networkx as nx G = nx.read_gpickle(out_folder + 'graph-%s.obj' % (bfs)) n0 = len(G.nodes()) G = ShrinkGraph_v2(G, threshold=edgTh) n1 = len(G.nodes()) print('#nodes: %d -> %d' % (n0, n1)) nx.write_gpickle( G, out_folder + 'graph-%s-%d-%d.obj' % (bfs, edgTh[0], 10 * edgTh[1])) elif opt == '3': # generate h5 for visualization import networkx as nx G = nx.read_gpickle(out_folder + 'graph-%s-%d-%d.obj' % (bfs, edgTh[0], 10 * edgTh[1])) pos = ReadH5(out_folder + 'node_pos.h5', 'main') vis = Graph2H5(G, pos) WriteH5( out_folder + 'graph-%s-%d-%d.h5' % (bfs, edgTh[0], 10 * edgTh[1]), vis)
def Symlink_Mask(r, dst_rgb, dst_mask): rgb = r['path_to_image'] #print rgb mask_name = r['path_to_label'] symlink(rgb, join(dst_rgb, basename(rgb))) mask = imread(mask_name) line = generate_wsl(mask) mask[mask > 0] = 1 mask[line > 0] = 0 mask = distance_transform_cdt(mask) imsave(join(dst_mask, basename(mask_name)), mask)
def dt_image(shape, vertices, thresh=5): """ Create a distance transform image given the size of the canvas and vertices of the polygon. Any distance less than the threshold is set to 0 """ mask = create_polygon(shape, vertices, perimeter=True) # Invert mask = 1 - mask dt_mask = distance_transform_cdt(mask, metric='taxicab').astype(np.float32) dt_mask[dt_mask < thresh] = 0 return dt_mask
def DistanceBinNormalise(bin_image): bin_image = label(bin_image) result = np.zeros_like(bin_image, dtype="float") for k in range(1, bin_image.max() + 1): tmp = np.zeros_like(result, dtype="float") tmp[bin_image == k] = 1 dist = distance_transform_cdt(tmp) MAX = dist.max() dist = dist.astype(float) / MAX result[bin_image == k] = dist[bin_image == k] result = result * 255 result = result.astype('uint8') return result
def DistanceBinNormalise(bin_image): bin_image = label(bin_image) result = np.zeros_like(bin_image, dtype="float") for k in range(1, bin_image.max() + 1): tmp = np.zeros_like(result, dtype="float") tmp[bin_image == k] = 1 dist = distance_transform_cdt(tmp) MAX = dist.max() dist = dist.astype(float) / MAX result[bin_image == k] = dist[bin_image == k] result = result * 255 result = result.astype('uint8') return result
def dist_image(imf): ''' Return the distance image 'imd' of 'imf' imd[r,c] is the distance of pixel (r,c) to the closest edge pixel. ''' imf_inv = 1 - (skimage.img_as_ubyte(imf) != 0) imd = distance_transform_cdt(imf_inv) # imd = cv2.distanceTransform(imf_inv ,cv2.DIST_L2,5) # plt.imshow(imf_inv) # plt.title('imf_inv') # plt.figure() # plt.imshow(imd) # plt.title('imd') # plt.colorbar() return imd
def stringify_board(board): t = {0: '*', 1: '.', 2: '.', 3: 'c'} stringified_board = [''] dt = distance_transform_cdt(board) try: candidate = np.argwhere(dt > 1)[0] board[candidate[0], candidate[1]] = 3 except IndexError: board[0, 0] = 3 for l in board: stringified_board.append("".join([t[e] for e in l])) return "\n".join(stringified_board)
def _augment(self, img, _): img = np.copy(img) orig_ann = img[..., 0] # instance ID map fixed_ann = self._fix_mirror_padding(orig_ann) # re-cropping with fixed instance id map crop_ann = cropping_center(fixed_ann, self.crop_shape) orig_dst = np.zeros(orig_ann.shape, dtype=np.float32) inst_list = list(np.unique(crop_ann)) inst_list.remove(0) # 0 is background for inst_id in inst_list: inst_map = np.array(fixed_ann == inst_id, np.uint8) inst_box = bounding_box(inst_map) # expand the box by 2px inst_box[0] -= 2 inst_box[2] -= 2 inst_box[1] += 2 inst_box[3] += 2 inst_map = inst_map[inst_box[0]:inst_box[1], inst_box[2]:inst_box[3]] if inst_map.shape[0] < 2 or \ inst_map.shape[1] < 2: continue # chessboard distance map generation # normalize distance to 0-1 inst_dst = distance_transform_cdt(inst_map) inst_dst = inst_dst.astype('float32') if self.inst_norm: max_value = np.amax(inst_dst) if max_value <= 0: continue # HACK: temporay patch for divide 0 i.e no nuclei (how?) inst_dst = (inst_dst / np.amax(inst_dst)) #### dst_map_box = orig_dst[inst_box[0]:inst_box[1], inst_box[2]:inst_box[3]] dst_map_box[inst_map > 0] = inst_dst[inst_map > 0] # img = img.astype('float32') img = np.dstack([img, orig_dst]) return img
def dt_targets_from_class(poly, grid_size, dt_threshold): # grid_size: 28 # poly: 即Ground Truth, [bs, seq_len], 每行一个poly, seq_len个值, 每个值是在grid*gird中的index """ NOTE: numpy function! poly: [bs, time_steps], each value in [0, grid*size**2+1) grid_size: size of the grid the polygon is in dt_threshold: threshold for smoothing in dt targets returns: full_targets: [bs, time_steps, grid_size**2+1] array containing dt smoothed targets to be used for the polygon loss function """ full_targets = [] for b in range(poly.shape[0]): targets = [] for p in poly[b]: t = np.zeros(grid_size**2 + 1, dtype=np.int32) t[p] += 1 if p != grid_size**2: #EOS spatial_part = t[:-1] spatial_part = np.reshape(spatial_part, [grid_size, grid_size, 1]) # Invert image spatial_part = -1 * (spatial_part - 1) # Compute distance transform spatial_part = distance_transform_cdt(spatial_part, metric='taxicab').astype( np.float32) # Threshold spatial_part = np.clip(spatial_part, 0, dt_threshold) # Normalize spatial_part /= dt_threshold # Invert back spatial_part = -1. * (spatial_part - 1.) spatial_part /= np.sum(spatial_part) spatial_part = spatial_part.flatten() t = np.concatenate([spatial_part, [0.]], axis=-1) targets.append(t.astype(np.float32)) full_targets.append(targets) return np.array(full_targets, dtype=np.float32)
def from_t2(t2, mask, data_img, split, edge_n=None, grp_target=None): """ scales effect with observations Args: t2 (float): ratio of effect to population variance mask (Mask): effect location data_img (DataImage): grp_target: grp that effect is applied to split (dict): keys are grp labels, values are sbj_list edge_n (int): number of voxels on edge of mask (taxicab erosion) which have a 'scaled' effect. For example, if edge_n = 1, then the outermost layer of voxels has only half the delta applied. see Effect.scale """ # get grp_tuple, grp_tuple[1] has effect applied assert len(split) == 2, 'invalid split' grp_tuple = sorted(split.keys()) if grp_target is not None: assert grp_target in grp_tuple if grp_target is not grp_tuple[1]: grp_tuple = reversed(grp_tuple) # get fs_dict fs_dict = dict() for grp, sbj_list in split.items(): fs_dict[grp] = data_img.get_fs(sbj_list=sbj_list, mask=mask) delta, cov_pool, _, _ = get_t2_stats(fs_dict, grp_tuple=grp_tuple) # compute scale if edge_n is None: scale = mask else: scale = distance_transform_cdt(mask, metric='taxicab') / (edge_n + 1) scale[scale >= 1] = 1 # build effect with proper direction # todo: refactor all pool_cov -> cov_pool eff = EffectConstant(mask=mask, delta=delta, pool_cov=cov_pool, scale=scale) # scale to given t2 return eff.to_t2(t2)
def fitAndDivide(roi_mask, brain_mask, t_map, nii, workdir, iteration): if not os.path.exists(workdir + str(iteration)): os.mkdir(workdir + str(iteration)) flat_data = t_map[roi_mask].ravel().squeeze() (flat_active, selected_model) = fitMixture(flat_data) print "winning model: %s"%selected_model active_map = np.zeros(t_map.shape) == 1 active_map[roi_mask] = flat_active new_img = nb.Nifti1Image(active_map, nii.get_affine(), nii.get_header()) nb.save(new_img, os.path.join(workdir + str(iteration), 'thr_map.nii')) plt.show() #26 connectivity labeled_map, n_regions = label(active_map, generate_binary_structure(3,3)) print "%d disconnected regions"%n_regions distances, indices = distance_transform_cdt(np.logical_not(active_map), metric='chessboard', return_distances=True, return_indices=True) new_img = nb.Nifti1Image(distances, nii.get_affine(), nii.get_header()) nb.save(new_img, os.path.join(workdir+ str(iteration), 'distances.nii')) labels = labeled_map[indices[0,:], indices[1,:], indices[2,:]] for region_id in range(1,n_regions+1): sub_roi_mask = np.zeros(t_map.shape) == 1 sub_roi_mask[np.logical_and(labels == region_id, roi_mask)] = True activity_within_roi = (labeled_map == region_id) new_img = nb.Nifti1Image(sub_roi_mask, nii.get_affine(), nii.get_header()) nb.save(new_img, os.path.join(workdir+ str(iteration), 'sub%d_roi_mask.nii'%region_id)) new_sub_roi_mask = extendROIMask(sub_roi_mask, activity_within_roi, brain_mask) new_img = nb.Nifti1Image(new_sub_roi_mask, nii.get_affine(), nii.get_header()) nb.save(new_img, os.path.join(workdir+ str(iteration), 'new_sub%d_roi_mask.nii'%region_id)) if new_sub_roi_mask != sub_roi_mask: fitAndDivide(new_sub_roi_mask, brain_mask, t_map, nii, workdir += , iteration+1)
def find_seed_centroids(stack): """Find seeds in given binary stack, returning dictionary containing seed centroids.""" distances = distance_transform_cdt(stack) seeds = distances > 10 seed_label_array = label(seeds) seed_labels = {} for seed_label in np.unique(seed_label_array): float_center = map(np.mean, np.where(seed_label_array==seed_label)) int_center = map(int, float_center) seed_name = 'seed{}'.format(seed_label) seed_labels[seed_name] = int_center return seed_labels
def get_roi_new(roi_no,dist_transf=False): atlas_img=nib.load(fatlas) atlas=atlas_img.get_data() roiaff=atlas_img.get_affine() roi=atlas.copy() roi[atlas!=roi_no]=0 if dist_transf: roi2=distance_transform_cdt(roi) roi[roi2!=roi2.max()]=0 I=np.array(np.where(roi==roi_no)).T else: I=np.array(np.where(roi==roi_no)).T wI=np.dot(roiaff[:3,:3],I.T).T+roiaff[:3,3] wI=wI.astype('f4') return wI
def spike_dt(data_file): pm = PathManager(data_file, working_base='/localscratch/ct_analysis') stack_path = pm.spath('raw_stack.stack') z = 273 filename = "z{}.png".format(z) full_path = os.path.join(stack_path, filename) plane = Image.from_file(full_path) threshold = threshold_otsu(plane) thresholded = plane > threshold imsave('t.png', thresholded) dt = distance_transform_cdt(thresholded) imsave('dt.png', dt) print dt.max() tdt = dt > 70 imsave('tdt.png', tdt)
def Sampling(image_path): """ :param image_path: path to image generated by get_paths :param patch_sizes: a list or array of patch sizes desired for convolution. Must be odd > 1. :param total_sample_size: sampled patches for convolution, and corresponding labels :return: sampled patches for convolution, and corresponding labels """ Image = io.loadmat(image_path) Scan = Image['Scan'] Label = np.zeros(Image['Label'].shape) Label[Image['Label'] > 0] = 1 Gold_ind = np.squeeze(np.where(Label >= 1)) Dims = np.prod(Scan.shape) B = morphology.distance_transform_cdt(np.absolute(Label - 1)) B = B.reshape(Dims) X = np.float32(range(np.max(B), 1, -1)) / range(2, np.max(B) + 1, 1) No_samples = Gold_ind.shape[1] Index = np.array([]) samples = np.divide(X, sum(X)) * No_samples for i in range(2, np.max(B)): Index = np.int32( np.append( Index, np.random.choice(np.squeeze(np.where(B == i)), (samples[i - 1]), replace=False))) Label = Label.reshape(Dims) Gold_ind = np.squeeze(np.where(Label >= 1)) # Find indexes of voxels to sample P_ind = np.squeeze(np.where(B == 1)) Index = np.hstack((Gold_ind, Index, P_ind)) np.random.shuffle(Index) Inds = np.asarray(np.unravel_index(Index, Scan.shape, order='C')) Label_Sample = Label[Index] return Scan, Label_Sample, Inds.T
def _get_surface_distance(self, y_pred_edges, y_edges): """ Calculate the surface distances from `y_pred_edges` to `y_edges`. Args: y_pred_edges (np.ndarray): the edge of the predictions. y_edges (np.ndarray): the edge of the ground truth. """ if not np.any(y_pred_edges): return np.array([]) if not np.any(y_edges): dis = np.inf * np.ones_like(y_edges) else: if self.distance_metric == "euclidean": dis = morphology.distance_transform_edt(~y_edges) elif self.distance_metric == "chessboard" or self.distance_metric == "taxicab": dis = morphology.distance_transform_cdt(~y_edges, metric=self.distance_metric) surface_distance = dis[y_pred_edges] return surface_distance
def _get_surface_distance(self, y_pred_edges, y_edges): """ Calculate the surface distances from `y_pred_edges` to `y_edges`. Args: y_pred_edges (np.ndarray): the edge of the predictions. y_edges (np.ndarray): the edge of the ground truth. """ if not np.any(y_pred_edges): return np.array([]) if not np.any(y_edges): dis = np.full(y_edges.shape, np.inf) else: if self.distance_metric == "euclidean": dis = morphology.distance_transform_edt(~y_edges) elif self.distance_metric in self.distance_metric_list[-2:]: dis = morphology.distance_transform_cdt(~y_edges, metric=self.distance_metric) surface_distance = dis[y_pred_edges] return surface_distance
print('read skel') skel = ReadSkeletons(out_folder, skeleton_algorithm='thinning', downsample_resolution=res, read_edges=True)[1] print('save node positions') node_pos = np.stack(skel.get_nodes()).astype(int) WriteH5(out_folder + 'node_pos.h5', node_pos) print('generate dt for edge width') seg = ReadH5(seg_fn, 'main') sz = seg.shape bb = GetBbox(seg > 0) seg_b = seg[bb[0]:bb[1] + 1, bb[2]:bb[3] + 1, bb[4]:bb[5] + 1] dt = distance_transform_cdt(seg_b, return_distances=True) print('generate graph') new_graph, wt_dict, th_dict, ph_dict = GetGraphFromSkeleton(skel, dt=dt, dt_bb=[bb[x] for x in [0,2,4]],\ modified_bfs=modified_bfs) print('save as a networkx object') edge_list = GetEdgeList(new_graph, wt_dict, th_dict, ph_dict) G = nx.Graph(shape=sz) # add edge attributes G.add_edges_from(edge_list) nx.write_gpickle(G, out_folder + 'graph-%s.obj' % (bfs)) elif opt == '2': # reduced graph import networkx as nx G = nx.read_gpickle(out_folder + 'graph-%s.obj' % (bfs))
def dthresh(image): thresh = threshold_otsu(image) thresholded = image > thresh dt = distance_transform_cdt(thresholded) return dt > 18
def dt_and_threshold(input_plane, threshold=75): t_otsu = threshold_otsu(input_plane) thresholded = input_plane > t_otsu dt = distance_transform_cdt(thresholded) return dt > threshold
def compact(im_label, compaction=3): """Performs a thinning operation on a label image to remove thin protrusions from objects that are in contact with the background. Applies a distance transform and sequentially removes pixels with small distances to background that are not connected to higher distance pixels. Parameters ---------- im_label : array_like A labeled segmentation mask compaction : int Factor used in compacting objects to remove thin protrusions. Refered to as d in the reference below. Default value = 3. Notes ----- Implemented from the reference below. Returns ------- im_compact : array_like A labeled segmentation mask with thin protrusions removed. See Also -------- histomicstk.segmentation.label.area_open, histomicstk.segmentation.label.condense, histomicstk.segmentation.label.shuffle, histomicstk.segmentation.label.split, histomicstk.segmentation.label.width_open References ---------- .. [1] S. Weinert et al "Detection and Segmentation of Cell Nuclei in Virtual Microscopy Images: A Minimum-Model Approach" in Nature Scientific Reports,vol.2,no.503, doi:10.1038/srep00503, 2012. """ # copy input image im_compact = im_label.copy() # generate distance map of label image D = mp.distance_transform_cdt(im_compact > 0, metric='taxicab') # define 4-neighbors filtering kernel Kernel = np.zeros((3, 3), dtype=np.bool) Kernel[1, :] = True Kernel[:, 1] = True # sweep over distance values from d-1 to 1 for i in np.arange(compaction-1, 0, -1): # four-neighbor maxima of distance transform MaxD = ft.maximum_filter(D, footprint=Kernel) # identify pixels whose max 4-neighbor is less than i+1 Decrement = (D == i) & (MaxD < i+1) # decrement non-compact pixels D[Decrement] -= 1 # zero label pixels where D == 0 im_compact[D == 0] = 0 return im_compact
def width_open(im_label, width): """Removes thin objects from label image using maximum of distance transform values within each object. Parameters ---------- im_label : array_like A uint32 type label image generated by segmentation methods. width : int width threshold for objects. Objects with fewer than 'Area' pixels will be zeroed to merge with background. Notes ----- Objects are assumed to have positive nonzero values. A binary mask is generated for each object setting all other objects to the background value (0). The maximum chamfered distance transform value of this mask is used to represent the object width. Returns ------- im_thinned : array_like A uint32 label where objects with pixels < Area are removed. See Also -------- histomicstk.segmentation.label.condense, histomicstk.segmentation.label.shuffle, histomicstk.segmentation.label.split, histomicstk.segmentation.label.area_open """ # copy input image im_thinned = im_label.copy() # condense label image if np.unique(im_thinned).size-1 != im_thinned.max(): im_thinned = condense(im_thinned) # get locations of objects in initial label image Locations = ms.find_objects(im_thinned) # iterate through objects, calculating distances where needed for i in np.arange(1, len(Locations)+1): # extract object from label image W = im_thinned[Locations[i-1]] # embed into mask with boundary Mask = np.zeros((W.shape[0]+2, W.shape[1]+2), dtype=np.bool) Mask[1:-1, 1:-1] = W == i # calculate distance transform of mask D = mp.distance_transform_cdt(Mask, metric='taxicab') # get max distance Max = D.max() # zero label mask of object 'i' if Max < width: W[W == i] = 0 # condense to fill gaps im_thinned = condense(im_thinned) return im_thinned