OpenCV Gamma Correction

gamma_correction_animated

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

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.

Looking for the source code to this post?
Jump right to the downloads section.

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.

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:

Figure 1: Our original image (left); Gamma correction with G  1 (right), this time the output image is much lighter than the original.

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.

OpenCV Gamma Correction

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:

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 :

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:

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:

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:

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

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:

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

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.

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

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”:

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

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:

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

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 :

Figure 7: Optimal results are obtained near gamma=1.5.

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:

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

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

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.

Downloads:

If you would like to download the code and images used in this post, please enter your email address in the form below. Not only will you get a .zip of the code, I’ll also send you 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! Sound good? If so, enter your email address and I’ll send you the code immediately!

, ,

44 Responses to OpenCV Gamma Correction

  1. Abhinav October 16, 2015 at 2:33 am #

    Hello Adrian,
    Your Blog posts has got me very interested in OpenCV. Keep posting!
    However, I think there is an mistake in the above code, Line 11 and 12 are in each other’s place.

    • Adrian Rosebrock October 16, 2015 at 6:15 am #

      Hey Abhinav — Lines 12 and 12 are actually a single statement that wrap two lines of code.

  2. Brian November 17, 2015 at 6:09 pm #

    Is there any way to perform localized gamma correction? For example, in the picture with dog, is there a function that would gamma correct (lighten) the areas that are in the shadows but would essentially ignore the areas that are in the sun since they are already bright?

    This might help to “equalize” the picture (for lack of the correct word). Once the picture is equalized, other OpenCV functions could the be used to detect things without having to worry about bright and dark regions negatively impacting the results. What do you think?

  3. Rossi September 7, 2016 at 3:06 pm #

    Hello Adrian.
    First of all, I’d like to thank you for all support that your blog is giving to me. Thus, I’d like to know if you have some explanation about image filters, like the Difference of Gaussians and Histogram Equalization.
    Thank you again.
    Best Regards

    • Adrian Rosebrock September 8, 2016 at 1:21 pm #

      Hey Rossi, thanks for the comment. I discuss Difference of Gaussians and Histogram Equalization in quite a bit of detail inside the PyImageSearch Gurus course. I would suggest starting there.

      • Rossi September 8, 2016 at 4:57 pm #

        Thank you Adrian.

  4. YuriiChernyshov November 27, 2016 at 2:07 pm #

    Hi Adrian,
    Consequent question 🙂
    How to do opposite? How to know whether it is necessary to increase or decrease level of gamma? How to know a level of gamma?

    • Adrian Rosebrock November 28, 2016 at 10:24 am #

      In this case you normally wouldn’t unless you have calibrated your camera using a color filter. Gamma correction is almost always a post-processing step after the image has already been captured.

      • YuriiChernyshov December 2, 2016 at 8:12 pm #

        Sorry, I was not clear with my question.
        I was talking about some functionality which normalize gamma before pass image for further processing. In your solution you show how to change gamma assuming that client already knows what to do. But in order to know what to do (increase or decrease) it is necessary to analyze image somehow … The question is “how” ?

        • Adrian Rosebrock December 5, 2016 at 1:37 pm #

          You would need to visually inspect the image. This is how graphic designers and photographers edit an image. They capture an image, open it in Photoshop (or whatever other photo editing software) and adjust any gamma levels they see fit.

          If you were deploying a computer vision product you would inspect the environment and captured images, then build in the gamma correction to the program.

  5. Yurvan Igo May 18, 2017 at 12:51 am #

    How to save the new image has changed

    • Adrian Rosebrock May 18, 2017 at 11:50 am #

      You can use the cv2.imwrite function to write an image to file:

      cv2.imwrite("foo.png", image)

      You can learn more about the basics of OpenCV and computer vision inside Practical Python and OpenCV.

  6. Irene Among May 25, 2017 at 11:12 pm #

    Hi, I like your explanations very clear.
    I am doing projects in opencv and python but totally new to it.
    Your posts are really helpful.
    Thank you.

    • Adrian Rosebrock May 28, 2017 at 1:15 am #

      Thanks Irene — I’m happy to hear you’ve found the PyImageSearch blog helpful 🙂 If you are new to OpenCV and computer vision, be sure to take a look at Practical Python and OpenCV. This book is designed to help beginners learn the fundamentals of OpenCV quickly.

  7. ambika September 14, 2017 at 6:49 am #

    Hi,

    Great Post! But when I try to save the Gamma corrected output of the image, it saves both images together in one image just as it is shown above. What changes should I make in the code to display as well as save only the output image?

    • Adrian Rosebrock September 14, 2017 at 7:00 am #

      Remove the np.hstack call:

      cv2.imwrite("output.png", adjusted)

  8. Kinvert February 23, 2018 at 9:50 pm #

    Thanks for this! It is helping our students with a project.

    Do you have any recommended articles on color correction / white balance?

    Students are considering LUT on an RGB / HSV split, then a merge. The tables would have to be a bit different.

    Thanks again!

    • Adrian Rosebrock February 26, 2018 at 2:03 pm #

      I’m glad to hear my tutorials are helping your students, that’s great!

      I do not have any tutorials on color correction or white balancing. I will try to cover these subjects in the future. The gist is that you need to compute the CDF of both your input and reference images, then transfer the CDF to the input image to correct for the white balance.

  9. esha May 16, 2018 at 5:09 am #

    hello
    how i can i apply gamma technique to gray scale filtered image

    • Adrian Rosebrock May 17, 2018 at 6:57 am #

      You can still use the method in this blog post.

  10. esha May 29, 2018 at 3:39 am #

    hello
    the above code is showing error pls help
    the error is as follows:
    check.py: error: the following arguments are required: -i/–fogimage

  11. esha June 4, 2018 at 3:10 am #

    on command line it is showing error
    unrecognized argument : example1.png
    pls resolve

    • Adrian Rosebrock June 5, 2018 at 7:55 am #

      I believe your error is due to not utilizing the command line arguments properly. Make sure you read this post.

  12. esha June 4, 2018 at 5:02 am #

    sir i have downloaded ur code nd apply with my images but it is showing error of unrecognized argument

    • Adrian Rosebrock June 5, 2018 at 7:52 am #

      What is the exact error you are receiving?

  13. esha June 7, 2018 at 1:25 am #

    if possible pls send me code which is applicable to gray images

  14. Dharshan June 29, 2018 at 4:37 am #

    Is there any posts which will analyse the image and set a gamma value based on that,rather than user defining it

  15. Rohil July 6, 2018 at 2:05 am #

    Hi Adrian

    I really liked your explanation. My only doubt is why the lookup table method is faster than the first method?

    • Adrian Rosebrock July 10, 2018 at 8:57 am #

      Which first method are you referring to? As to why a LUT is fast see this sentence:

      “OpenCV can then take this table and quickly determine the output value for a given pixel in O(1) time.”

  16. Jibin John July 13, 2018 at 2:02 am #

    Hello Adrian is it a best method for the correction of images taken at night using cameras

    • Adrian Rosebrock July 13, 2018 at 4:48 am #

      What type of camera are you using? Some cameras include a “smart IR” method that can help perform correction at capture time which would probably be more ideal than trying to perform gamma correction manually.

  17. esha July 13, 2018 at 5:15 am #

    Is there any posts which will analyse the image and set a gamma value based on that,rather than user defining it

    • Adrian Rosebrock July 13, 2018 at 5:23 am #

      No, I do not have any tutorials on automatically setting the gamma value.

  18. anne September 1, 2018 at 3:47 pm #

    hi
    Why did you use inverse gamma instead of applying the normal gamma?

    thanks

  19. Eli February 9, 2019 at 8:23 am #

    Hi, is there a way to do this for webcams?

  20. Edo April 10, 2019 at 2:41 am #

    Hello sir, can we do gamma correction to the video stream ? then how to do that ?

    • Adrian Rosebrock April 12, 2019 at 11:36 am #

      You would access your video stream and then apply gamma correction to each individual frame. If you’ve never accessed a video stream before, be sure to refer to Practical Python and OpenCV where I cover the topic in detail.

  21. Quek Yao Jing April 30, 2019 at 7:44 am #

    Hi Dr, is there any ways for us to do auto gamma correction? For example, when the image is too bright, it will make it darker and when the image is too dark, then it will make it brighter?

    • Harendra May 15, 2019 at 6:42 am #

      Hi,
      I also need this for my code.Auto correction of gamma. If you find the solution please help me as well.

      My use case is I am taking images in the night and so they are dark. I need mechanism to detect if the images are being taken in the dark and auto correct with out any human intervention.

  22. Vaibhaw July 2, 2019 at 1:30 am #

    Hi Adrian,
    Thanks for the post and your comments reply for different problem which gives kick to my geek of learning OpenCV. But I my domain is C++. If you have any tutorial/Blog based on C++, that will be great for me.

    Thanks again
    Best Regards

    • Adrian Rosebrock July 4, 2019 at 10:24 am #

      Sorry, I only provide Python tutorials on PyImageSearch.

Leave a Reply

[email]
[email]