.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples\03_brightness_contrast.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_03_brightness_contrast.py: ======================= Brightness and Contrast ======================= Previously, in :ref:`single-channel-image`, we learned that we can assign different values to different colors using various color gradients. We can also change the **range of values** represented by a color gradient. In grayscale, adjusting this range affects the **brightness and contrast** of an image. To show how this works in practice, we'll use *blobs.jpeg* as our example image. .. GENERATED FROM PYTHON SOURCE LINES 15-23 .. 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) .. GENERATED FROM PYTHON SOURCE LINES 24-35 Before we start, let's create a simple function that displays an image and its histogram side by side. We can also specify a minimum and maximum value (``vmin`` and ``vmax``) for displaying the image. Since we use grayscale as the color gradient, pixels with ``vmin`` value will be displayed as black, and pixels with ``vmax`` value will be displayed as white. In addition, red and green lines will be drawn on the histogram to indicate ``vmin`` and ``vmax``, respectively. .. GENERATED FROM PYTHON SOURCE LINES 35-61 .. code-block:: Python def show_image_histogram(image, title='', vmin=None, vmax=None): plt.figure(figsize=(9,3.8)) plt.suptitle(title) plt.subplot(121) plt.title('Image') if vmin is None: vmin = image.min() if vmax is None: vmax = image.max() plt.imshow(image, cmap='gray', vmin=vmin, vmax=vmax) plt.colorbar() plt.subplot(122, box_aspect=1.2) plt.title('Histogram') plt.hist(image.flatten()) plt.axvline(vmin, color='red') plt.axvline(vmax, color='green') plt.xlim() plt.xlabel('pixel value') plt.ylabel('count') plt.show() .. GENERATED FROM PYTHON SOURCE LINES 62-69 By default, ``plt.imshow``, automatically sets the darkest color (black) to the minimum pixel value and the brightest color (white) to the maximum pixel value in the image. Let's look at the distribution of these pixel values using the ``show_image_histogram`` function: .. GENERATED FROM PYTHON SOURCE LINES 69-72 .. code-block:: Python show_image_histogram(blobs, title="Default display") .. image-sg:: /auto_examples/images/sphx_glr_03_brightness_contrast_001.png :alt: Default display, Image, Histogram :srcset: /auto_examples/images/sphx_glr_03_brightness_contrast_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 73-82 Brightness ========== In a grayscale image, brighter areas correspond to the upper end of the grayscale gradient. The more pixels mapped to this upper end, the brighter the image appears. One way to adjust brightness is to **shift the display range (scale)**. We can do this by changing ``vmin`` and ``vmax``. .. GENERATED FROM PYTHON SOURCE LINES 82-88 .. code-block:: Python shift = 100 show_image_histogram(blobs, title=f"Shift the scale {shift} to the right", vmin=blobs.min()+shift, vmax=blobs.max()+shift) show_image_histogram(blobs, title=f"Shift the scale {shift} to the left", vmin=blobs.min()-shift, vmax=blobs.max()-shift) .. rst-class:: sphx-glr-horizontal * .. image-sg:: /auto_examples/images/sphx_glr_03_brightness_contrast_002.png :alt: Shift the scale 100 to the right, Image, Histogram :srcset: /auto_examples/images/sphx_glr_03_brightness_contrast_002.png :class: sphx-glr-multi-img * .. image-sg:: /auto_examples/images/sphx_glr_03_brightness_contrast_003.png :alt: Shift the scale 100 to the left, Image, Histogram :srcset: /auto_examples/images/sphx_glr_03_brightness_contrast_003.png :class: sphx-glr-multi-img .. GENERATED FROM PYTHON SOURCE LINES 89-96 .. note:: Note that if a pixel's value falls outside the specified display range, it will appear as the color at the closest end of the gradient. Higher-than-maximum values are shown as white, and lower-than-minimum values are shown as black. .. GENERATED FROM PYTHON SOURCE LINES 98-101 - **Shifting the scale to the right** places fewer pixels at the upper end, **decreasing brightness**. - **Shifting the scale to the left** places more pixels at the upper end, **increasing brightness**. .. GENERATED FROM PYTHON SOURCE LINES 104-117 Contrast ======== While brightness relates to how many pixels lie at the upper end of the scale, you can think of contrast as how spread out the pixel values are across the scale. For example, the blobs image we've been using already has high contrast. We can see this in the histogram: pixel values are well-spread out, and there are distinct peaks at opposite ends of the scale. This indicates a large difference between dark and bright areas, resulting in high contrast. One way to change the contrast is by adjusting the grayscale display range. .. GENERATED FROM PYTHON SOURCE LINES 117-122 .. code-block:: Python show_image_histogram(blobs, title=f"Narrow range: 100 – 150 (Higher contrast)", vmin=100, vmax=150) show_image_histogram(blobs, title=f"Wide Range: -100 – 350 (Low contrast)", vmin=-100, vmax=350) .. rst-class:: sphx-glr-horizontal * .. image-sg:: /auto_examples/images/sphx_glr_03_brightness_contrast_004.png :alt: Narrow range: 100 – 150 (Higher contrast), Image, Histogram :srcset: /auto_examples/images/sphx_glr_03_brightness_contrast_004.png :class: sphx-glr-multi-img * .. image-sg:: /auto_examples/images/sphx_glr_03_brightness_contrast_005.png :alt: Wide Range: -100 – 350 (Low contrast), Image, Histogram :srcset: /auto_examples/images/sphx_glr_03_brightness_contrast_005.png :class: sphx-glr-multi-img .. GENERATED FROM PYTHON SOURCE LINES 123-126 - By **narrowing the display range** to 100–150, the pixels are forced toward opposite ends (black and white), making the image to have **more contrast**. - By **widening the display range** to -100–350, more pixels cluster in the middle of the grayscale. Because there's less difference between the lightest and darkest displayed values, the image appears to have **less contrast**. .. GENERATED FROM PYTHON SOURCE LINES 129-134 Practical Example ================= Here we have two fluorescence images showing mitochondria under two different conditions: .. GENERATED FROM PYTHON SOURCE LINES 134-143 .. code-block:: Python from tifffile import imread mito_1 = imread('images/mitochondria_1.tif') mito_2 = imread('images/mitochondria_2.tif') show_image_histogram(mito_1, title="Condition 1 (Automatic display)") show_image_histogram(mito_2, title="Condition 2 (Automatic display)") .. rst-class:: sphx-glr-horizontal * .. image-sg:: /auto_examples/images/sphx_glr_03_brightness_contrast_006.png :alt: Condition 1 (Automatic display), Image, Histogram :srcset: /auto_examples/images/sphx_glr_03_brightness_contrast_006.png :class: sphx-glr-multi-img * .. image-sg:: /auto_examples/images/sphx_glr_03_brightness_contrast_007.png :alt: Condition 2 (Automatic display), Image, Histogram :srcset: /auto_examples/images/sphx_glr_03_brightness_contrast_007.png :class: sphx-glr-multi-img .. GENERATED FROM PYTHON SOURCE LINES 144-154 From the images above, both look similar. However, this is *misleading*. Because their histograms show different intensity distributions. Since fluorescence intensity represents the detected fluorophore signal, the mitochondria clearly don't contain the same amount of fluorophore, even though they may look similar in the above image representations. A more accurate way to compare them is to use the **same display range** (brightness and contrast) for both: .. GENERATED FROM PYTHON SOURCE LINES 154-164 .. code-block:: Python # Determine a global min/max from both images max_val = max(mito_1.max(), mito_2.max()) min_val = min(mito_1.min(), mito_2.min()) show_image_histogram(mito_1,title=f"Condition 1 (Display range: {min_val}–{max_val})", vmin=min_val, vmax=max_val) show_image_histogram(mito_2, title=f"Condition 2 (Display range: {min_val}–{max_val})", vmin=min_val, vmax=max_val) .. rst-class:: sphx-glr-horizontal * .. image-sg:: /auto_examples/images/sphx_glr_03_brightness_contrast_008.png :alt: Condition 1 (Display range: 348–2478), Image, Histogram :srcset: /auto_examples/images/sphx_glr_03_brightness_contrast_008.png :class: sphx-glr-multi-img * .. image-sg:: /auto_examples/images/sphx_glr_03_brightness_contrast_009.png :alt: Condition 2 (Display range: 348–2478), Image, Histogram :srcset: /auto_examples/images/sphx_glr_03_brightness_contrast_009.png :class: sphx-glr-multi-img .. GENERATED FROM PYTHON SOURCE LINES 165-168 By using a the same display range, you can see the difference between the two conditions more clearly. .. GENERATED FROM PYTHON SOURCE LINES 170-175 Summary ======= Brightness and contrast (in this context) are simply how we set the scale or range of values represented by a grayscale gradient. .. GENERATED FROM PYTHON SOURCE LINES 177-196 Important ========= .. warning:: Changing the display range does not change the pixel values of the image itself. However, when you save or copy the image after adjusting the display, it may automatically rescale the pixel values, because most image viewers expect a standard range of 0–255 (for 8-bit) or 0–65,535 (for 16-bit). This is also the case when using ImageJ. To rescale the pixel values of the image to a standard display range, we can use the following steps: 1. **Clip** the pixel values to a specified minimum (``minval``) and maximum (``maxval``). 2. **Normalize** the clipped values to 0–1. 3. **Scale** this range to 0–255 (for 8-bit) or 0–65,535 (for 16-bit). .. GENERATED FROM PYTHON SOURCE LINES 196-207 .. code-block:: Python def rescale(a, minval, maxval, image_type='8-bit'): clipped = np.clip(a, minval, maxval) normalized = (clipped - clipped.min()) / (max(clipped.max(), maxval) - min(clipped.min(), minval)) if image_type=='8-bit': scaled = normalized * 255 return scaled.astype(np.uint8) elif image_type=='16-bit': scaled = normalized * 65535 return scaled.astype(np.uint16) .. GENERATED FROM PYTHON SOURCE LINES 208-212 Let's apply it to our examples above (namely, the image with *shifted* range to lower the brightness and *narrowed range* to increase the contrast) and display them with the standard 0–255 range: .. GENERATED FROM PYTHON SOURCE LINES 212-218 .. code-block:: Python shifted = rescale(blobs, minval=blobs.min()+shift, maxval=blobs.max()+shift) narrow_range = rescale(blobs, minval=100, maxval=150) show_image_histogram(shifted, title="Shifted 100 and Rescaled", vmin=0, vmax=255) show_image_histogram(narrow_range, title="Narrow range (100–150) and Rescaled", vmin=0, vmax=255) .. rst-class:: sphx-glr-horizontal * .. image-sg:: /auto_examples/images/sphx_glr_03_brightness_contrast_010.png :alt: Shifted 100 and Rescaled, Image, Histogram :srcset: /auto_examples/images/sphx_glr_03_brightness_contrast_010.png :class: sphx-glr-multi-img * .. image-sg:: /auto_examples/images/sphx_glr_03_brightness_contrast_011.png :alt: Narrow range (100–150) and Rescaled, Image, Histogram :srcset: /auto_examples/images/sphx_glr_03_brightness_contrast_011.png :class: sphx-glr-multi-img .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.287 seconds) .. _sphx_glr_download_auto_examples_03_brightness_contrast.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: 03_brightness_contrast.ipynb <03_brightness_contrast.ipynb>` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: 03_brightness_contrast.py <03_brightness_contrast.py>` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: 03_brightness_contrast.zip <03_brightness_contrast.zip>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_