I am trying to process images and I would like to brighten the dark areas of my image. I tried Histogram Equalization, however as there are also some bright areas in the image, the result is not satisfying. This is why I am looking for a way to brighten only the dark areas of the image.
As an example, Input image is on the left and the expected result is on the right, the hair and face of the girl are brightened
ImageMagick seems to offer some possibilities to achieve this, however, I would like to do it using python
CodePudding user response:
If you want to avoid colour distortions, you could:
- convert to HSV colourspace,
- split the channels,
- bump up the V (Value) channel
- recombine the channels
- save
That might go something like this:
from PIL import Image
# Open the image
im = Image.open('hEHxh.jpg')
# Convert to HSV colourspace and split channels for ease of separate processing
H, S, V = im.convert('HSV').split()
# Increase the brightness, or Value channel
# Change 30 to 50 for bigger effect, or 10 for smaller effect
newV = V.point(lambda i: i int(30*(255-i)/255))
# Recombine channels and convert back to RGB
res = Image.merge(mode="HSV", bands=(H,S,newV)).convert('RGB')
res.save('result.jpg')
Essentially, I am changing the brightness from the black mapping to the green mapping:
Reminder to forgetful self... "you made the plot like this, Mark":
import matplotlib.pyplot as plt
import numpy as np
# Generate some straight-line data
xdata = np.arange(0,256)
# And the new mapping
ydata = xdata 30*(255-xdata)/255
# Plot
plt.plot(xdata,xdata,'.k')
plt.plot(xdata,ydata,'g^')
plt.title('Adjustment of V')
plt.xlabel('Input V')
plt.ylabel('Output V')
plt.grid(True)
plt.show()
CodePudding user response:
Here is one way to do that in Imagemagick and Python/OpenCV. Threshold the L channel of LAB colorspace using triangle method. Then brighten the whole image. Then merge the original and brightened image using the threshold as a mask.
Imagemagick:
magick girl_on_chair.jpg \
\( -clone 0 -colorspace LAB -channel 0 -separate channel \
-auto-threshold triangle -negate write thresh.png \) \
\( -clone 0 -evaluate multiply 4 \) \
swap -compose over -composite \
girl_on_chair_processed.jpg
Threshold:
Result:
Python/OpenCV:
import cv2
import numpy as np
# read image
img = cv2.imread("girl_on_chair.jpg")
# convert to LAB and extract L channel
LAB = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
L = LAB[:,:,0]
# threshold L channel with triangle method
value, thresh = cv2.threshold(L, 0, 255, cv2.THRESH_BINARY cv2.THRESH_TRIANGLE)
print(value)
# threshold with adjusted value
value = value 10
thresh = cv2.threshold(L, value, 255, cv2.THRESH_BINARY)[1]
# invert threshold and make 3 channels
thresh = 255 - thresh
thresh = cv2.merge([thresh, thresh, thresh])
gain = 3
blue = cv2.multiply(img[:,:,0], gain)
green = cv2.multiply(img[:,:,1], gain)
red = cv2.multiply(img[:,:,2], gain)
img_bright = cv2.merge([blue, green, red])
# blend original and brightened using thresh as mask
result = np.where(thresh==255, img_bright, img)
# save result
cv2.imwrite('girl_on_chair_thresh.jpg', thresh)
cv2.imwrite('girl_on_chair_brighten.jpg', result)
cv2.imshow('img', img)
cv2.imshow('L', L)
cv2.imshow('thresh', thresh)
cv2.imshow('img_bright', img_bright)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Threshold:
Result:
CodePudding user response:
Here is how you can accomplish that with just the cv2
module:
import cv2
def lighten(img, value=30):
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
v = hsv[..., 2]
v[:] = cv2.add(v, value)
return cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
img = cv2.imread("image.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
mask = cv2.threshold(gray, 175, 255, cv2.THRESH_BINARY)[1] == 0
img[mask] = lighten(img)[mask]
cv2.imshow("result", img)
cv2.waitKey(0)
Input Image and Output Image:
CodePudding user response:
An alternate way to do this in Imagemagick is to use -fx to threshold and increase brightness using the L channel of LAB or the Y channel of YCbCr or the V channel of HSV by adding a constant value where that channel is less than some threshold.
(Note: In -fx, images such asu
vary from 0 to 1 in range.)
magick girl_on_chair.jpg \
-colorspace LAB -separate \
\( -clone 0 -fx "u<0.15?u 0.15:u" \) \
-swap 0,3 delete \
-set colorspace LAB -combine -colorspace sRGB \
girl_on_chair_proc2.jpg
magick girl_on_chair.jpg \
-colorspace YCBCR -separate \
\( -clone 0 -fx "u<0.15?u 0.15:u" \) \
-swap 0,3 delete \
-set colorspace YCBCR -combine -colorspace sRGB \
girl_on_chair_proc3.jpg
magick girl_on_chair.jpg \
-colorspace HSV -separate \
\( -clone 2 -fx "u<0.15?u 0.15:u" \) \
swap delete \
-set colorspace HSV -combine -colorspace sRGB \
girl_on_chair_proc4.jpg
LAB Result:
YCbCr Result:
HSV Result:
Similar processing can be done using Python/OpenCV.