
.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "auto_examples/segmentation/plot_floodfill.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_segmentation_plot_floodfill.py>`
        to download the full example code.

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_auto_examples_segmentation_plot_floodfill.py:


==========
Flood Fill
==========

Flood fill is an algorithm to identify and/or change adjacent values in an
image based on their similarity to an initial seed point [1]_. The conceptual
analogy is the 'paint bucket' tool in many graphic editors.

.. [1] https://en.wikipedia.org/wiki/Flood_fill

Basic example
-------------

First, a basic example where we will change a checkerboard square from white
to mid-gray.

.. GENERATED FROM PYTHON SOURCE LINES 18-42

.. code-block:: Python


    import numpy as np
    import matplotlib.pyplot as plt
    from skimage import data, filters, color, morphology
    from skimage.segmentation import flood, flood_fill


    checkers = data.checkerboard()

    # Fill a square near the middle with value 127, starting at index (76, 76)
    filled_checkers = flood_fill(checkers, (76, 76), 127)

    fig, ax = plt.subplots(ncols=2, figsize=(10, 5))

    ax[0].imshow(checkers, cmap=plt.cm.gray)
    ax[0].set_title('Original')

    ax[1].imshow(filled_checkers, cmap=plt.cm.gray)
    ax[1].plot(76, 76, 'wo')  # seed point
    ax[1].set_title('After flood fill')

    plt.show()





.. image-sg:: /auto_examples/segmentation/images/sphx_glr_plot_floodfill_001.png
   :alt: Original, After flood fill
   :srcset: /auto_examples/segmentation/images/sphx_glr_plot_floodfill_001.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 43-53

Advanced example
----------------

Because standard flood filling requires the neighbors to be strictly equal,
its use is limited on real-world images with color gradients and noise.
The `tolerance` keyword argument widens the permitted range about the initial
value, allowing use on real-world images.

Here we will experiment a bit on the cameraman.  First, turning his coat from
dark to light.

.. GENERATED FROM PYTHON SOURCE LINES 53-73

.. code-block:: Python


    cameraman = data.camera()

    # Change the cameraman's coat from dark to light (255).  The seed point is
    # chosen as (155, 150)
    light_coat = flood_fill(cameraman, (155, 150), 255, tolerance=10)
    fig, ax = plt.subplots(ncols=2, figsize=(10, 5))

    ax[0].imshow(cameraman, cmap=plt.cm.gray)
    ax[0].set_title('Original')
    ax[0].axis('off')

    ax[1].imshow(light_coat, cmap=plt.cm.gray)
    ax[1].plot(150, 155, 'ro')  # seed point
    ax[1].set_title('After flood fill')
    ax[1].axis('off')

    plt.show()





.. image-sg:: /auto_examples/segmentation/images/sphx_glr_plot_floodfill_002.png
   :alt: Original, After flood fill
   :srcset: /auto_examples/segmentation/images/sphx_glr_plot_floodfill_002.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 74-83

The cameraman's  coat is in varying shades of gray. Only the parts of the coat
matching the shade near the seed value is changed.

Experimentation with tolerance
------------------------------

To get a better intuitive understanding of how the tolerance parameter
works, here is a set of images progressively increasing the parameter with
seed point in the upper left corner.

.. GENERATED FROM PYTHON SOURCE LINES 83-109

.. code-block:: Python



    output = []

    for i in range(8):
        tol = 5 + 20 * i
        output.append(flood_fill(cameraman, (0, 0), 255, tolerance=tol))

    # Initialize plot and place original image
    fig, ax = plt.subplots(nrows=3, ncols=3, figsize=(12, 12))
    ax[0, 0].imshow(cameraman, cmap=plt.cm.gray)
    ax[0, 0].set_title('Original')
    ax[0, 0].axis('off')

    # Plot all eight different tolerances for comparison.
    for i in range(8):
        m, n = np.unravel_index(i + 1, (3, 3))
        ax[m, n].imshow(output[i], cmap=plt.cm.gray)
        ax[m, n].set_title(f'Tolerance {5 + 20 * i}')
        ax[m, n].axis('off')
        ax[m, n].plot(0, 0, 'bo')  # seed point

    fig.tight_layout()
    plt.show()





