Reputation: 19708
i want to change the both brightness and contrast of an existing image by 100%.
decoded = Image.open(BytesIO(base64.b64decode(base64Data)))
image = cv2.cvtColor(np.array(decoded), cv2.COLOR_BGR2RGB)
Is there a function that allows me to do this?
Upvotes: 2
Views: 8874
Reputation: 5835
It's a little surprising that no one has suggested histogram equalization. In this technique, you stretch the intensities to a wider range. The official docs for OpenCV have a great Python tutorial on histogram equalization.
There are two major techniques available in OpenCV: (1) equalization (2) contrast limited equalization. The second technique comes into play if your images have some regions that are locally bright and you don't want them to be washed out. For this post, I'll only do (1) equalization.
I used the mandrill
and couple
reference images from USC SIPI database
import os
import numpy as np
import cv2
imgList = ['mandrill.tiff', 'couple.tiff']
for fname in imgList:
img = cv2.imread(fname)
B, G, R = cv2.split(img)
B = cv2.equalizeHist(B)
G = cv2.equalizeHist(G)
R = cv2.equalizeHist(R)
out = cv2.merge((B,G,R))
outfile = os.path.splitext(fname)[0] + '_eq.jpg' # change fname to tack on eq
# (equalized) and change
cv2.imwrite(outfile, np.hstack((img,out))) # extension to jpg
Upvotes: 4
Reputation: 53174
Here is a very mathematical and direct way to adjust brightness and contrast as arguments. The contrast controls the slope of an equation of a straight line in a plot of output vs input values. The intercept depends upon both the brightness and the contrast. The brightness controls the pivot point for the slope of the straight line such that the brighter the desired result the higher the pivot point. Here is code that provides bri and con arguments that can be changed in the range -100 to 100, but limited so that contrast cannot be inverted. Values of bri=0 and con=-100, will desaturate the image so that it will be completely mid gray. Values of bri=100 and con=-100 will result in a pure white image. Likewise bri=-100 and con=-100 will result in a pure black image. So the bri and con values are like percent changes. Thus bri=0 and con=0 is no change from the input.
Input:
import cv2
import numpy as np
import math
# load image with alpha channel
img = cv2.imread('lena.png')
# define desired brightness and contrast change values
bri = 20
con = 20
# compute slope and intercept
diffcon = (100 - con)
if diffcon <= 0.1: con=99.9
arg = math.pi * (((con * con) / 20000) + (3 * con / 200)) / 4
slope = 1 + (math.sin(arg) / math.cos(arg))
if slope < 0: slope=0
pivot = (100 - bri) / 200
intcpbri = bri / 100
intcpcon = pivot * (1 - slope)
intercept = (intcpbri + intcpcon)
# print slope and intercept
print(slope, intercept)
# apply slope and intercept
img = img/255.0
out = slope * img + intercept
out[out>1] = 1
out[out<0] = 0
# display IN and OUT images
cv2.imshow('IN', img)
cv2.imshow('OUT', out)
cv2.waitKey(0)
cv2.destroyAllWindows()
# save output image
out = 255.0 * out
out = out.astype(int)
cv2.imwrite('lena_bc_20_20.png', out)
Upvotes: 2
Reputation: 53174
Here is one simple way using skimage rescale_intensity. You provide the min and max input values you want to become the min=0 and max=255 output values and it does a linear adjustment for all image values. Here are two examples:
Input:
import cv2
import numpy as np
import skimage.exposure
# load image with alpha channel
img = cv2.imread('lena.png')
# adjust just the input max value
out1 = skimage.exposure.rescale_intensity(img, in_range=(0,128), out_range=(0,255))
cv2.imwrite('lena_stretch_0_128.png', out1)
# adjust both the input min and max values
out2 = skimage.exposure.rescale_intensity(img, in_range=(64,192), out_range=(0,255))
cv2.imwrite('lena_stretch_64_192.png', out2)
cv2.imshow('Out1', out1)
cv2.imshow('Out2', out2)
cv2.waitKey(0)
cv2.destroyAllWindows()
Out1 (adjust just the input min value):
Out2 (adjust both the input min and max values):
Upvotes: 2
Reputation: 81
I couldn't find OpenCV function for this, but I found that guide: https://docs.opencv.org/3.4/d3/dc1/tutorial_basic_linear_transform.html It says that you can adjust contrast and brightness this way:
new_image = old_image * contrast_coeff + brightness_coeff
However, I didn't use it, because as you can notice, it doesn't make dark pixels darker and light pixels lighter simultaneously, if you want to change only contrast.
Earlier I used contrast adjustment from tensorflow, so I use formula from it:
float_image = image / 255.0 # image must be float!!
mean = np.mean(image, axis=-1) # compute mean values over each channel
new_image = (image - mean) * contrast_coeff + mean # change contrast
Also you might want to convert result to int, so it would be better to cut values under 0 and over 1. You can normalize it, or you can just clip:
new_image = np.clip(new_image, a_min=0., a_max=1.) # cut values under 0 and over 1
As you can see, all this doesn't use OpenCV, but uses NumPy, so I hope it suits your needs.
Also you might want to read about different contrast formulas there: https://en.wikipedia.org/wiki/Contrast_(vision)
Upvotes: 2