Here are two ways to do that in Python/OpenCV. Both are based upon the ratio of the log(mid-gray)/log(mean). Results are often reasonable, especially for dark image, but do not work in all cases. For bright image, invert the gray or value image, process as for dark images, then invert again and recombine if using the value image.

  • Read the input
  • Convert to gray or HSV value
  • Compute the ratio log(mid-gray)/log(mean) on the gray or value channel
  • Raise the input or value to the power of the ratio
  • If using the value channel, combine the new value channel with the hue and saturation channels and convert back to RGB

Input:

import cv2
import numpy as np
import math

# read image
img = cv2.imread('lioncuddle1.jpg')

# METHOD 1: RGB

# convert img to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# compute gamma = log(mid*255)/log(mean)
mid = 0.5
mean = np.mean(gray)
gamma = math.log(mid*255)/math.log(mean)
print(gamma)

# do gamma correction
img_gamma1 = np.power(img, gamma).clip(0,255).astype(np.uint8)



# METHOD 2: HSV (or other color spaces)

# convert img to HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
hue, sat, val = cv2.split(hsv)

# compute gamma = log(mid*255)/log(mean)
mid = 0.5
mean = np.mean(val)
gamma = math.log(mid*255)/math.log(mean)
print(gamma)

# do gamma correction on value channel
val_gamma = np.power(val, gamma).clip(0,255).astype(np.uint8)

# combine new value channel with original hue and sat channels
hsv_gamma = cv2.merge([hue, sat, val_gamma])
img_gamma2 = cv2.cvtColor(hsv_gamma, cv2.COLOR_HSV2BGR)

# show results
cv2.imshow('input', img)
cv2.imshow('result1', img_gamma1)
cv2.imshow('result2', img_gamma2)
cv2.waitKey(0)
cv2.destroyAllWindows()

# save results
cv2.imwrite('lioncuddle1_gamma1.jpg', img_gamma1)
cv2.imwrite('lioncuddle1_gamma2.jpg', img_gamma2)


Result from method 1:

Result from method 2:

Answer from fmw42 on Stack Overflow
🌐
PyImageSearch
pyimagesearch.com › home › blog › opencv gamma correction
OpenCV Gamma Correction - PyImageSearch
April 22, 2021 - 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.
Top answer
1 of 1
14

Here are two ways to do that in Python/OpenCV. Both are based upon the ratio of the log(mid-gray)/log(mean). Results are often reasonable, especially for dark image, but do not work in all cases. For bright image, invert the gray or value image, process as for dark images, then invert again and recombine if using the value image.

  • Read the input
  • Convert to gray or HSV value
  • Compute the ratio log(mid-gray)/log(mean) on the gray or value channel
  • Raise the input or value to the power of the ratio
  • If using the value channel, combine the new value channel with the hue and saturation channels and convert back to RGB

Input:

import cv2
import numpy as np
import math

# read image
img = cv2.imread('lioncuddle1.jpg')

# METHOD 1: RGB

# convert img to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# compute gamma = log(mid*255)/log(mean)
mid = 0.5
mean = np.mean(gray)
gamma = math.log(mid*255)/math.log(mean)
print(gamma)

# do gamma correction
img_gamma1 = np.power(img, gamma).clip(0,255).astype(np.uint8)



# METHOD 2: HSV (or other color spaces)

# convert img to HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
hue, sat, val = cv2.split(hsv)

# compute gamma = log(mid*255)/log(mean)
mid = 0.5
mean = np.mean(val)
gamma = math.log(mid*255)/math.log(mean)
print(gamma)

# do gamma correction on value channel
val_gamma = np.power(val, gamma).clip(0,255).astype(np.uint8)

# combine new value channel with original hue and sat channels
hsv_gamma = cv2.merge([hue, sat, val_gamma])
img_gamma2 = cv2.cvtColor(hsv_gamma, cv2.COLOR_HSV2BGR)

# show results
cv2.imshow('input', img)
cv2.imshow('result1', img_gamma1)
cv2.imshow('result2', img_gamma2)
cv2.waitKey(0)
cv2.destroyAllWindows()

# save results
cv2.imwrite('lioncuddle1_gamma1.jpg', img_gamma1)
cv2.imwrite('lioncuddle1_gamma2.jpg', img_gamma2)


Result from method 1:

Result from method 2:

