The following Python script allows to change the (overall) luminance of an image. This can be interesting when trying to match the luminance of several images (to their mean luminance for instance).
def change_image_luminance(image, luminance, precision=4):
"""Change the luminance of an image.
Parameters
----------
image : PIL.Image
the image to change the luminance of
luminance : float
the luminance to change the image to (value between 0 and 1)
precision : int, optional
the precision of resulting luminance (in decimals; default=4)
Returns
-------
new_image : PIL.Image
the new image with the changed luminance
"""
# Convert to HLS
pix = np.asarray(image)[:,:,:3] / 255
for x in range(pix.shape[0]):
for y in range(pix.shape[1]):
pix[x, y] = rgb_to_hls(*pix[x, y])
# Iteratively approach target luminance
mean = np.mean(pix[:,:,1])
while round(mean, precision) != round(luminence, precision):
for x in range(pix.shape[0]):
for y in range(pix.shape[1]):
new = pix[x, y, 1] + (luminance - mean)
if new > 1:
new = 1
if new < 0:
new = 0
pix[x, y, 1] = new
mean = np.mean(pix[:,:,1])
# Convert back to RGB
for x in range(pix.shape[0]):
for y in range(pix.shape[1]):
pix[x, y] = hls_to_rgb(*pix[x, y])
return Image.fromarray((pix * 255).astype(np.uint8))
Let's take the following two images:
Notice how the second image is brighter than the first one. Now let's change the luminance of both to 0.5:
from PIL import Image
change_image_luminance(Image.open("pexels-artem-beliaikin-2691478.jpg"), 0.5).save("pexels-artem-beliaikin-2691478_lum-0.5.jpg")
change_image_luminance(Image.open("pexels-porapak-apichodilok-346804.jpg"), 0.5).save("pexels-porapak-apichodilok-346804-0.5.jpg")
And now they are matched!
Please note that the actual luminence depends on the gamma curve of the monitor.