.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/applications/plot_human_mitosis.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code or to run this example in your browser via Binder .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_applications_plot_human_mitosis.py: ================================ Segment human cells (in mitosis) ================================ In this example, we analyze a microscopy image of human cells. We use data provided by Jason Moffat [1]_ through `CellProfiler `_. .. [1] Moffat J, Grueneberg DA, Yang X, Kim SY, Kloepfer AM, Hinkle G, Piqani B, Eisenhaure TM, Luo B, Grenier JK, Carpenter AE, Foo SY, Stewart SA, Stockwell BR, Hacohen N, Hahn WC, Lander ES, Sabatini DM, Root DE (2006) "A lentiviral RNAi library for human and mouse genes applied to an arrayed viral high-content screen" Cell, 124(6):1283-98. PMID: 16564017 :DOI:`10.1016/j.cell.2006.01.040` .. GENERATED FROM PYTHON SOURCE LINES 19-33 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from scipy import ndimage as ndi import skimage as ski image = ski.data.human_mitosis() fig, ax = plt.subplots() ax.imshow(image, cmap='gray') ax.set_title('Microscopy image of human cells stained for nuclear DNA') plt.show() .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_human_mitosis_001.png :alt: Microscopy image of human cells stained for nuclear DNA :srcset: /auto_examples/applications/images/sphx_glr_plot_human_mitosis_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 34-38 We can see many cell nuclei on a dark background. Most of them are smooth and have an elliptical shape. However, we can distinguish some brighter spots corresponding to nuclei undergoing `mitosis `_ (cell division). .. GENERATED FROM PYTHON SOURCE LINES 40-41 Another way of visualizing a grayscale image is contour plotting: .. GENERATED FROM PYTHON SOURCE LINES 41-47 .. code-block:: Python fig, ax = plt.subplots(figsize=(5, 5)) qcs = ax.contour(image, origin='image') ax.set_title('Contour plot of the same raw image') plt.show() .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_human_mitosis_002.png :alt: Contour plot of the same raw image :srcset: /auto_examples/applications/images/sphx_glr_plot_human_mitosis_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 49-50 The contour lines are drawn at these levels: .. GENERATED FROM PYTHON SOURCE LINES 50-53 .. code-block:: Python qcs.levels .. rst-class:: sphx-glr-script-out .. code-block:: none array([ 0., 40., 80., 120., 160., 200., 240., 280.]) .. GENERATED FROM PYTHON SOURCE LINES 54-55 Each level has, respectively, the following number of segments: .. GENERATED FROM PYTHON SOURCE LINES 55-58 .. code-block:: Python [len(seg) for seg in qcs.allsegs] .. rst-class:: sphx-glr-script-out .. code-block:: none [1, 320, 270, 48, 19, 3, 1, 1] .. GENERATED FROM PYTHON SOURCE LINES 59-71 Estimate the mitotic index ========================== Cell biology uses the `mitotic index `_ to quantify cell division and, hence, cell proliferation. By definition, it is the ratio of cells in mitosis over the total number of cells. To analyze the above image, we are thus interested in two thresholds: one separating the nuclei from the background, the other separating the dividing nuclei (brighter spots) from the non-dividing nuclei. To separate these three different classes of pixels, we resort to :ref:`sphx_glr_auto_examples_segmentation_plot_multiotsu.py`. .. GENERATED FROM PYTHON SOURCE LINES 71-84 .. code-block:: Python thresholds = ski.filters.threshold_multiotsu(image, classes=3) regions = np.digitize(image, bins=thresholds) fig, ax = plt.subplots(ncols=2, figsize=(10, 5)) ax[0].imshow(image) ax[0].set_title('Original') ax[0].set_axis_off() ax[1].imshow(regions) ax[1].set_title('Multi-Otsu thresholding') ax[1].set_axis_off() plt.show() .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_human_mitosis_003.png :alt: Original, Multi-Otsu thresholding :srcset: /auto_examples/applications/images/sphx_glr_plot_human_mitosis_003.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 85-89 Since there are overlapping nuclei, thresholding is not enough to segment all the nuclei. If it were, we could readily compute a mitotic index for this sample: .. GENERATED FROM PYTHON SOURCE LINES 89-97 .. code-block:: Python cells = image > thresholds[0] dividing = image > thresholds[1] labeled_cells = ski.measure.label(cells) labeled_dividing = ski.measure.label(dividing) naive_mi = labeled_dividing.max() / labeled_cells.max() print(naive_mi) .. rst-class:: sphx-glr-script-out .. code-block:: none 0.7847222222222222 .. GENERATED FROM PYTHON SOURCE LINES 98-99 Whoa, this can't be! The number of dividing nuclei .. GENERATED FROM PYTHON SOURCE LINES 99-102 .. code-block:: Python print(labeled_dividing.max()) .. rst-class:: sphx-glr-script-out .. code-block:: none 226 .. GENERATED FROM PYTHON SOURCE LINES 103-104 is overestimated, while the total number of cells .. GENERATED FROM PYTHON SOURCE LINES 104-107 .. code-block:: Python print(labeled_cells.max()) .. rst-class:: sphx-glr-script-out .. code-block:: none 288 .. GENERATED FROM PYTHON SOURCE LINES 108-109 is underestimated. .. GENERATED FROM PYTHON SOURCE LINES 109-122 .. code-block:: Python fig, ax = plt.subplots(ncols=3, figsize=(15, 5)) ax[0].imshow(image) ax[0].set_title('Original') ax[0].set_axis_off() ax[1].imshow(dividing) ax[1].set_title('Dividing nuclei?') ax[1].set_axis_off() ax[2].imshow(cells) ax[2].set_title('All nuclei?') ax[2].set_axis_off() plt.show() .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_human_mitosis_004.png :alt: Original, Dividing nuclei?, All nuclei? :srcset: /auto_examples/applications/images/sphx_glr_plot_human_mitosis_004.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 123-134 Count dividing nuclei ===================== Clearly, not all connected regions in the middle plot are dividing nuclei. On one hand, the second threshold (value of ``thresholds[1]``) appears to be too low to separate those very bright areas corresponding to dividing nuclei from relatively bright pixels otherwise present in many nuclei. On the other hand, we want a smoother image, removing small spurious objects and, possibly, merging clusters of neighboring objects (some could correspond to two nuclei emerging from one cell division). In a way, the segmentation challenge we are facing with dividing nuclei is the opposite of that with (touching) cells. .. GENERATED FROM PYTHON SOURCE LINES 136-138 To find suitable values for thresholds and filtering parameters, we proceed by dichotomy, visually and manually. .. GENERATED FROM PYTHON SOURCE LINES 138-154 .. code-block:: Python higher_threshold = 125 dividing = image > higher_threshold smoother_dividing = ski.filters.rank.mean( ski.util.img_as_ubyte(dividing), ski.morphology.disk(4) ) binary_smoother_dividing = smoother_dividing > 20 fig, ax = plt.subplots(figsize=(5, 5)) ax.imshow(binary_smoother_dividing) ax.set_title('Dividing nuclei') ax.set_axis_off() plt.show() .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_human_mitosis_005.png :alt: Dividing nuclei :srcset: /auto_examples/applications/images/sphx_glr_plot_human_mitosis_005.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 155-156 We are left with .. GENERATED FROM PYTHON SOURCE LINES 156-159 .. code-block:: Python cleaned_dividing = ski.measure.label(binary_smoother_dividing) print(cleaned_dividing.max()) .. rst-class:: sphx-glr-script-out .. code-block:: none 29 .. GENERATED FROM PYTHON SOURCE LINES 160-161 dividing nuclei in this sample. .. GENERATED FROM PYTHON SOURCE LINES 163-174 Segment nuclei ============== To separate overlapping nuclei, we resort to :ref:`sphx_glr_auto_examples_segmentation_plot_watershed.py`. The idea of the algorithm is to find watershed basins as if flooded from a set of `markers`. We generate these markers as the local maxima of the distance function to the background. Given the typical size of the nuclei, we pass ``min_distance=7`` so that local maxima and, hence, markers will lie at least 7 pixels away from one another. We also use ``exclude_border=False`` so that all nuclei touching the image border will be included. .. GENERATED FROM PYTHON SOURCE LINES 174-186 .. code-block:: Python distance = ndi.distance_transform_edt(cells) local_max_coords = ski.feature.peak_local_max( distance, min_distance=7, exclude_border=False ) local_max_mask = np.zeros(distance.shape, dtype=bool) local_max_mask[tuple(local_max_coords.T)] = True markers = ski.measure.label(local_max_mask) segmented_cells = ski.segmentation.watershed(-distance, markers, mask=cells) .. GENERATED FROM PYTHON SOURCE LINES 187-190 To visualize the segmentation conveniently, we colour-code the labelled regions using the `color.label2rgb` function, specifying the background label with argument `bg_label=0`. .. GENERATED FROM PYTHON SOURCE LINES 190-200 .. code-block:: Python fig, ax = plt.subplots(ncols=2, figsize=(10, 5)) ax[0].imshow(cells, cmap='gray') ax[0].set_title('Overlapping nuclei') ax[0].set_axis_off() ax[1].imshow(ski.color.label2rgb(segmented_cells, bg_label=0)) ax[1].set_title('Segmented nuclei') ax[1].set_axis_off() plt.show() .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_human_mitosis_006.png :alt: Overlapping nuclei, Segmented nuclei :srcset: /auto_examples/applications/images/sphx_glr_plot_human_mitosis_006.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 201-202 Make sure that the watershed algorithm has led to identifying more nuclei: .. GENERATED FROM PYTHON SOURCE LINES 202-205 .. code-block:: Python assert segmented_cells.max() > labeled_cells.max() .. GENERATED FROM PYTHON SOURCE LINES 206-207 Finally, we find a total number of .. GENERATED FROM PYTHON SOURCE LINES 207-210 .. code-block:: Python print(segmented_cells.max()) .. rst-class:: sphx-glr-script-out .. code-block:: none 317 .. GENERATED FROM PYTHON SOURCE LINES 211-212 cells in this sample. Therefore, we estimate the mitotic index to be: .. GENERATED FROM PYTHON SOURCE LINES 212-214 .. code-block:: Python print(cleaned_dividing.max() / segmented_cells.max()) .. rst-class:: sphx-glr-script-out .. code-block:: none 0.0914826498422713 .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 2.180 seconds) .. _sphx_glr_download_auto_examples_applications_plot_human_mitosis.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: binder-badge .. image:: images/binder_badge_logo.svg :target: https://mybinder.org/v2/gh/scikit-image/scikit-image/v0.23.1?filepath=notebooks/auto_examples/applications/plot_human_mitosis.ipynb :alt: Launch binder :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_human_mitosis.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_human_mitosis.py ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_