简体   繁体   English

如何使用 python + OpenCV 快速改变图像亮度?

[英]How to fast change image brightness with python + OpenCV?

I have a sequence of images.我有一系列图像。 I need to average brightness of these images.我需要平均这些图像的亮度。

First example (very slow):第一个例子(很慢):

img = cv2.imread('test.jpg') #load rgb image
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) #convert it to hsv

for x in range(0, len(hsv)):
    for y in range(0, len(hsv[0])):
        hsv[x, y][2] += value

img = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
cv2.imwrite("image_processed.jpg", img)

Second example (quickly)第二个例子(快速)

hsv += value

This example very fast but it changes all values HSV (I need to change only V (brightness))这个例子非常快,但它改变了所有值 HSV(我只需要改变 V(亮度))

I know this question is a bit old, but I thought I might post the complete solution that worked for me (takes care of the overflow situation by saturating at 255):我知道这个问题有点老了,但我想我可能会发布对我有用的完整解决方案(通过在 255 处饱和来处理溢出情况):

def increase_brightness(img, value=30):
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    h, s, v = cv2.split(hsv)

    lim = 255 - value
    v[v > lim] = 255
    v[v <= lim] += value

    final_hsv = cv2.merge((h, s, v))
    img = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
    return img

This can be used as follows:这可以按如下方式使用:

frame = increase_brightness(frame, value=20)

The other answers suggest doing the saturation "by hand" using all kinds of numpy magic, but you can also use cv2.add() and let OpenCV handle that for you:其他答案建议使用各种 numpy 魔法“手动”进行饱和,但您也可以使用cv2.add()并让 OpenCV 为您处理:

import cv2
import numpy as np

image = cv2.read('image.png')
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
value = 42 #whatever value you want to add
cv2.add(hsv[:,:,2], value, hsv[:,:,2])
image = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
cv2.imwrite('out.png', image)

Slice以仅选择第三个通道,然后修改这些元素 -

hsv[:,:,2] += value

Iterating over the whole image to make changes is not a very scalable option in opencv, Opencv provides a lot of methods and functions to perform the arithmetic operations on the given image.迭代整个图像以进行更改在 opencv 中不是一个非常可扩展的选项,Opencv 提供了很多方法和函数来对给定图像执行算术运算。

You may simply split the converted HSV image in the individual channels and then process the V channel accordingly as:您可以简单地将转换后的 HSV 图像拆分到各个通道中,然后相应地处理 V 通道:

img = cv2.imread('test.jpg') #load rgb image
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) #convert it to hsv

h, s, v = cv2.split(hsv)
v += 255
final_hsv = cv2.merge((h, s, v))

img = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
cv2.imwrite("image_processed.jpg", img)

This was my solution to both increase and decrease brightness.这是我增加和减少亮度的解决方案。 Was having some error issues with a couple of the other answers.其他几个答案有一些错误问题。 Function takes in a positive or negative value and alters brightness.函数采用正值或负值并改变亮度。

example in code代码中的示例

img = cv2.imread(path_to_image)
img = change_brightness(img, value=30) #increases
img = change_brightness(img, value=-30) #decreases

function being called被调用的函数

def change_brightness(img, value=30):
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    h, s, v = cv2.split(hsv)
    v = cv2.add(v,value)
    v[v > 255] = 255
    v[v < 0] = 0
    final_hsv = cv2.merge((h, s, v))
    img = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
return img
def change_brightness(img, alpha, beta):
   return cv2.addWeighted(img, alpha, np.zeros(img.shape, img.dtype),0, beta)

Here alpha & beta are input parameters.这里 alpha & beta 是输入参数。 Each pixel of the input image will change according to this formula.输入图像的每个像素都会根据这个公式发生变化。

 alpha(pixel_value) + beta.

Lower value of alpha like 2 or 3 is good较低的 alpha 值(如 2 或 3)是好的

import cv2
import numpy as np

