简体   繁体   中英

Python OpenCV cv2 - Easy way to increase the brightness and contrast of an image by 100%

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?

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)

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

在此处输入图片说明

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)


在此处输入图片说明

What about Histogram Equalization?

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.

Reference Images

I used the mandrill and couple reference images from USC SIPI database

在此处输入图像描述 在此处输入图像描述

Code

Here's the code.
 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

Results

(left is unprocessed, right is equalized)

在此处输入图像描述 ![在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM