对于 Python,我还没有找到提供对比的 OpenCV 函数。正如其他人所建议的那样,有一些技术可以使用非常简单的公式自动增加对比度。
在official OpenCV docs中,建议可以使用这个方程同时应用对比度和亮度:
new_img = alpha*old_img + beta
其中 alpha 对应于对比度,而 beta 是亮度。不同的情况
alpha 1 beta 0 --> no change
0 < alpha < 1 --> lower contrast
alpha > 1 --> higher contrast
-127 < beta < +127 --> good range for brightness values
在 C/C++ 中,您可以使用 cv::Mat::convertTo 来实现这个等式,但我们无法从 Python 访问该库的那部分。要在 Python 中执行此操作,我建议使用 cv::addWeighted 函数,因为它速度很快,并且它会自动强制输出在 0 到 255 的范围内(例如,对于 24 位彩色图像,每个通道 8 位)。您也可以按照@nathancy 的建议使用convertScaleAbs。
import cv2
img = cv2.imread('input.png')
# call addWeighted function. use beta = 0 to effectively only operate one one image
out = cv2.addWeighted( img, contrast, img, 0, brightness)
output = cv2.addWeighted
上面的公式和代码写起来很快,会改变亮度和对比度。但它们产生的结果与照片编辑程序有很大不同。该答案的其余部分将产生一个结果,该结果将重现 GIMP 中的行为以及 LibreOffice 亮度和对比度。这是更多的代码行,但它给出了一个很好的结果。
对比
在the GIMP 中,对比度从-127 到+127。我调整了公式from here 以适应该范围。
f = 131*(对比度 + 127)/(127*(131-对比度))
new_image = f*(old_image - 127) + 127 = f*(old_image) + 127*(1-f)
为了弄清楚亮度,我弄清楚了亮度和级别之间的关系,并使用this levels post中的信息得出了一个解决方案。
#pseudo code
if brightness > 0
shadow = brightness
highlight = 255
else:
shadow = 0
highlight = 255 + brightness
new_img = ((highlight - shadow)/255)*old_img + shadow
Python 和 OpenCV 中的亮度和对比度
将它们放在一起并使用来自USC SIPI 的参考“山魈”图像添加:
import cv2
import numpy as np
# Open a typical 24 bit color image. For this kind of image there are
# 8 bits (0 to 255) per color channel
img = cv2.imread('mandrill.png') # mandrill reference image from USC SIPI
s = 128
img = cv2.resize(img, (s,s), 0, 0, cv2.INTER_AREA)
def apply_brightness_contrast(input_img, brightness = 0, contrast = 0):
if brightness != 0:
if brightness > 0:
shadow = brightness
highlight = 255
else:
shadow = 0
highlight = 255 + brightness
alpha_b = (highlight - shadow)/255
gamma_b = shadow
buf = cv2.addWeighted(input_img, alpha_b, input_img, 0, gamma_b)
else:
buf = input_img.copy()
if contrast != 0:
f = 131*(contrast + 127)/(127*(131-contrast))
alpha_c = f
gamma_c = 127*(1-f)
buf = cv2.addWeighted(buf, alpha_c, buf, 0, gamma_c)
return buf
font = cv2.FONT_HERSHEY_SIMPLEX
fcolor = (0,0,0)
blist = [0, -127, 127, 0, 0, 64] # list of brightness values
clist = [0, 0, 0, -64, 64, 64] # list of contrast values
out = np.zeros((s*2, s*3, 3), dtype = np.uint8)
for i, b in enumerate(blist):
c = clist[i]
print('b, c: ', b,', ',c)
row = s*int(i/3)
col = s*(i%3)
print('row, col: ', row, ', ', col)
out[row:row+s, col:col+s] = apply_brightness_contrast(img, b, c)
msg = 'b %d' % b
cv2.putText(out,msg,(col,row+s-22), font, .7, fcolor,1,cv2.LINE_AA)
msg = 'c %d' % c
cv2.putText(out,msg,(col,row+s-4), font, .7, fcolor,1,cv2.LINE_AA)
cv2.putText(out, 'OpenCV',(260,30), font, 1.0, fcolor,2,cv2.LINE_AA)
cv2.imwrite('out.png', out)
我在 GIMP 中手动处理了图像,并在 Python/OpenCV 中添加了文本标签:
注意: @UtkarshBhardwaj 建议 Python 2.x 用户必须将对比度校正计算代码转换为 float 以获得浮动结果,如下所示:
...
if contrast != 0:
f = float(131*(contrast + 127))/(127*(131-contrast))
...