.. 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 ` 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_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.binary_opening(mask_postprocessed, np.ones((3, 3))) # Fill small holes with binary closing mask_postprocessed = morphology.binary_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 9.816 seconds) .. _sphx_glr_download_auto_examples_segmentation_plot_floodfill.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/segmentation/plot_floodfill.ipynb :alt: Launch binder :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_floodfill.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_floodfill.py ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_