How to fast change image brightness with python + OpenCV?

前端 未结 12 689
感动是毒
感动是毒 2020-12-05 10:42

I have a sequence of images. I need to average brightness of these images.

First example (very slow):

img = cv2.imread(\'test.jpg\')         


        
相关标签:
12条回答
  • 2020-12-05 11:11

    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.

    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
    
    0 讨论(0)
  • 2020-12-05 11:11

    HSV channels are uint8 type, hue value range is [0, 179]. Therefore, when add with a large number or a negative number, Python returns a garbage result. So in hue channel we need to change to int16 type and then back to uint8 type. On saturation (S), and value (V) channels, the same problem occurs, so we need to check the value before adding or subtracting.

    Here is my solution for random hue, saturation, and value shifting. It base on @alkasm, and @bill-grates code sample.

    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)
    
    0 讨论(0)
  • 2020-12-05 11:12
    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()
    
    0 讨论(0)
  • 2020-12-05 11:12

    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.

    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. 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. You can check the full details of about python implementation here.

    0 讨论(0)
  • 2020-12-05 11:15

    Hope this is useful for someone

    @Divakar answer Python, OpenCV: Increasing image brightness without overflowing UINT8 array

    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()
    
    0 讨论(0)
  • 2020-12-05 11:15

    Might be too old but I use cv.covertTo which works for me

    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. I don't use Python and the above is in C++ but I hope it is easily convertible in Python and hope it helps

    0 讨论(0)
提交回复
热议问题