.. image-sg:: /auto_examples/segmentation/images/sphx_glr_plot_floodfill_003.png
   :alt: Original, Tolerance 5, Tolerance 25, Tolerance 45, Tolerance 65, Tolerance 85, Tolerance 105, Tolerance 125, Tolerance 145
   :srcset: /auto_examples/segmentation/images/sphx_glr_plot_floodfill_003.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 110-120

Flood as mask
-------------

A sister function, `flood`, is available which returns a mask identifying
the flood rather than modifying the image itself.  This is useful for
segmentation purposes and more advanced analysis pipelines.

Here we segment the nose of a cat.  However, multi-channel images are not
supported by flood[_fill].  Instead we Sobel filter the red channel to
enhance edges, then flood the nose with a tolerance.

.. GENERATED FROM PYTHON SOURCE LINES 120-144

.. code-block:: Python


    cat = data.chelsea()
    cat_sobel = filters.sobel(cat[..., 0])
    cat_nose = flood(cat_sobel, (240, 265), tolerance=0.03)

    fig, ax = plt.subplots(nrows=3, figsize=(10, 20))

    ax[0].imshow(cat)
    ax[0].set_title('Original')
    ax[0].axis('off')

    ax[1].imshow(cat_sobel)
    ax[1].set_title('Sobel filtered')
    ax[1].axis('off')

    ax[2].imshow(cat)
    ax[2].imshow(cat_nose, cmap=plt.cm.gray, alpha=0.3)
    ax[2].plot(265, 240, 'wo')  # seed point
    ax[2].set_title('Nose segmented with `flood`')
    ax[2].axis('off')

    fig.tight_layout()
    plt.show()




.. image-sg:: /auto_examples/segmentation/images/sphx_glr_plot_floodfill_004.png
   :alt: Original, Sobel filtered, Nose segmented with `flood`
   :srcset: /auto_examples/segmentation/images/sphx_glr_plot_floodfill_004.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 145-155

Flood-fill in HSV space and mask post-processing
------------------------------------------------

Since flood fill operates on single-channel images, we transform here the
image to the HSV (Hue Saturation Value) space in order to flood pixels of
similar hue.

In this example we also show that it is possible to post-process the binary
mask returned by :func:`skimage.segmentation.flood` thanks to the functions
of :mod:`skimage.morphology`.

.. GENERATED FROM PYTHON SOURCE LINES 155-184

.. code-block:: Python



    img = data.astronaut()
    img_hsv = color.rgb2hsv(img)
    img_hsv_copy = np.copy(img_hsv)

    # flood function returns a mask of flooded pixels
    mask = flood(img_hsv[..., 0], (313, 160), tolerance=0.016)
    # Set pixels of mask to new value for hue channel
    img_hsv[mask, 0] = 0.5
    # Post-processing in order to improve the result
    # Remove white pixels from flag, using saturation channel
    mask_postprocessed = np.logical_and(mask, img_hsv_copy[..., 1] > 0.4)
    # Remove thin structures with binary opening
    mask_postprocessed = morphology.opening(mask_postprocessed, np.ones((3, 3)))
    # Fill small holes with binary closing
    mask_postprocessed = morphology.closing(mask_postprocessed, morphology.disk(20))
    img_hsv_copy[mask_postprocessed, 0] = 0.5

    fig, ax = plt.subplots(1, 2, figsize=(8, 4))
    ax[0].imshow(color.hsv2rgb(img_hsv))
    ax[0].axis('off')
    ax[0].set_title('After flood fill')
    ax[1].imshow(color.hsv2rgb(img_hsv_copy))
    ax[1].axis('off')
    ax[1].set_title('After flood fill and post-processing')

    fig.tight_layout()
    plt.show()



.. image-sg:: /auto_examples/segmentation/images/sphx_glr_plot_floodfill_005.png
   :alt: After flood fill, After flood fill and post-processing
   :srcset: /auto_examples/segmentation/images/sphx_glr_plot_floodfill_005.png
   :class: sphx-glr-single-img






.. rst-class:: sphx-glr-timing

   **Total running time of the script:** (0 minutes 11.573 seconds)


.. _sphx_glr_download_auto_examples_segmentation_plot_floodfill.py:

.. only:: html

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

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

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

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

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

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

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


.. only:: html

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

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