🌐
GitHub
github.com › atapour › ip-python-opencv › blob › main › gamma_correction.py
ip-python-opencv/gamma_correction.py at main · atapour/ip-python-opencv
Examples and code demonstrations for the Image Processing module at Durham University - ip-python-opencv/gamma_correction.py at main · atapour/ip-python-opencv
Author: atapour
🌐
Lindevs
lindevs.com › apply-gamma-correction-to-an-image-using-opencv
Apply Gamma Correction to an Image using OpenCV | Lindevs
November 2, 2022 - import cv2 import numpy as np def gammaCorrection(src, gamma): invGamma = 1 / gamma table = [((i / 255) ** invGamma) * 255 for i in range(256)] table = np.array(table, np.uint8) return cv2.LUT(src, table) img = cv2.imread('test.jpg') gammaImg = gammaCorrection(img, 2.2) cv2.imshow('Original image', img) cv2.imshow('Gamma corrected image', gammaImg) cv2.waitKey(0) cv2.destroyAllWindows() #include <opencv2/opencv.hpp> using namespace cv; void gammaCorrection(const Mat &src, Mat &dst, const float gamma) { float invGamma = 1 / gamma; Mat table(1, 256, CV_8U); uchar *p = table.ptr(); for (int i = 0
🌐
Medium
medium.com › @daniel.lepold › image-processing-in-python-gamma-correction-homography-transformation-and-face-detection-with-7c806a587186
Face Detection from ID Cards in Python using OpenCV: Gamma Correction & Homography | by Daniel Lepold | Medium
May 6, 2025 - Gamma correction is a method that allows nonlinear adjustment of an image’s brightness. The adjust_gamma() function applies gamma correction using a precomputed lookup table. A gamma value > 1 makes the image brighter, while a gamma value ...
🌐
DEV Community
dev.to › tinazhouhui › discovering-opencv-with-python-gamma-correction-3cnh
Discovering OpenCV with Python: Gamma correction - DEV Community
January 11, 2023 - Another practical exercise that I had quite some fun with was gamma correction. This concept is mainly used when we want to adjust the brightness of an image. We could also use it to restore the faded pictures to their previous depth of colour. Since I am just a Python Padawan, we will be demonstrating this on grayscale pictures but I promise, the concept works on coloured images as well.
🌐
Medium
medium.com › @sinhaaa003 › transforming-images-rgb-to-grayscale-and-gamma-correction-with-python-fe5a0afa12b9
Transforming Images: RGB to Grayscale and Gamma Correction with Python | by Aditya Sinha | Medium
July 30, 2024 - Python Programming · Machine Learning · Data Science · Opencv · Aditya Sinha · 4 min read · ·Jul 30, 2024 · -- Listen · Share · By Aditya Sinha and Bhumikamohan · Welcome to the fascinating world of image processing! In this article, we, Aditya Sinha and Bhumika M, will guide you through two fundamental yet powerful transformations: converting an RGB image to grayscale and applying gamma correction.
🌐
YouTube
youtube.com › watch
OpenCV 13: Gamma Correction to Increase or Decrease Brightness | Python | OpenCV - YouTube
OpenCV 13: Gamma Correction to Increase or Decrease Brightness | Python | OpenCVGitHub JupyterNotebook: https://github.com/siddiquiamir/OpenCVGitHub Data: ht...
Published: August 21, 2023
Find elsewhere
🌐
LinuxTut
linuxtut.com › en › c3cd5475663c41d9f154
Gamma correction without using OpenCV
May 13, 2020 - The image processing library OpenCV also has a gamma correction function. As you can see from the formula, it's so easy that you can create a gamma correction function with just numpy. ... Let's create a gamma correction function based on the formula. For a moment.
🌐
OpenCV
forum.opencv.org › python
Auto selection of Gamma value for image brightness - Python - OpenCV
January 19, 2021 - I have a sequence of images or live video and I want to check if the image is darker or brighter, then adjust the brightness using gamma correction i.e. Image ^ gamma. gamma = 1 do nothing and smaller than 1 value of ga…
🌐
GitHub
github.com › leowang7 › iagcwd
GitHub - leowang7/iagcwd: An improved contrast enhancement method for image. :camera: · GitHub
This is an python implementation of the paper "Contrast enhancement of brightness-distorted images by improved adaptive gamma correction." at https://arxiv.org/abs/1709.04427. The purpose of the algorithm is to improve the contrast of the image ...
Starred by 69 users
Forked by 18 users
Languages: Python
Top answer
1 of 3
36

I know I am late, but I would suggest using gamma correction.

Now what is gamma correction?

I will make it clear in layman's terms:

  • To display image on a screen, input voltage is needed.
  • This voltage is output as light intensity.
  • In perfect world, input voltage would be linear to output intensity.
  • But the real screen output is close to an exponential curve, the exponent being gamma.

Since the computer screen applies a gamma value to the image on screen, the process of applying inverse gamma to counter this effect is called gamma correction.

Here is the code for the same using OpenCV 3.0.0 and python:

import cv2
import numpy as np

def adjust_gamma(image, gamma=1.0):

   invGamma = 1.0 / gamma
   table = np.array([((i / 255.0) ** invGamma) * 255
      for i in np.arange(0, 256)]).astype("uint8")

   return cv2.LUT(image, table)

x = 'C:/Users/524316/Desktop/stack/test.jpg'  #location of the image
original = cv2.imread(x, 1)
cv2.imshow('original',original)

gamma = 0.5                                   # change the value here to get different result
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("gammam image 1", adjusted)

cv2.waitKey(0)
cv2.destroyAllWindows()

Here is the original image:

Applying gamma of value 0.5 will yield:

Applying gamma of value 1.5 will yield:

Applying gamma of value 2.5 will yield:

Applying gamma of value 1.0 will yield the same image.

Code was borrowed from this link

2 of 3
5

I think you can done this with opencv. Here is my suggestion

import cv2
import numpy as np

