
.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "auto_examples/applications/plot_pixel_graphs.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        Click :ref:`here <sphx_glr_download_auto_examples_applications_plot_pixel_graphs.py>`
        to download the full example code

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

.. _sphx_glr_auto_examples_applications_plot_pixel_graphs.py:


====================================================
Use pixel graphs to find an object's geodesic center
====================================================

In various image analysis situations, it is useful to think of the pixels of an
image, or of a region of an image, as a network or graph, in which each pixel
is connected to its neighbors (with or without diagonals). One such situation
is finding the *geodesic center* of an object, which is the point closest to
all other points *if you are only allowed to travel on the pixels of the
object*, rather than in a straight line. This point is the one with maximal
*closeness centrality* [1]_ in the network.

In this example, we create such a *pixel graph* of a skeleton and find
the central pixel of that skeleton. This demonstrates its utility in contrast
with the centroid (also known as the center of mass) which may actually fall
outside the object.

References
----------
.. [1] Linton C. Freeman: Centrality in networks: I.
       Conceptual clarification. Social Networks 1:215-239, 1979.
       :DOI:`10.1016/0378-8733(78)90021-7`

.. GENERATED FROM PYTHON SOURCE LINES 25-30

.. code-block:: default

    import matplotlib.pyplot as plt
    import numpy as np
    from scipy import ndimage as ndi
    from skimage import color, data, filters, graph, measure, morphology








.. GENERATED FROM PYTHON SOURCE LINES 31-32

We start by loading the data: an image of a human retina.

.. GENERATED FROM PYTHON SOURCE LINES 32-40

.. code-block:: default


    retina_source = data.retina()

    _, ax = plt.subplots()
    ax.imshow(retina_source)
    ax.set_axis_off()
    _ = ax.set_title('Human retina')




.. image-sg:: /auto_examples/applications/images/sphx_glr_plot_pixel_graphs_001.png
   :alt: Human retina
   :srcset: /auto_examples/applications/images/sphx_glr_plot_pixel_graphs_001.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 41-44

We convert the image to grayscale, then use the
`Sato vesselness filter <skimage.filters.sato>` to better distinguish the
main vessels in the image.

.. GENERATED FROM PYTHON SOURCE LINES 44-58

.. code-block:: default


    retina = color.rgb2gray(retina_source)
    t0, t1 = filters.threshold_multiotsu(retina, classes=3)
    mask = (retina > t0)
    vessels = filters.sato(retina, sigmas=range(1, 10)) * mask

    _, axes = plt.subplots(nrows=1, ncols=2)
    axes[0].imshow(retina, cmap='gray')
    axes[0].set_axis_off()
    axes[0].set_title('grayscale')
    axes[1].imshow(vessels, cmap='magma')
    axes[1].set_axis_off()
    _ = axes[1].set_title('Sato vesselness')




.. image-sg:: /auto_examples/applications/images/sphx_glr_plot_pixel_graphs_002.png
   :alt: grayscale, Sato vesselness
   :srcset: /auto_examples/applications/images/sphx_glr_plot_pixel_graphs_002.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 59-62

Based on the observed vesselness values, we use
`hysteresis thresholding <skimage.filters.apply_hysteresis_threshold>` to
define the main vessels.

.. GENERATED FROM PYTHON SOURCE LINES 62-71

.. code-block:: default


    thresholded = filters.apply_hysteresis_threshold(vessels, 0.01, 0.03)
    labeled = ndi.label(thresholded)[0]

    _, ax = plt.subplots()
    ax.imshow(color.label2rgb(labeled, retina))
    ax.set_axis_off()
    _ = ax.set_title('thresholded vesselness')




.. image-sg:: /auto_examples/applications/images/sphx_glr_plot_pixel_graphs_003.png
   :alt: thresholded vesselness
   :srcset: /auto_examples/applications/images/sphx_glr_plot_pixel_graphs_003.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 72-76

Finally, we can `skeletonize <skimage.morphology.skeletonize>` this label
image and use that as the basis to find the
`central pixel <skimage.graph.central_pixel>` in that skeleton. Compare that
to the position of the centroid!

.. GENERATED FROM PYTHON SOURCE LINES 76-96

.. code-block:: default


    largest_nonzero_label = np.argmax(np.bincount(labeled[labeled > 0]))
    binary = labeled == largest_nonzero_label
    skeleton = morphology.skeletonize(binary)
    g, nodes = graph.pixel_graph(skeleton, connectivity=2)
    px, distances = graph.central_pixel(
            g, nodes=nodes, shape=skeleton.shape, partition_size=100
            )

    centroid = measure.centroid(labeled > 0)

    _, ax = plt.subplots()
    ax.imshow(color.label2rgb(skeleton, retina))
    ax.scatter(px[1], px[0], label='graph center')
    ax.scatter(centroid[1], centroid[0], label='centroid')
    ax.legend()
    ax.set_axis_off()
    ax.set_title('vessel graph center vs centroid')

    plt.show()



.. image-sg:: /auto_examples/applications/images/sphx_glr_plot_pixel_graphs_004.png
   :alt: vessel graph center vs centroid
   :srcset: /auto_examples/applications/images/sphx_glr_plot_pixel_graphs_004.png
   :class: sphx-glr-single-img






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

   **Total running time of the script:** ( 1 minutes  17.037 seconds)


.. _sphx_glr_download_auto_examples_applications_plot_pixel_graphs.py:


.. only :: html

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



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

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



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

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


.. only:: html

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

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