如何在Python OpenCV中增加图像的对比度

35g0bw71  于 2023-06-06  发布在  Python
关注(0)|答案(7)|浏览(548)

我是Python OpenCV的新手。我看过一些文档和答案here,但我无法弄清楚下面的代码是什么意思:

if (self.array_alpha is None):
    self.array_alpha = np.array([1.25])
    self.array_beta = np.array([-100.0])

# add a beta value to every pixel 
cv2.add(new_img, self.array_beta, new_img)                    

# multiply every pixel value by alpha
cv2.multiply(new_img, self.array_alpha, new_img)

我知道Basically, every pixel can be transformed as X = aY + b where a and b are scalars.。基本上,我已经理解了这一点。但是,我不明白的代码,以及如何增加对比度与此。
到目前为止,我已经设法简单地使用img = cv2.imread('image.jpg',0)读取图像
谢谢你的帮助

o4hqfura

o4hqfura1#

我想推荐一个使用LAB color space的方法。
LAB颜色空间表示跨三个通道的颜色变化。一个亮度通道和两个颜色通道:

  • L通道:表示图像中的亮度
  • a通道:表示红色和绿色之间的颜色变化
  • b通道:表示黄色和蓝色之间的颜色变化

在下面,我在L通道上执行自适应直方图均衡化,并将结果图像转换回BGR颜色空间。这增强了亮度,同时也限制了对比灵敏度。我使用OpenCV 3.0.0和Python完成了以下操作:

代码:

import cv2
import numpy as np

img = cv2.imread('flower.jpg', 1)
# converting to LAB color space
lab= cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
l_channel, a, b = cv2.split(lab)

# Applying CLAHE to L-channel
# feel free to try different values for the limit and grid size:
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl = clahe.apply(l_channel)

# merge the CLAHE enhanced L-channel with the a and b channel
limg = cv2.merge((cl,a,b))

# Converting image from LAB Color model to BGR color spcae
enhanced_img = cv2.cvtColor(limg, cv2.COLOR_LAB2BGR)

# Stacking the original image with the enhanced image
result = np.hstack((img, enhanced_img))
cv2.imshow('Result', result)

结果:

增强图像在右边

您可以按原样运行代码。要了解CLAHE(对比度有限自适应直方图均衡)是什么,请参阅此维基百科页面

pw136qt2

pw136qt22#

对于Python,我还没有找到一个提供对比的OpenCV函数。正如其他人所建议的,有一些技术可以使用非常简单的公式自动增加对比度。
official OpenCV docs中,建议使用此公式同时应用对比度和亮度:
new_img = alpha*old_img + 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位)。你也可以使用convertScaleAbs,就像@nathancy建议的那样。

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)
为了弄清楚亮度,我弄清楚了亮度和水平之间的关系,并使用了这个水平帖子中的信息来得出解决方案。

#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的参考“mandrill”图像添加:

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))
...
oxcyiej7

oxcyiej73#

对比度和亮度可以分别使用alpha(α)和beta(β)进行调整。这些变量通常称为 * 增益 * 和 * 偏置 * 参数。表达式可以写成

OpenCV已经将其实现为cv2.convertScaleAbs(),只需提供用户定义的alphabeta

import cv2

image = cv2.imread('1.jpg')

alpha = 1.5 # Contrast control (1.0-3.0)
beta = 0 # Brightness control (0-100)

adjusted = cv2.convertScaleAbs(image, alpha=alpha, beta=beta)

cv2.imshow('original', image)
cv2.imshow('adjusted', adjusted)
cv2.waitKey()

之前->之后

**注意:**要自动调整亮度/对比度,请查看automatic contrast and brightness adjustment of a color photo

4ioopgfo

4ioopgfo4#

这里有很多答案,从简单到复杂。我想在更简单的一面添加另一个,对于实际的对比度和亮度调整似乎更实用一点。

def adjust_contrast_brightness(img, contrast:float=1.0, brightness:int=0):
    """
    Adjusts contrast and brightness of an uint8 image.
    contrast:   (0.0,  inf) with 1.0 leaving the contrast as is
    brightness: [-255, 255] with 0 leaving the brightness as is
    """
    brightness += int(round(255*(1-contrast)/2))
    return cv2.addWeighted(img, contrast, img, 0, brightness)

我们通过addWeighted()函数进行a*x+b调整。然而,为了在不修改亮度的情况下改变对比度,数据需要以零为中心。OpenCV的默认数据类型是uint8,情况并非如此。因此,我们还需要根据分布如何移位来调整亮度。

sbdsn5lh

sbdsn5lh5#

关于X = aY + b(实际上是f(x) = ax + b)的最佳解释见https://math.stackexchange.com/a/906280/357701
一个简单的一个,通过调整亮度/亮度/亮度的对比度如下:

import cv2

img = cv2.imread('test.jpg')
cv2.imshow('test', img)
cv2.waitKey(1000)
imghsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

imghsv[:,:,2] = [[max(pixel - 25, 0) if pixel < 190 else min(pixel + 25, 255) for pixel in row] for row in imghsv[:,:,2]]
cv2.imshow('contrast', cv2.cvtColor(imghsv, cv2.COLOR_HSV2BGR))
cv2.waitKey(1000)
raw_input()
gzjq41n4

gzjq41n46#

img = cv2.imread("/x2.jpeg")

image = cv2.resize(img, (1800, 1800))

alpha=1.5
beta=20

new_image=cv2.addWeighted(image,alpha,np.zeros(image.shape, image.dtype),0,beta)

cv2.imshow("new",new_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
bjp0bcyl

bjp0bcyl7#

引用自enter link description here
我们必须计算由以下公式给出的对比度校正因子。

为了使算法正确工作,对比度校正因子(F)值必须存储为浮点数,而不是整数。公式中的C值表示所需的对比度水平。

下一步骤是执行实际的对比度调节本身。以下公式显示了对颜色的红色分量所做的对比度调整:
truncate函数仅确保红色、绿色和蓝色的新值在0和255之间的有效范围内。
对比度值将在-255至+255的范围内。负值将减少对比度的量,相反,正值将增加对比度的量。
在这里,您将对比度设置为-128(降低)和+128(增加)。

import cv2
import matplotlib.pyplot as plt

image = cv2.imread("lena.jpg")
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)

imageContrast = image.copy()
height, width, _ = image.shape

def truncate(value):
    if value < 0:
        return 0
    elif value > 255:
        return 255
    else:
        return value

def adjustContrast(pixel, contrast=0):
    b, g, r = pixel
    f = (259 * (contrast + 255)) / (255 * (259 - contrast))
    bNew = (int)(truncate(f * (b - 128) + 128))
    gNew = (int)(truncate(f * (r - 128) + 128))
    rNew = (int)(truncate(f * (r - 128) + 128))
    return bNew, gNew, rNew

clist = [-128, 128]

plt.subplot(1, len(clist) + 1, 1)
plt.title("Orjinal")
plt.imshow(image)
plt.xticks([])
plt.yticks([])

for index, contrast in enumerate(clist):
    for i in range(width):
        for j in range(height):
            _b, _g, _r = adjustContrast(image[j, i], clist[index])
            imageContrast[j, i] = [_b, _g, _r]

    plt.subplot(1, len(clist) + 1, index + 2)
    plt.title("Contrast:" + str(contrast))
    plt.imshow(imageContrast)
    plt.xticks([])
    plt.yticks([])

plt.show()

结果:

相关问题