img1 = cv2.imread('abc.jpg')
a = np.double(img1)
b = a + 15
img2 = np.uint8(b)
cv2.imshow("frame",img1)
cv2.imshow("frame2",img2)
cv2.waitKey(0)
cv2.destroyAllWindows()

Here i increased the brightness of image. If you use subtraction that will makes darker.

🌐
Hakky Handbook
book.st-hakky.com › hakky handbook › data science › gamma correction: a guide for data scientists
Gamma Correction: A Guide for Data Scientists | Hakky Handbook
1 month ago - Explains how to implement gamma correction using Python and OpenCV, highlighting RGB value ranges and clipping considerations.
🌐
YouTube
youtube.com › watch
Lecture 7 Image Gamma transformation OpenCV Python - YouTube
Image gamma transformation or power law transformation
Published: January 16, 2018
🌐
OpenCV
docs.opencv.org › 3.4.20 › d3 › dc1 › tutorial_basic_linear_transform.html
OpenCV: Changing the contrast and brightness of an image!
After \( \alpha \), \( \beta \) ... in the right. After gamma correction, the histogram is shifted to the right but the pixels in the dark regions are more shifted (see the gamma curves figure) than those in the bright regions....
🌐
GeeksforGeeks
geeksforgeeks.org › python-intensity-transformation-operations-on-images
Python | Intensity Transformation Operations on Images | GeeksforGeeks
January 4, 2023 - import cv2 import numpy as np # Open the image. img = cv2.imread('sample.jpg') # Trying 4 gamma values. for gamma in [0.1, 0.5, 1.2, 2.2]: # Apply gamma correction. gamma_corrected = np.array(255*(img / 255) ** gamma, dtype = 'uint8') # Save edited ...
🌐
Medium
medium.com › @pontus.bergmark › intro-to-image-processing-in-opencv-with-python-1c7f94af18a7
Intro to Image Processing in OpenCV with Python | by Pontus Bergmark | Medium
October 11, 2018 - The above transformation uses r ... we have different results. So the gamma correction is the process of choosing the best value for gamma to have the best output image....
Top answer
1 of 1
9

as I understand your question, you are mainly trying to detect the edges of the card? Or are you trying to separate the card completely (i.e. cut out) from the image?

Your use of gamma is simply changing apparent contrast of the entire image after you convert it to gray. OpenCV has a lot of edge and object detection routines of its own, as I am assuming you are trying to do pre-processing to help?

A CONCEPTS (Not Code) ANSWER:

SEPARATE CHANNELS

Let me point you in a different direction. If the input images are always color, consider using only one of the three RGB color channels. Here's an example:

RED CHANNEL:

GREEN CHANNEL:

BLUE CHANNEL:

Notice how much more contrast the blue channel has relative to the red channel. Depending on the image contents, you will typically find that one channel has better separation for the desired object.

If you look at the histogram:

You can see that the blue channel has the greatest distance between the peaks on the right (the desired object) and the left peak (bright spot on the table). But the red channel has everything bunched up in the middle.

As an idea, you could use peak detection/peak location/distance between peaks to programmatically determine relative contrasts in each color channel.

You can also determine which color channel has its peak the farthest from the same peak in another channel, and then SUBTRACT or use DIFFERENCE or DIVIDE the two channels (example of this in "channel math" below).


The Table Cloth

Now with the table cloth, it has a very high contrast pattern on it — white(gray) that is lighter than the ID card and green that is darker than the card. The card is mostly in between.

Using a curves tool from an image editor to provide a graphical example, you can see that clamping the lower AND upper levels to black, you can isolate the mid-ranged card.

But again, notice the histogram:

While nearly everything is clumped in the midrange values, the RED channel does have a small peak near black. Using this as a guide, we turn off the green and blue channels, and then CLAMP values below and values above the range of the card's value.

CURVES TOOL:

And then the resultant red channel only - note this is inverted to make the resulting contrast more clear:


SUMMARY

So the jist of these isolation concepts is to

  1. Examine each color channel to determine which one has best contrast. This will be looking for a peak that is most different from the other channels AND/OR looking for peaks in a channel with the widest "valley" between them.
  2. Clamp low and high values to isolate the desired object. This will use the peaks found in A, with a threshold, to determine the points to clamp and ramp into the desired image.

The problem with just using a general "gamma" adjustment is that you're going to be dragging the entire image around to change apparent contrast, when what you are really trying to do is eliminate (clamp) portions of the image that are not relevant.

While I realize this isn't exactly what you were asking, I hope it was useful nevertheless. Also, I'd suggest checking out more of the detection functions in OpenCV if you aren't already.


BONUS: FUN WITH CHANNEL MATH

This may or may not have utility for you, but multiplying, dividing, subtracting, difference, exclusion between color channels can sometimes help get rid of unwanted background objects. Take the table cloth and the pattern.

Lets MULTIPLY the GREEN and BLUE channels and get THIS:

Now lets DIVIDE by the RED channel

Now adjust the GAMMA of the RED channel to eliminate the tablecloth pattern (Gamma Adjusted to 1.57):

With this resultant image:

Which of course can have further contrast enhancement now that the tablecloth pattern is gone.