Title: OpenCV Gamma Correction - PyImageSearch

URL Source: https://pyimagesearch.com/2015/10/05/opencv-gamma-correction/

Published Time: 2015-10-05T14:00:25+00:00

Markdown Content:
**Did you know that the human eye perceives color and luminance differently than the sensor on your smartphone or digital camera?**

[![Image 1: gamma_correction_animated](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20400%20532'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/09/gamma_correction_animated.gif)

You see, when _twice_ the number of photons hit the sensor of a digital camera, it receives _twice_ the signal (a linear relationship). However, that’s not how our human eyes work. Instead, we perceive _double the amount of light_ as only a _fraction_ brighter (a non-linear relationship)! Furthermore, our eyes are also much more sensitive to changes in dark tones than brighter tones (another non-linear relationship).

In order to account for this we can apply _gamma correction_, a translation between the sensitivity of our eyes and sensors of a camera.

In the remainder of this post I’ll demonstrate how you can implement a super fast, dead-simple gamma correction function using Python and OpenCV.

![Image 2](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20128%20128'%3E%3C/svg%3E)

#### Looking for the source code to this post?

[Jump Right To The Downloads Section](#download-the-code)

Gamma correction and the Power Law Transform
--------------------------------------------

Gamma correction is also known as the _Power Law Transform._ First, our image pixel intensities must be scaled from the range _\[0, 255\]_ to _\[0, 1.0\]_. From there, we obtain our output gamma corrected image by applying the following equation:

_O = I ^ (1 / G)_

Where _I_ is our input image and _G_ is our gamma value. The output image _O_ is then scaled back to the range _\[0, 255\]_.

Gamma values _< 1_ will shift the image towards the darker end of the spectrum while gamma values _\> 1_ will make the image appear lighter. A gamma value of _G=1_ will have no affect on the input image:

[![Image 3: Figure 1: Our original image (left); Gamma correction with G 1 (right), this time the output image is much lighter than the original.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201000%20506'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/09/gamma_correction_example.jpg)

**Figure 1:** Our original image _(left)_; Gamma correction with _G < 1 (center)_, notice how the gamma adjusted image is much darker than the original image; Gamma correction with _G > 1 (right)_, this time the output image is much lighter than the original.

Now that we understand what gamma correction is, let’s use OpenCV and Python to implement it. Open up a new file, name it `adjust_gamma.py` , and we’ll get started:

\# import the necessary packages
from \_\_future\_\_ import print\_function
import numpy as np
import argparse
import cv2

def adjust\_gamma(image, gamma=1.0):
	# build a lookup table mapping the pixel values \[0, 255\] to
	# their adjusted gamma values
	invGamma = 1.0 / gamma
	table = np.array(\[((i / 255.0) \*\* invGamma) \* 255
		for i in np.arange(0, 256)\]).astype("uint8")

	# apply gamma correction using the lookup table
	return cv2.LUT(image, table)

**Lines 2-5** simply import our necessary packages, nothing special here.

We define our `adjust_gamma` function on **Line 7**. This method requires a single parameter, `image` , which is the image we want to apply gamma correction to. A second (optional) value is our `gamma` value. In this case, we default `gamma=1.0` , but you should supply whatever value is necessary to obtain a decent looking corrected image.

There are two (easy) ways to apply gamma correction using OpenCV and Python. The first method is to simply leverage the fact that Python + OpenCV represents images as NumPy arrays. All we need to do is scale the pixel intensities to the range _\[0, 1.0\]_, apply the transform, and then scale back to the range _\[0, 255\]_. Overall, the NumPy approach involves a division, raising to a power, followed by a multiplication — this tends to be very fast since all these operations are vectorized.

However, there is an even _faster_ way to perform gamma correction thanks to OpenCV. All we need to do is build a table (i.e. dictionary) that maps the _input pixel values_ to the _output gamma corrected values_. OpenCV can then take this table and quickly determine the output value for a given pixel in _O(1)_ time.

For example, here is an example lookup table for `gamma=1.2` :

0 => 0
1 => 2
2 => 4
3 => 6
4 => 7
5 => 9
6 => 11
7 => 12
8 => 14
9 => 15
10 => 17

The _left column_ is the **input pixel value** while the _right column_ is the **output pixel value** after applying the power law transform.

**Lines 11 and 12** build this lookup table by looping over all pixel values in the range _\[0, 255\]_. The pixel value is then scaled to the range _\[0, 1.0\]_ followed by being raised to the power of the inverse gamma — this value is then stored in the `table` .

Lastly, all we need to do is apply the `cv2.LUT` function (**Line 15**) to take the input `image` and the `table` and find the correct mappings for each pixel value — it’s a simple (and yet very speedy) operation!

Let’s continue on with our example:

\# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add\_argument("-i", "--image", required=True,
	help="path to input image")
args = vars(ap.parse\_args())

# load the original image
original = cv2.imread(args\["image"\])

**Lines 17-21** handle parsing command line arguments. We only need a single switch here, `--image` , which is the path to where our input image resides on disk. **Line 24** takes the path to our image and loads it.

Let’s explore gamma correction by using a variety of gamma values and inspecting the output image for each:

\# loop over various values of gamma
for gamma in np.arange(0.0, 3.5, 0.5):
	# ignore when gamma is 1 (there will be no change to the image)
	if gamma == 1:
		continue

	# apply gamma correction and show the images
	gamma = gamma if gamma > 0 else 0.1
	adjusted = adjust\_gamma(original, gamma=gamma)
	cv2.putText(adjusted, "g={}".format(gamma), (10, 30),
		cv2.FONT\_HERSHEY\_SIMPLEX, 0.8, (0, 0, 255), 3)
	cv2.imshow("Images", np.hstack(\[original, adjusted\]))
	cv2.waitKey(0)

On **Line 27** we start by looping over `gamma` values in the range _\[0, 3.0\]_ (the `np.arange` function is _non-inclusive_), incrementing by _0.5_ at each step.

In the case that our `gamma` value is _1.0_, we simply ignore it (**Lines 29 and 30**) since `gamma=1.0` will not change our input image.

From there, **Lines 33-38** apply gamma correction to our image and display the output result.

To see gamma correction in action, just open up a terminal and execute the following command:

$ python adjust\_gamma.py --image example\_01.png

[![Image 4: Figure 2: When applying gamma correction with G < 1, the output image is will darker than the original input image.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20438'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/09/gamma_correction_example_01_g05.jpg)

**Figure 2:** When applying gamma correction with _G < 1_, the output image is will darker than the original input image.

Notice for `gamma=0.5` that the gamma corrected image _(right)_ is substantially darker than the input image _(left)_ which is already quite dark — we can barely see any detail on the dog’s face in the original yet, let alone the gamma corrected version!

However, at `gamma=1.5` the image starts to lighten up and we can see more detail:

[![Image 5: Figure 3: As the gamma value reaches 1.0 and starts to exceed it, the image lightens up and we can see more detail.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20438'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/09/gamma_correction_example_01_g15.jpg)

**Figure 3:** As the gamma value reaches 1.0 and starts to exceed it, the image lightens up and we can see more detail.

By the time we reach `gamma=2.0` , the details in the image are fully visible.

[![Image 6: Figure 4: Now at gamma=2.0, we can fully see the details on the dogs face.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20438'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/09/gamma_correction_example_01_g20.jpg)

**Figure 4:** Now at _gamma=2.0_, we can fully see the details on the dogs face.

Although at `gamma=2.5` , the image starts to appear “washed out”:

[![Image 7: Figure 5: However, if we carry gamma correction too far, the image will start to appear washed out.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20438'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/09/gamma_correction_example_01_g25.jpg)

**Figure 5:** However, if we carry gamma correction too far, the image will start to appear washed out.

Let’s give another image a try:

$ python adjust\_gamma.py --image example\_02.png

[![Image 8: Figure 6: After applying gamma correction with gamma=0.5, we cannot see any detail in this image.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20275'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/09/gamma_correction_example_02_g05.jpg)

**Figure 6:** After applying gamma correction with _gamma=0.5_, we cannot see any detail in this image.

Just like in `example_01.png` , a gamma value of _0.5_ makes the input image appear darker than it already is. We can’t really make out any detail in this image, other than there is sky and what appears to be a mountain range.

However, this changes when we apply gamma correction with `gamma=1.5` :

[![Image 9: Figure 7: Optimal results are obtained near gamma=1.5.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20275'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/09/gamma_correction_example_02_g15.jpg)

**Figure 7:** Optimal results are obtained near _gamma=1.5_.

Now we can see that the image has become much lighter — we can even start to see there are trees in the foreground, something that is not entirely apparent from the original input image on the _left_.

At `gamma=2.0` the image starts to appear washed out, but again, the difference between the original image and the gamma corrected image is quite substantial:

[![Image 10: Figure 8: But again, we can carry gamma correction too far and washout our image.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20275'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/09/gamma_correction_example_02_g20.jpg)

**Figure 8:** But again, we can carry gamma correction too far and washout our image.

### What's next? We recommend [PyImageSearch University](https://pyimagesearch.com/pyimagesearch-university/?utm_source=blogPost&utm_medium=bottomBanner&utm_campaign=What%27s%20next%3F%20I%20recommend).

**Course information:**  
84 total classes • 114+ hours of on-demand code walkthrough videos • Last updated: February 2024  
★★★★★ 4.84 (128 Ratings) • 16,000+ Students Enrolled

**I strongly believe that if you had the right teacher you could _master_ computer vision and deep learning.**

Do you think learning computer vision and deep learning has to be time-consuming, overwhelming, and complicated? Or has to involve complex mathematics and equations? Or requires a degree in computer science?

That’s _not_ the case.

All you need to master computer vision and deep learning is for someone to explain things to you in _simple, intuitive_ terms. _And that’s exactly what I do_. My mission is to change education and how complex Artificial Intelligence topics are taught.

If you're serious about learning computer vision, your next stop should be PyImageSearch University, the most comprehensive computer vision, deep learning, and OpenCV course online today. Here you’ll learn how to _successfully_ and _confidently_ apply computer vision to your work, research, and projects. Join me in computer vision mastery.

**Inside PyImageSearch University you'll find:**

*   ✓ **84 courses** on essential computer vision, deep learning, and OpenCV topics
*   ✓ **84 Certificates** of Completion
*   ✓ **114+ hours** of on-demand video
*   ✓ **Brand new courses released _regularly_**, ensuring you can keep up with state-of-the-art techniques
*   ✓ **Pre-configured Jupyter Notebooks in Google Colab**
*   ✓ Run all code examples in your web browser — works on Windows, macOS, and Linux (no dev environment configuration required!)
*   ✓ Access to **centralized code repos for _all_ 536+ tutorials** on PyImageSearch
*   ✓ **Easy one-click downloads** for code, datasets, pre-trained models, etc.
*   ✓ **Access** on mobile, laptop, desktop, etc.

[Click here to join PyImageSearch University](https://pyimagesearch.com/pyimagesearch-university/?utm_source=blogPost&utm_medium=bottomBanner&utm_campaign=What%27s%20next%3F%20I%20recommend)

Summary
-------

In this blog post we learned about _gamma correction_, also called the _Power Law Transform._ We then implemented gamma correction using Python and OpenCV.

The reason we apply gamma correction is because our eyes perceive color and luminance differently than the sensors in a digital camera. When a sensor on a digital camera picks up _twice_ the amount of photons, the signal is _doubled_. However, our eyes do not work like this. Instead, our eyes perceive _double_ the amount of light as only a _fraction_ brighter. Thus, while a digital camera has a _linear_ relationship between brightness our eyes have a _non-linear_ relationship. In order to account for this relationship we apply gamma correction.

Be sure to download the code to this post and try applying gamma correction to your own photos. Try to go through your photo collection and find images that are either _excessively dark_ or _very bright_ _and washed out_. Then perform gamma correction on these images and see if they become more visually appealing.

![Image 11](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20410%20567'%3E%3C/svg%3E)

#### Download the Source Code and FREE 17-page Resource Guide

Enter your email address below to get a .zip of the code and a **FREE 17-page Resource Guide on Computer Vision, OpenCV, and Deep Learning.** Inside you'll find my hand-picked tutorials, books, courses, and libraries to help you master CV and DL!