image = cv2.imread('image.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

increase = 100

v = image[:, :, 2]
v = np.where(v <= 255 - increase, v + increase, 255)
image[:, :, 2] = v

image = cv2.cvtColor(image, cv2.COLOR_HSV2BGR)

cv2.imshow('Brightness', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

Hope this is useful for someone希望这对某人有用

@Divakar answer Python, OpenCV: Increasing image brightness without overflowing UINT8 array @Divakar 回答Python,OpenCV:在不溢出 UINT8 数组的情况下增加图像亮度

mImage = cv2.imread('image1.jpg')

hsvImg = cv2.cvtColor(mImage,cv2.COLOR_BGR2HSV)

value = 0

vValue = hsvImg[...,2]
hsvImg[...,2] = np.where((255-vValue)<value,255,vValue+value)

plt.subplot(111), plt.imshow(cv2.cvtColor(hsvImg,cv2.COLOR_HSV2RGB))
plt.title('brightened image'), plt.xticks([]), plt.yticks([])
plt.show()

To decrease the brightness降低亮度

mImage = cv2.imread('image1.jpg')

hsvImg = cv2.cvtColor(mImage,cv2.COLOR_BGR2HSV)

# decreasing the V channel by a factor from the original
hsvImg[...,2] = hsvImg[...,2]*0.6

plt.subplot(111), plt.imshow(cv2.cvtColor(hsvImg,cv2.COLOR_HSV2RGB))
plt.title('brightened image'), plt.xticks([]), plt.yticks([])
plt.show()

Might be too old but I use cv.covertTo which works for me可能太旧了,但我使用对我有用的 cv.covertTo

Mat resultBrightImage;    
origImage.convertTo(resultBrightImage, -1, 1, percent); // Where percent = (int)(percent_val/100)*255, e.g., percent = 50 to increase brightness by 50%

convertTo uses saturate_cast at the end to avoid any overflows. convertTo 最后使用 saturate_cast 以避免任何溢出。 I don't use Python and the above is in C++ but I hope it is easily convertible in Python and hope it helps我不使用 Python,上面是 C++,但我希望它可以在 Python 中轻松转换,希望对您有所帮助

You can use this function to change your desired brightness or contrast using C++ just like the same way you do it on photoshop or other similar photo editing software.您可以使用此功能使用 C++ 更改所需的亮度或对比度,就像在 Photoshop 或其他类似的照片编辑软件上一样。

def apply_brightness_contrast(input_img, brightness = 255, contrast = 127):
    brightness = map(brightness, 0, 510, -255, 255)
    contrast = map(contrast, 0, 254, -127, 127)

    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 = float(131 * (contrast + 127)) / (127 * (131 - contrast))
        alpha_c = f
        gamma_c = 127*(1-f)

        buf = cv2.addWeighted(buf, alpha_c, buf, 0, gamma_c)

    cv2.putText(buf,'B:{},C:{}'.format(brightness,contrast),(10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
    return buf

def map(x, in_min, in_max, out_min, out_max):
    return int((x-in_min) * (out_max-out_min) / (in_max-in_min) + out_min)

After that you need to call the functions by creating trackbar using cv2.createTrackbar() and call that above functions with proper parameters as well.之后,您需要通过使用cv2.createTrackbar()创建轨迹栏来调用函数,并使用适当的参数调用上述函数。 In order to map the brightness values which ranges from -255 to +255 and contrast values -127 to +127, you can use that map() function.为了映射范围从 -255 到 +255 和对比度值 -127 到 +127 的亮度值,您可以使用map()函数。 You can check the full details of about python implementation here .您可以在此处查看有关 python 实现的完整详细信息。

I know this shouldn't be so hard and there to adjust the brightness of an image.我知道这不应该那么难,并且可以调整图像的亮度。 Also, there are already plenty of great answers.此外,已经有很多很好的答案。 I would like to enhance the answer of @BillGrates, so it works on grayscale images and with decreasing the brightness: value = -255 creates a black image whereas value = 255 a white one.我想增强@BillGrates 的答案,因此它适用于灰度图像并降低亮度: value = -255创建黑色图像,而value = 255是白色图像。

def adjust_brightness(img, value):
    num_channels = 1 if len(img.shape) < 3 else 1 if img.shape[-1] == 1 else 3
    img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) if num_channels == 1 else img
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    h, s, v = cv2.split(hsv)

    if value >= 0:
        lim = 255 - value
        v[v > lim] = 255
        v[v <= lim] += value
    else:
        value = int(-value)
        lim = 0 + value
        v[v < lim] = 0
        v[v >= lim] -= value

    final_hsv = cv2.merge((h, s, v))

    img = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) if num_channels == 1 else img
    return img

HSV channels are uint8 type, hue value range is [0, 179]. HSV 通道为 uint8 类型,色调值范围为 [0, 179]。 Therefore, when add with a large number or a negative number, Python returns a garbage result.因此,当与大数或负数相加时,Python 会返回垃圾结果。 So in hue channel we need to change to int16 type and then back to uint8 type.所以在hue通道中我们需要先改成int16类型再改回uint8类型。 On saturation (S), and value (V) channels, the same problem occurs, so we need to check the value before adding or subtracting.在饱和度 (S) 和值 (V) 通道上,也会出现同样的问题,因此我们需要在加减之前检查值。

Here is my solution for random hue, saturation, and value shifting.这是我对随机色调、饱和度和值偏移的解决方案。 It base on @alkasm , and @bill-grates code sample.它基于@alkasm@bill- grates 代码示例。

def shift_channel(c, amount):
   if amount > 0:
        lim = 255 - amount
        c[c >= lim] = 255
        c[c < lim] += amount
    elif amount < 0:
        amount = -amount
        lim = amount
        c[c <= lim] = 0
        c[c > lim] -= amount
    return c

rand_h, rand_s, rand_v = 50, 50, 50
img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(img_hsv)
# Random shift hue
shift_h = random.randint(-rand_h, rand_h)
h = ((h.astype('int16') + shift_h) % 180).astype('uint8')
# Random shift saturation
shift_s = random.randint(-rand_s, rand_s)
s = shift_channel(s, shift_s)
# Random shift value
shift_v = random.randint(-rand_v, rand_v)
v = shift_channel(v, shift_v)
shift_hsv = cv2.merge([h, s, v])
print(shift_h, shift_s, shift_v)
img_rgb = cv2.cvtColor(shift_hsv, cv2.COLOR_HSV2RGB)

Fastest?最快的?

For raw speed, just add a positive or negative integer to the original BGR image is probably the fastest.对于原始速度,只需将正整数或负整数添加到原始 BGR 图像可能是最快的。 But you'll want to use an OpenCV function to avoid overflows.但是您需要使用 OpenCV 函数来避免溢出。 convertScaleAbs is a good choice. convertScaleAbs是一个不错的选择。 We use the reference "mandrill" image from USC SIPI:我们使用来自 USC SIPI 的参考“山魈”图像:

import cv2

def fast_brightness(input_image, brightness):
    ''' input_image:  color or grayscale image
        brightness:  -255 (all black) to +255 (all white)

        returns image of same type as input_image but with
        brightness adjusted'''
    img = input_image.copy()
    cv2.convertScaleAbs(img, img, 1, brightness)
    return img

img = cv2.imread('mandrill.tiff',cv2.IMREAD_COLOR)

cv2.imwrite('output.jpg', fast_brightness(img, 100))

which gives (for brightness value of 100)给出(对于 100 的亮度值)

Like Photoshop像 Photoshop

For a brightness function more like Photoshop, The Gimp, or other image processing programs, you can use a function similar to @md-hanif-ali-sohag or the one in this answer :对于更像 Photoshop、The Gimp 或其他图像处理程序的亮度函数,您可以使用类似于@md-hanif-ali-sohag的函数或此答案中的函数:

def photoshop_brightness(input_img, brightness = 0):
    ''' input_image:  color or grayscale image
        brightness:  -127 (all black) to +127 (all white)

            returns image of same type as input_image but with
            brightness adjusted

    '''
    img = input_img.copy()
    if brightness != 0:
        if brightness > 0:
            shadow = brightness
            highlight = 255
        else:
            shadow = 0
            highlight = 255 + brightness
        alpha_b = (highlight - shadow)/255
        gamma_b = shadow

        cv2.convertScaleAbs(input_img, img, alpha_b, gamma_b)

    return img

Timing定时

I timed it for 1,000 iterations of running each function.我为每个函数运行 1,000 次迭代计时。 And surprisingly, the times are nearly identical令人惊讶的是,时间几乎相同

elapsed fast_brightness [sec]:       0.8595983982086182
elapsed photoshop_brightness [sec]:  0.8565976619720459

An OpenCV image is a numpy array of data type numpy.uint8. OpenCV 图像是数据类型为 numpy.uint8 的 numpy 数组。 The problem with adding an arbitrary value to any of the channels is that an overflow can easily occur.向任何通道添加任意值的问题是很容易发生溢出。 For example, numpy.uint8(255) + numpy.uint8(1) = 0. To avoid this problem, we first convert our BGR image to HLS.例如,numpy.uint8(255) + numpy.uint8(1) = 0。为了避免这个问题,我们首先将我们的 BGR 图像转换为 HLS。 Then we convert our HLS image (a numpy.uint8 array) to numpy.int16, we add a lightness value to the second channel, push any entries above 255 in the lightness channel down to 255, and push any entries below 0 up to 0. Now all the values v in the lightness channel satisfy 0 <= v <=255.然后我们将我们的 HLS 图像(一个 numpy.uint8 数组)转换为 numpy.int16,我们将亮度值添加到第二个通道,将亮度通道中高于 255 的任何条目推送到 255,并将低于 0 的任何条目推送到 0 . 现在亮度通道中的所有值 v 满足 0 <= v <=255。 At this point we can convert back to numpy.uint8, and then convert to BGR.此时我们可以转换回numpy.uint8,然后再转换为BGR。

import cv2 as cv
import numpy as np

# Negative values for the percentage parameter are allowed
def increase_brightness(bgr_img, percentage):
    hls_img = cv.cvtColor(bgr_img, cv.COLOR_BGR2HLS)
    value = np.int16(255*percentage/100)
    hls_arr_16bit = np.int16(hls_img)
    hls_arr_16bit[:,:,1] += value
    hls_arr_16bit[:,:,1] = np.where(hls_arr_16bit[:,:,1] <= 255, hls_arr_16bit[:,:,1], np.int16(255))
    hls_arr_16bit[:,:,1] = np.where(hls_arr_16bit[:,:,1] >= 0, hls_arr_16bit[:,:,1], np.int16(0))
    hls_img = np.uint8(hls_arr_16bit)
    brightened_bgr_img = cv.cvtColor(hls_img, cv.COLOR_HLS2BGR)
    return brightened_bgr_img

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

相关问题 如何使用 opencv python 自动调整扫描图像的对比度和亮度 - How to auto adjust contrast and brightness of a scanned Image with opencv python 在 opencv python 中获取图像的亮度和对比度 - Get brightness and contrast of an image in opencv python 是否可以使用python中的opencv将图像中的亮度调整为更暗? - Is that possible to adjust the brightness to be more darkest in the image using opencv in python? Python、OpenCV:在不溢出 UINT8 数组的情况下增加图像亮度 - Python, OpenCV: Increasing image brightness without overflowing UINT8 array 使用 OpenCV 自动调整图像亮度 - Automatically adjusting brightness of image with OpenCV 如何在opencv python中更改图像照明 - how to change image illumination in opencv python 如何使用python在opencv中通过某个标量影响某个区域的亮度? - How to affect a certain region's brightness by a certain scalar in opencv with python? 如何使用 opencv python 调整亮度、对比度和振动度? - How do I adjust brightness, contrast and vibrance with opencv python? OpenCV和Python:如何使用二进制掩码降低亮度? - OpenCV & Python: How to decrease brightness using binary mask? Python 将 3 通道 rgb 彩色图像更改为 1 通道灰色的速度有多快? - How fast in Python change 3 channel rgb color image to 1 channel gray?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM