roi = roi[:, :, 3] > 0 # Alternatively a mask could be created manually with for example a disk: # roi = np.zeros((img.shape[0], img.shape[1])) # a, b = 150, 150 # r = 100 # y,x = np.ogrid[-a:img.shape[0]-a, -b:img.shape[1]-b] # mask = x*x + y*y <= r*r # roi[mask] = 1 # ~~~~~~~~~~~~ Example 1: maskSLIC ~~~~~~~~~~~~~ t1 = time.time() # Note that compactness is defined differently because a grid is not used. Lower compactness # for maskSLIC is equivalent segments = seg.slic(img, compactness=10, seed_type='nplace', mask=roi, n_segments=12, recompute_seeds=True, enforce_connectivity=True) print("Time: {:.2f} s".format(time.time() - t1)) plt.figure() plt.title('maskSLIC') plt.imshow(mark_boundaries(img, segments)) plt.contour(roi, contours=1, colors='red', linewidths=1) plt.axis('off') # ~~~~~~~~~~~ Example 2: SLIC ~~~~~~~~~~~~~~~~~ t1 = time.time() segments = seg.slic(img, compactness=30, seed_type='grid', n_segments=80, enforce_connectivity=True) print("Time: {:.2f} s".format(time.time() - t1))
print t2w_mod.data_.shape # Extract the information about the spacing spacing_itk = t2w_mod.metadata_['spacing'] # Remember that this is in ITK format X, Y, Z and that we are in Y, X, Z spacing = (spacing_itk[1], spacing_itk[0], spacing_itk[2]) print spacing # Read the ground-truth gt_mod = GTModality() gt_mod.read_data_from_path(label_gt, path_gt) print gt_mod.data_[0].shape img = t2w_mod.data_[:, :, 32] img = (img - np.min(img)) * ((1.) / (np.max(img) - np.min(img))) roi = gt_mod.data_[0, :, :, 32].astype(bool) # Make SLIC over-segmentation segments = seg.slic(img, compactness=1, seed_type='nplace', multichannel=False, convert2lab=False, enforce_connectivity=True, mask=roi, n_segments=50, recompute_seeds=True, plot_examples=True)
def getTileCoords(self, num_tiles: int, sampling_method='skeleton', tissue_th: tuple = (0.2, 0.7), seed=None, offset: tuple = (0, 0)): ''' Find `num_indices` indices with maximal amount of tissue. `tissue_th` is the slice of tissue percentage ~(min, max) within which we allow the search: sometimes the `max` might not give enough tiles for the mosaic, so we can decrease it gradually until `min` is reached. offset = (x,y) coord offset in tile size fractions that is applied to sampled coords. This is meant as a form of data augmentation. ''' assert sampling_method in {'skeleton', 'tissue_pct', 'slic'} "`sampling_method` should be one of 'skeleton', 'tissue_pct' or 'slic'" level_offset = 2 - self.level if sampling_method == 'skeleton': # Determine skeleton from filled tissue mask filled_tissue_mask = fillTissueMask(self.tissue_mask.copy()) filled_tissue_mask = filled_tissue_mask // 255 # needs to be an array of 0s and 1s skeleton = skeletonize(filled_tissue_mask, method='lee') self.skeleton = np.uint8(np.where(skeleton != 0, 255, 0)) skeleton = cv2.dilate(self.skeleton, None) contours, _ = cv2.findContours(skeleton, 0, cv2.CHAIN_APPROX_NONE) # Filter contours based on length arch_lens = [] valid_indices = [] radius = int(self.tile_size / (4**level_offset)) for idx, arch in enumerate(contours): c = cv2.arcLength(arch, False) c = c / 2 if c < radius / 4: continue valid_indices.append(idx) arch_lens.append(c) if not np.array(valid_indices).size == 0: contours = np.array(contours)[valid_indices] else: #if no main skeletons were found, it could be that the tissue slide is just very small arch_lens = [1 / len(contours)] * len(contours) # Extract points from the accepted contours weights = np.array(arch_lens) / np.sum(arch_lens) points_per_arch = distributeIntToChunks( num_tiles, weights) # <- number of points to be extracted for idx, arch in enumerate(contours): num_indices = points_per_arch[idx] output = np.zeros_like(skeleton) cv2.drawContours(output, [arch], -1, 1, 1) y_, x_ = np.where(output) # Simplify the shape by fitting circles arch = np.dstack([x_, y_]) cps = estimateWithCircles(arch, radius) cx, cy = cps[..., 0], cps[..., 1] # # Randomly select indices, in case too many; seed if needed if len(cx) > num_indices: # Seed if needed if not seed == None: np.random.seed(seed) indices = sorted( np.random.choice(len(cx), points_per_arch[idx], replace=False)) np.random.seed(None) # Return clock seed cx, cy = cx[indices], cy[indices] # Append to returnables if idx == 0: intermediate_coords = np.dstack([cx, cy]) else: intermediate_coords = np.hstack( [intermediate_coords, np.dstack([cx, cy])]) # To top-left-corner format final_coords = intermediate_coords.squeeze() * 4**level_offset if final_coords.shape == (2, ): final_coords = np.expand_dims(final_coords, 0) final_coords = final_coords - np.array( [self.tile_size // 2, self.tile_size // 2]) elif sampling_method == 'tissue_pct': self.top_left_corners = getTopLeftCorners(self.dims, self.tile_size) self.tissue_pcts = getTissuePercentages( self.tissue_mask, level_offset=level_offset, tile_size=self.tile_size, top_left_corners=self.top_left_corners) # Find indices tth_min, tth = tissue_th while len(np.where(self.tissue_pcts > tth)[0]) < num_tiles: if tth <= tth_min: break tth -= 0.05 # Indices indices = np.where(self.tissue_pcts > tth)[0] # Randomly select indices, in case too many; seed if needed if len(indices) > num_tiles: if not seed == None: np.random.seed(seed) indices = sorted( np.random.choice(indices, num_tiles, replace=False)) np.random.seed(None) # Return clock seed final_coords = self.top_left_corners[indices].copy() elif sampling_method == 'slic': # Determine SLIC clusters from filled tissue mask filled_tissue_mask = fillTissueMask(self.tissue_mask.copy()) filled_tissue_mask = filled_tissue_mask // 255 # needs to be an array of 0s and 1s segments = seg.slic(self.ds_img, compactness=10, seed_type='nplace', mask=filled_tissue_mask, n_segments=num_tiles, multichannel=True, recompute_seeds=True, enforce_connectivity=True) indices = [k for k in np.unique(segments) if not k == -1] # Randomly select indices, in case too many; seed if needed if len(indices) > num_tiles: if not seed == None: np.random.seed(seed) indices = sorted( np.random.choice(indices, num_tiles, replace=False)) np.random.seed(None) # Return clock seed for i in indices: contours, _ = cv2.findContours( np.uint8(np.where(segments == i, 255, 0)), 0, 1) contours = sorted(contours, key=lambda x: cv2.contourArea(x))[::-1] M = cv2.moments(contours[0]) cx = np.int32(M['m10'] / M['m00']) cy = np.int32(M['m01'] / M['m00']) if i == 0: intermediate_coords = np.dstack([cx, cy]) else: intermediate_coords = np.hstack( [intermediate_coords, np.dstack([cx, cy])]) # Append more cluster contours if num_tiles has not been reached if len(indices) < num_tiles: enough_tiles = False for i in indices: contours, _ = cv2.findContours( np.uint8(np.where(segments == i, 255, 0)), 0, 1) contours = sorted(contours, key=lambda x: cv2.contourArea(x))[::-1] for j, cnt in enumerate(contours): # accept a slic cluster contour if it's area is at least 5% of tile area if j != 0 and cv2.contourArea(cnt) > ( 0.05 * self.tile_size / (4**level_offset))**2: M = cv2.moments(cnt) cx = np.int32(M['m10'] / M['m00']) cy = np.int32(M['m01'] / M['m00']) intermediate_coords = np.hstack( [intermediate_coords, np.dstack([cx, cy])]) if intermediate_coords.shape[1] == 12: enough_tiles = True break if enough_tiles: break # To top-left-corner format final_coords = intermediate_coords.squeeze() * 4**level_offset final_coords = final_coords - np.array( [self.tile_size // 2, self.tile_size // 2]) # apply offset to coordinates final_coords = final_coords + np.array( [int(self.tile_size * offset[0]), int(self.tile_size * offset[1])]) self.tile_coords = final_coords.copy()
roi = roi[:, :, 3] > 0 # Alternatively a mask could be created manually with for example a disk: # roi = np.zeros((img.shape[0], img.shape[1])) # a, b = 150, 150 # r = 100 # y,x = np.ogrid[-a:img.shape[0]-a, -b:img.shape[1]-b] # mask = x*x + y*y <= r*r # roi[mask] = 1 # ~~~~~~~~~~~~ Example 1: maskSLIC ~~~~~~~~~~~~~ t1 = time.time() # Note that compactness is defined differently because a grid is not used. Lower compactness for maskSLIC is equivalent segments = seg.slic(img, compactness=10, seed_type='nplace', mask=roi, n_segments=12, recompute_seeds=True, plot_examples=True, enforce_connectivity=True) print("Time: {:.2f} s".format(time.time() - t1)) plt.figure() plt.title('maskSLIC') plt.imshow(mark_boundaries(img, segments)) plt.contour(roi, contours=1, colors='red', linewidths=1) plt.axis('off') # ~~~~~~~~~~~ Example 2: SLIC ~~~~~~~~~~~~~~~~~ t1 = time.time() segments = seg.slic(img, compactness=30, seed_type='grid', n_segments=80, plot_examples=False, enforce_connectivity=True) # segments[roi==0] = -1 print("Time: {:.2f} s".format(time.time() - t1))
import maskslic as seg from skimage.segmentation import mark_boundaries from skimage.io import imread import time img = imread('chelsea.png') roi = imread('chelsea_mask.png') # roi = img_as_float(chelsea_mask()) roi = roi[:, :, 3] > 0 # ~~~~~~~~~~~~ Example 1: maskSLIC ~~~~~~~~~~~~~ t1 = time.time() # Note that compactness is defined differently because a grid is not used. Lower compactness for maskSLIC is equivalent segments = seg.slic(img, compactness=10, seed_type='nplace', mask=roi, n_segments=12, recompute_seeds=True, plot_examples=True) print("Time: {:.2f} s".format(time.time() - t1)) plt.figure() plt.title('maskSLIC') plt.imshow(mark_boundaries(img, segments)) plt.contour(roi, contours=1, colors='red', linewidths=1) plt.axis('off') # ~~~~~~~~~~~ Example 2: SLIC ~~~~~~~~~~~~~~~~~ t1 = time.time() segments = seg.slic(img, compactness=30, seed_type='grid', n_segments=80, plot_examples=False) # segments[roi==0] = -1 print("Time: {:.2f} s".format(time.time() - t1))
# Extract the information about the spacing spacing_itk = t2w_mod.metadata_['spacing'] # Remember that this is in ITK format X, Y, Z and that we are in Y, X, Z spacing = (spacing_itk[1], spacing_itk[0], spacing_itk[2]) print spacing # Read the ground-truth gt_mod = GTModality() gt_mod.read_data_from_path(label_gt, path_gt) print gt_mod.data_[0].shape img = t2w_mod.data_[:, :, 32] img = (img - np.min(img)) * ((1.) / (np.max(img) - np.min(img))) roi = gt_mod.data_[0, :, :, 32].astype(bool) # Make SLIC over-segmentation segments = seg.slic(img, compactness=1, seed_type='nplace', multichannel=False, convert2lab=False, enforce_connectivity=True, mask=roi, n_segments=50, recompute_seeds=True, plot_examples=True)