
.. 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 <sphx_glr_download_auto_examples_applications_plot_thresholding_guide.py>`
        to download the full example code.

.. 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-43

.. code-block:: Python


    import matplotlib.pyplot as plt

    import skimage as ski

    img = ski.data.page()

    fig, ax = ski.filters.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 44-51

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 51-71

.. code-block:: Python



    image = ski.data.camera()
    thresh = ski.filters.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 72-78

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 78-104

.. code-block:: Python



    image = ski.data.camera()

    thresh_min = ski.filters.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 105-112

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 112-134

.. code-block:: Python



    image = ski.data.camera()
    thresh = ski.filters.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 135-149

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 149-178

.. code-block:: Python



    image = ski.data.page()

    global_thresh = ski.filters.threshold_otsu(image)
    binary_global = image > global_thresh

    block_size = 35
    local_thresh = ski.filters.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 179-186

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 186-220

.. code-block:: Python



    img = ski.util.img_as_ubyte(ski.data.page())

    radius = 15
    footprint = ski.morphology.disk(radius)

    local_otsu = ski.filters.rank.otsu(img, footprint)
    threshold_global_otsu = ski.filters.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(f'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 = 157)
   :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.076 seconds)


.. _sphx_glr_download_auto_examples_applications_plot_thresholding_guide.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: plot_thresholding_guide.ipynb <plot_thresholding_guide.ipynb>`

    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: plot_thresholding_guide.py <plot_thresholding_guide.py>`

    .. container:: sphx-glr-download sphx-glr-download-zip

      :download:`Download zipped: plot_thresholding_guide.zip <plot_thresholding_guide.zip>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_
