예제 #1
0
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))
예제 #2
0
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()
예제 #4
0
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))
예제 #5
0
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))
예제 #6
0
# 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)