簡體   English   中英

如何使用 python + OpenCV 快速改變圖像亮度?

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

我有一系列圖像。 我需要平均這些圖像的亮度。

第一個例子(很慢):

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)

第二個例子(快速)

hsv += value

這個例子非常快,但它改變了所有值 HSV(我只需要改變 V(亮度))

我知道這個問題有點老了,但我想我可能會發布對我有用的完整解決方案(通過在 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

這可以按如下方式使用:

frame = increase_brightness(frame, value=20)

其他答案建議使用各種 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

迭代整個圖像以進行更改在 opencv 中不是一個非常可擴展的選項,Opencv 提供了很多方法和函數來對給定圖像執行算術運算。

您可以簡單地將轉換后的 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)

這是我增加和減少亮度的解決方案。 其他幾個答案有一些錯誤問題。 函數采用正值或負值並改變亮度。

代碼中的示例

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

被調用的函數

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)

這里 alpha & beta 是輸入參數。 輸入圖像的每個像素都會根據這個公式發生變化。

 alpha(pixel_value) + beta.

較低的 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()

希望這對某人有用

@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()

降低亮度

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()

可能太舊了,但我使用對我有用的 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 最后使用 saturate_cast 以避免任何溢出。 我不使用 Python,上面是 C++,但我希望它可以在 Python 中輕松轉換,希望對您有所幫助

您可以使用此功能使用 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)

之后,您需要通過使用cv2.createTrackbar()創建軌跡欄來調用函數,並使用適當的參數調用上述函數。 為了映射范圍從 -255 到 +255 和對比度值 -127 到 +127 的亮度值,您可以使用map()函數。 您可以在此處查看有關 python 實現的完整詳細信息。

我知道這不應該那么難,並且可以調整圖像的亮度。 此外,已經有很多很好的答案。 我想增強@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 通道為 uint8 類型,色調值范圍為 [0, 179]。 因此,當與大數或負數相加時,Python 會返回垃圾結果。 所以在hue通道中我們需要先改成int16類型再改回uint8類型。 在飽和度 (S) 和值 (V) 通道上,也會出現同樣的問題,因此我們需要在加減之前檢查值。

這是我對隨機色調、飽和度和值偏移的解決方案。 它基於@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)

最快的?

對於原始速度,只需將正整數或負整數添加到原始 BGR 圖像可能是最快的。 但是您需要使用 OpenCV 函數來避免溢出。 convertScaleAbs是一個不錯的選擇。 我們使用來自 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))

給出(對於 100 的亮度值)

像 Photoshop

對於更像 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

定時

我為每個函數運行 1,000 次迭代計時。 令人驚訝的是,時間幾乎相同

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

OpenCV 圖像是數據類型為 numpy.uint8 的 numpy 數組。 向任何通道添加任意值的問題是很容易發生溢出。 例如,numpy.uint8(255) + numpy.uint8(1) = 0。為了避免這個問題,我們首先將我們的 BGR 圖像轉換為 HLS。 然后我們將我們的 HLS 圖像(一個 numpy.uint8 數組)轉換為 numpy.int16,我們將亮度值添加到第二個通道,將亮度通道中高於 255 的任何條目推送到 255,並將低於 0 的任何條目推送到 0 . 現在亮度通道中的所有值 v 滿足 0 <= v <=255。 此時我們可以轉換回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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM