.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples\04_thresholding.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. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_04_thresholding.py: ============ Thresholding ============ Typically, in the histogram of most fluorescence images, the peak appears at the lower end of the distribution. This is because the image usually consists mostly of background with values close to zero, while the signal we are interested in, which has higher values, is more sparse, resulting in fewer counts. This can also be observed in our example image, *blobs.jpeg*. .. GENERATED FROM PYTHON SOURCE LINES 14-44 .. code-block:: Python from PIL import Image import numpy as np import matplotlib.pyplot as plt blobs = Image.open("images/blobs.jpeg") blobs = np.array(blobs) plt.figure(figsize=(8,3.8)) plt.subplot(121) plt.title('Image') plt.imshow(blobs, cmap='gray') plt.subplot(122) plt.title('Histogram') plt.hist(blobs.flatten()) plt.xlabel('pixel value') plt.ylabel('count') plt.annotate('background', xy=(10, 3000), xytext=(50, 5000), arrowprops=dict(facecolor='black', shrink=0.001, width=1)) plt.annotate('signal', xy=(245, 1000), xytext=(200, 2000), arrowprops=dict(facecolor='black', shrink=0.001, width=1)) plt.annotate('???', xy=(122, 1000), xytext=(122, 1000)) plt.show() .. image-sg:: /auto_examples/images/sphx_glr_04_thresholding_001.png :alt: Image, Histogram :srcset: /auto_examples/images/sphx_glr_04_thresholding_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 45-56 From the distribution above, we can see that the value on the left represents the background, and the value on the right represents the signal. But what about the values in between? If we want to classify the pixels into background and signal (this process is called segmentation), one way is to determine the cutoff value that separates the two classes. This is essentially what "thresholding" is. Below is a simple function to show the thresholding result by visualizing the pixels with values greater than the threshold ``image > threshold``. .. GENERATED FROM PYTHON SOURCE LINES 56-80 .. code-block:: Python def show_threshold(image, threshold, title=''): plt.figure(figsize=(12,3.8)) plt.suptitle(title) plt.subplot(131) plt.title('Image') plt.imshow(image, cmap='gray') plt.subplot(132) plt.title(f"threshold = {threshold}") plt.hist(image.flatten()) plt.axvline(threshold, color='red') plt.xlim() plt.xlabel('pixel value') plt.ylabel('count') plt.subplot(133) plt.title(f"Pixels > {threshold}") plt.imshow(image > threshold, cmap='gray') plt.show() .. GENERATED FROM PYTHON SOURCE LINES 81-84 For example, let's make an initial guess and set the cutoff value, or threshold, to 122. Right in the middle. .. GENERATED FROM PYTHON SOURCE LINES 84-87 .. code-block:: Python show_threshold(image=blobs, threshold=122) .. image-sg:: /auto_examples/images/sphx_glr_04_thresholding_002.png :alt: , Image, threshold = 122, Pixels > 122 :srcset: /auto_examples/images/sphx_glr_04_thresholding_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 88-99 The result (the image on the right), represented as a binary image, is essentially a map showing the location of the object we're interested in (in this case, signal, which is defined by pixels with value greater than the threshold). There are many thresholding algorithms available, so we don't have to guess the threshold value each time. This is especially useful when the image data have different value distributions. Here are a few popular examples. .. GENERATED FROM PYTHON SOURCE LINES 99-114 .. code-block:: Python from skimage.filters import threshold_otsu, threshold_li, threshold_triangle, threshold_isodata th_otsu = threshold_otsu(blobs) th_li = threshold_li(blobs) th_tri = threshold_triangle(blobs) th_iso = threshold_isodata(blobs) for th_algorithm,th_value in {'otsu': th_otsu, 'li': th_li, 'triangle': th_tri, 'isodata': th_iso}.items(): show_threshold(image=blobs, threshold=th_value, title=f"Threshold {th_algorithm}") .. rst-class:: sphx-glr-horizontal * .. image-sg:: /auto_examples/images/sphx_glr_04_thresholding_003.png :alt: Threshold otsu, Image, threshold = 116, Pixels > 116 :srcset: /auto_examples/images/sphx_glr_04_thresholding_003.png :class: sphx-glr-multi-img * .. image-sg:: /auto_examples/images/sphx_glr_04_thresholding_004.png :alt: Threshold li, Image, threshold = 54.85720315303516, Pixels > 54.85720315303516 :srcset: /auto_examples/images/sphx_glr_04_thresholding_004.png :class: sphx-glr-multi-img * .. image-sg:: /auto_examples/images/sphx_glr_04_thresholding_005.png :alt: Threshold triangle, Image, threshold = 11, Pixels > 11 :srcset: /auto_examples/images/sphx_glr_04_thresholding_005.png :class: sphx-glr-multi-img * .. image-sg:: /auto_examples/images/sphx_glr_04_thresholding_006.png :alt: Threshold isodata, Image, threshold = 115, Pixels > 115 :srcset: /auto_examples/images/sphx_glr_04_thresholding_006.png :class: sphx-glr-multi-img .. GENERATED FROM PYTHON SOURCE LINES 115-116 Different algorithms produce different results, so it's best to experiment with various options to find the best fit for your purpose. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.839 seconds) .. _sphx_glr_download_auto_examples_04_thresholding.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: 04_thresholding.ipynb <04_thresholding.ipynb>` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: 04_thresholding.py <04_thresholding.py>` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: 04_thresholding.zip <04_thresholding.zip>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_