I have a sequence of images. I need to average brightness of these images.
First example (very slow):
img = cv2.imread(\'test.jpg\')
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
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)
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()
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.
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()
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