简体   繁体   English

Python OpenCV cv2 - 将图像的亮度和对比度提高 100% 的简单方法

[英]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%.我想将现有图像的亮度和对比度更改 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?是否有允许我这样做的 function?

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: 我找不到为此的OpenCV函数,但我找到了该指南: https : //docs.opencv.org/3.4/d3/dc1/tutorial_basic_linear_transform.html它表示您可以通过以下方式调整对比度和亮度:

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: 之前我使用过Tensorflow的对比度调整功能,所以我使用了以下公式:

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: 另外,您可能希望将结果转换为int,因此最好将值切割为0到1以下的值。可以将其标准化,也可以只裁剪:

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. 如您所见,所有这些都不使用OpenCV,而是使用NumPy,所以我希望它适合您的需求。

Also you might want to read about different contrast formulas there: https://en.wikipedia.org/wiki/Contrast_(vision) 另外,您可能想在此阅读不同的对比度公式: https : //en.wikipedia.org/wiki/Contrast_(vision)

Here is one simple way using skimage rescale_intensity. 这是使用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. 您提供要成为min = 0和max = 255输出值的最小和最大输入值,并对所有图像值进行线性调整。 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): Out1(仅调整输入的最小值):

在此处输入图片说明

Out2 (adjust both the input min and max values): Out2(同时调整输入的最小值和最大值):

在此处输入图片说明

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. 这是提供bri和con参数的代码,这些参数可以在-100到100的范围内更改,但是受限制以使对比度不能反转。 Values of bri=0 and con=-100, will desaturate the image so that it will be completely mid gray. bri = 0和con = -100的值将使图像去饱和,使其完全处于中间灰色。 Values of bri=100 and con=-100 will result in a pure white image. bri = 100和con = -100的值将产生纯白色图像。 Likewise bri=-100 and con=-100 will result in a pure black image. 同样,bri = -100和con = -100将产生纯黑色图像。 So the bri and con values are like percent changes. 所以bri和con值就像百分比变化。 Thus bri=0 and con=0 is no change from the input. 因此,bri = 0和con = 0与输入没有变化。

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 . OpenCV 的官方文档有一个很棒的Python 直方图均衡教程

There are two major techniques available in OpenCV: (1) equalization (2) contrast limited equalization. OpenCV 中有两种主要技术可用:(1)均衡(2)对比度限制均衡。 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.对于这篇文章,我只会做 (1) 均衡。

Reference Images参考图像

I used the mandrill and couple reference images from USC SIPI database我使用了来自USC SIPI 数据库mandrillcouple参考图像

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

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) (左边未处理,右边均衡)

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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