.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/applications/plot_thresholding_guide.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_thresholding_guide.py: ============ Thresholding ============ Thresholding is used to create a binary image from a grayscale image [1]_. It is the simplest way to segment objects from a background. Thresholding algorithms implemented in scikit-image can be separated in two categories: - Histogram-based. The histogram of the pixels' intensity is used and certain assumptions are made on the properties of this histogram (e.g. bimodal). - Local. To process a pixel, only the neighboring pixels are used. These algorithms often require more computation time. If you are not familiar with the details of the different algorithms and the underlying assumptions, it is often difficult to know which algorithm will give the best results. Therefore, Scikit-image includes a function to evaluate thresholding algorithms provided by the library. At a glance, you can select the best algorithm for you data without a deep understanding of their mechanisms. .. [1] https://en.wikipedia.org/wiki/Thresholding_%28image_processing%29 .. seealso:: Presentation on :ref:`sphx_glr_auto_examples_applications_plot_rank_filters.py`. .. GENERATED FROM PYTHON SOURCE LINES 31-44 .. code-block:: Python import matplotlib.pyplot as plt from skimage import data from skimage.filters import try_all_threshold img = data.page() fig, ax = try_all_threshold(img, figsize=(10, 8), verbose=False) plt.show() .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_thresholding_guide_001.png :alt: Original, Isodata, Li, Mean, Minimum, Otsu, Triangle, Yen :srcset: /auto_examples/applications/images/sphx_glr_plot_thresholding_guide_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 45-52 How to apply a threshold? ========================= Now, we illustrate how to apply one of these thresholding algorithms. This example uses the mean value of pixel intensities. It is a simple and naive threshold value, which is sometimes used as a guess value. .. GENERATED FROM PYTHON SOURCE LINES 52-74 .. code-block:: Python from skimage.filters import threshold_mean image = data.camera() thresh = threshold_mean(image) binary = image > thresh fig, axes = plt.subplots(ncols=2, figsize=(8, 3)) ax = axes.ravel() ax[0].imshow(image, cmap=plt.cm.gray) ax[0].set_title('Original image') ax[1].imshow(binary, cmap=plt.cm.gray) ax[1].set_title('Result') for a in ax: a.set_axis_off() plt.show() .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_thresholding_guide_002.png :alt: Original image, Result :srcset: /auto_examples/applications/images/sphx_glr_plot_thresholding_guide_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 75-81 Bimodal histogram ================= For pictures with a bimodal histogram, more specific algorithms can be used. For instance, the minimum algorithm takes a histogram of the image and smooths it repeatedly until there are only two peaks in the histogram. .. GENERATED FROM PYTHON SOURCE LINES 81-109 .. code-block:: Python from skimage.filters import threshold_minimum image = data.camera() thresh_min = threshold_minimum(image) binary_min = image > thresh_min fig, ax = plt.subplots(2, 2, figsize=(10, 10)) ax[0, 0].imshow(image, cmap=plt.cm.gray) ax[0, 0].set_title('Original') ax[0, 1].hist(image.ravel(), bins=256) ax[0, 1].set_title('Histogram') ax[1, 0].imshow(binary_min, cmap=plt.cm.gray) ax[1, 0].set_title('Thresholded (min)') ax[1, 1].hist(image.ravel(), bins=256) ax[1, 1].axvline(thresh_min, color='r') for a in ax[:, 0]: a.set_axis_off() plt.show() .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_thresholding_guide_003.png :alt: Original, Histogram, Thresholded (min) :srcset: /auto_examples/applications/images/sphx_glr_plot_thresholding_guide_003.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 110-117 Otsu's method [2]_ calculates an "optimal" threshold (marked by a red line in the histogram below) by maximizing the variance between two classes of pixels, which are separated by the threshold. Equivalently, this threshold minimizes the intra-class variance. .. [2] https://en.wikipedia.org/wiki/Otsu's_method .. GENERATED FROM PYTHON SOURCE LINES 117-140 .. code-block:: Python from skimage.filters import threshold_otsu image = data.camera() thresh = threshold_otsu(image) binary = image > thresh fig, ax = plt.subplots(ncols=3, figsize=(8, 2.5)) ax[0].imshow(image, cmap=plt.cm.gray) ax[0].set_title('Original') ax[0].axis('off') ax[1].hist(image.ravel(), bins=256) ax[1].set_title('Histogram') ax[1].axvline(thresh, color='r') ax[2].imshow(binary, cmap=plt.cm.gray) ax[2].set_title('Thresholded') ax[2].set_axis_off() plt.show() .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_thresholding_guide_004.png :alt: Original, Histogram, Thresholded :srcset: /auto_examples/applications/images/sphx_glr_plot_thresholding_guide_004.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 141-155 Local thresholding ================== If the image background is relatively uniform, then you can use a global threshold value as presented above. However, if there is large variation in the background intensity, adaptive thresholding (a.k.a. local or dynamic thresholding) may produce better results. Note that local is much slower than global thresholding. Here, we binarize an image using the `threshold_local` function, which calculates thresholds in regions with a characteristic size `block_size` surrounding each pixel (i.e. local neighborhoods). Each threshold value is the weighted mean of the local neighborhood minus an offset value. .. GENERATED FROM PYTHON SOURCE LINES 155-186 .. code-block:: Python from skimage.filters import threshold_otsu, threshold_local image = data.page() global_thresh = threshold_otsu(image) binary_global = image > global_thresh block_size = 35 local_thresh = threshold_local(image, block_size, offset=10) binary_local = image > local_thresh fig, axes = plt.subplots(nrows=3, figsize=(7, 8)) ax = axes.ravel() plt.gray() ax[0].imshow(image) ax[0].set_title('Original') ax[1].imshow(binary_global) ax[1].set_title('Global thresholding') ax[2].imshow(binary_local) ax[2].set_title('Local thresholding') for a in ax: a.set_axis_off() plt.show() .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_thresholding_guide_005.png :alt: Original, Global thresholding, Local thresholding :srcset: /auto_examples/applications/images/sphx_glr_plot_thresholding_guide_005.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 187-194 Now, we show how Otsu's threshold [2]_ method can be applied locally. For each pixel, an "optimal" threshold is determined by maximizing the variance between two classes of pixels of the local neighborhood defined by a structuring element. The example compares the local threshold with the global threshold. .. GENERATED FROM PYTHON SOURCE LINES 194-232 .. code-block:: Python from skimage.morphology import disk from skimage.filters import threshold_otsu, rank from skimage.util import img_as_ubyte img = img_as_ubyte(data.page()) radius = 15 footprint = disk(radius) local_otsu = rank.otsu(img, footprint) threshold_global_otsu = threshold_otsu(img) global_otsu = img >= threshold_global_otsu fig, axes = plt.subplots(2, 2, figsize=(8, 5), sharex=True, sharey=True) ax = axes.ravel() fig.tight_layout() fig.colorbar(ax[0].imshow(img, cmap=plt.cm.gray), ax=ax[0], orientation='horizontal') ax[0].set_title('Original') ax[0].set_axis_off() fig.colorbar( ax[1].imshow(local_otsu, cmap=plt.cm.gray), ax=ax[1], orientation='horizontal' ) ax[1].set_title(f'Local Otsu (radius={radius})') ax[1].set_axis_off() ax[2].imshow(img >= local_otsu, cmap=plt.cm.gray) ax[2].set_title('Original >= Local Otsu') ax[2].set_axis_off() ax[3].imshow(global_otsu, cmap=plt.cm.gray) ax[3].set_title('Global Otsu (threshold = {threshold_global_otsu})') ax[3].set_axis_off() plt.show() .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_thresholding_guide_006.png :alt: Original, Local Otsu (radius=15), Original >= Local Otsu, Global Otsu (threshold = {threshold_global_otsu}) :srcset: /auto_examples/applications/images/sphx_glr_plot_thresholding_guide_006.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 3.034 seconds) .. _sphx_glr_download_auto_examples_applications_plot_thresholding_guide.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.2?filepath=notebooks/auto_examples/applications/plot_thresholding_guide.ipynb :alt: Launch binder :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_thresholding_guide.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_thresholding_guide.py ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_