|
21 | 21 | import numpy as np |
22 | 22 | from scipy import ndimage as ndi |
23 | 23 |
|
24 | | -from skimage import color, feature, filters, measure, morphology, segmentation, util |
25 | | -from skimage.data import human_mitosis |
| 24 | +import skimage as ski |
26 | 25 |
|
27 | | -image = human_mitosis() |
| 26 | +image = ski.data.human_mitosis() |
28 | 27 |
|
29 | 28 | fig, ax = plt.subplots() |
30 | 29 | ax.imshow(image, cmap='gray') |
|
70 | 69 | # To separate these three different classes of pixels, we |
71 | 70 | # resort to :ref:`sphx_glr_auto_examples_segmentation_plot_multiotsu.py`. |
72 | 71 |
|
73 | | -thresholds = filters.threshold_multiotsu(image, classes=3) |
| 72 | +thresholds = ski.filters.threshold_multiotsu(image, classes=3) |
74 | 73 | regions = np.digitize(image, bins=thresholds) |
75 | 74 |
|
76 | 75 | fig, ax = plt.subplots(ncols=2, figsize=(10, 5)) |
|
90 | 89 |
|
91 | 90 | cells = image > thresholds[0] |
92 | 91 | dividing = image > thresholds[1] |
93 | | -labeled_cells = measure.label(cells) |
94 | | -labeled_dividing = measure.label(dividing) |
| 92 | +labeled_cells = ski.measure.label(cells) |
| 93 | +labeled_dividing = ski.measure.label(dividing) |
95 | 94 | naive_mi = labeled_dividing.max() / labeled_cells.max() |
96 | 95 | print(naive_mi) |
97 | 96 |
|
|
112 | 111 | ax[0].imshow(image) |
113 | 112 | ax[0].set_title('Original') |
114 | 113 | ax[0].set_axis_off() |
115 | | -ax[2].imshow(cells) |
116 | | -ax[2].set_title('All nuclei?') |
117 | | -ax[2].set_axis_off() |
118 | 114 | ax[1].imshow(dividing) |
119 | 115 | ax[1].set_title('Dividing nuclei?') |
120 | 116 | ax[1].set_axis_off() |
| 117 | +ax[2].imshow(cells) |
| 118 | +ax[2].set_title('All nuclei?') |
| 119 | +ax[2].set_axis_off() |
121 | 120 | plt.show() |
122 | 121 |
|
123 | 122 | ##################################################################### |
|
140 | 139 | higher_threshold = 125 |
141 | 140 | dividing = image > higher_threshold |
142 | 141 |
|
143 | | -smoother_dividing = filters.rank.mean(util.img_as_ubyte(dividing), morphology.disk(4)) |
| 142 | +smoother_dividing = ski.filters.rank.mean( |
| 143 | + ski.util.img_as_ubyte(dividing), ski.morphology.disk(4) |
| 144 | +) |
144 | 145 |
|
145 | 146 | binary_smoother_dividing = smoother_dividing > 20 |
146 | 147 |
|
|
152 | 153 |
|
153 | 154 | ##################################################################### |
154 | 155 | # We are left with |
155 | | -cleaned_dividing = measure.label(binary_smoother_dividing) |
| 156 | +cleaned_dividing = ski.measure.label(binary_smoother_dividing) |
156 | 157 | print(cleaned_dividing.max()) |
157 | 158 |
|
158 | 159 | ##################################################################### |
|
163 | 164 | # ============== |
164 | 165 | # To separate overlapping nuclei, we resort to |
165 | 166 | # :ref:`sphx_glr_auto_examples_segmentation_plot_watershed.py`. |
166 | | -# To visualize the segmentation conveniently, we colour-code the labelled |
167 | | -# regions using the `color.label2rgb` function, specifying the background |
168 | | -# label with argument `bg_label=0`. |
| 167 | +# The idea of the algorithm is to find watershed basins as if flooded from |
| 168 | +# a set of `markers`. We generate these markers as the local maxima of the |
| 169 | +# distance function to the background. Given the typical size of the nuclei, |
| 170 | +# we pass ``min_distance=7`` so that local maxima and, hence, markers will lie |
| 171 | +# at least 7 pixels away from one another. |
| 172 | +# We also use ``exclude_border=False`` so that all nuclei touching the image |
| 173 | +# border will be included. |
169 | 174 |
|
170 | 175 | distance = ndi.distance_transform_edt(cells) |
171 | 176 |
|
172 | | -local_max_coords = feature.peak_local_max(distance, min_distance=7) |
| 177 | +local_max_coords = ski.feature.peak_local_max( |
| 178 | + distance, min_distance=7, exclude_border=False |
| 179 | +) |
173 | 180 | local_max_mask = np.zeros(distance.shape, dtype=bool) |
174 | 181 | local_max_mask[tuple(local_max_coords.T)] = True |
175 | | -markers = measure.label(local_max_mask) |
| 182 | +markers = ski.measure.label(local_max_mask) |
176 | 183 |
|
177 | | -segmented_cells = segmentation.watershed(-distance, markers, mask=cells) |
| 184 | +segmented_cells = ski.segmentation.watershed(-distance, markers, mask=cells) |
| 185 | + |
| 186 | +##################################################################### |
| 187 | +# To visualize the segmentation conveniently, we colour-code the labelled |
| 188 | +# regions using the `color.label2rgb` function, specifying the background |
| 189 | +# label with argument `bg_label=0`. |
178 | 190 |
|
179 | 191 | fig, ax = plt.subplots(ncols=2, figsize=(10, 5)) |
180 | 192 | ax[0].imshow(cells, cmap='gray') |
181 | 193 | ax[0].set_title('Overlapping nuclei') |
182 | 194 | ax[0].set_axis_off() |
183 | | -ax[1].imshow(color.label2rgb(segmented_cells, bg_label=0)) |
| 195 | +ax[1].imshow(ski.color.label2rgb(segmented_cells, bg_label=0)) |
184 | 196 | ax[1].set_title('Segmented nuclei') |
185 | 197 | ax[1].set_axis_off() |
186 | 198 | plt.show() |
187 | 199 |
|
188 | 200 | ##################################################################### |
189 | | -# Additionally, we may use function `color.label2rgb` to overlay the original |
190 | | -# image with the segmentation result, using transparency (alpha parameter). |
191 | | - |
192 | | -color_labels = color.label2rgb(segmented_cells, image, alpha=0.4, bg_label=0) |
| 201 | +# Make sure that the watershed algorithm has led to identifying more nuclei: |
193 | 202 |
|
194 | | -fig, ax = plt.subplots(figsize=(5, 5)) |
195 | | -ax.imshow(color_labels) |
196 | | -ax.set_title('Segmentation result over raw image') |
197 | | -plt.show() |
| 203 | +assert segmented_cells.max() > labeled_cells.max() |
198 | 204 |
|
199 | 205 | ##################################################################### |
200 | 206 | # Finally, we find a total number of |
|
0 commit comments