Is there any way to manipulate an image using a color curve in python?
Question:
I have a series of tif images and was wondering if there is a possibility to write something in python (using maybe scikit-image or OpenCV) to apply a color curve. The data I have looks like the following, where we have a list of x, y, x, y… data like so: (0, 0, 32, 22, 64, 56, 128, 128, 192, 196, 255, 255).
Answers:
In the comments, some already gave answers on how to apply a color LUT to an image. However when I read your question, I have the impression that you would like to have in fact a 2D colormap, where the color depends on two parameters. If this is the case, I would recommend to visit this post or this one.
Hope this helps!
With the new information you provided I think that the following code should do the trick. lut_in
is the vector of input gray levels and lut_out
the desired output level. Here it’s applied for all 3 channels (like in photoshop). The only thing you need is the interpolation to have a LUT (look up table) of 256 elements, that fits the 256 gray levels of the input. You can apply the same method for other color resolutions.
import cv2
import numpy as np
image = cv2.imread('apple.jpg')
lut_in = [0, 127, 255]
lut_out = [0, 80, 255]
lut_8u = np.interp(np.arange(0, 256), lut_in, lut_out).astype(np.uint8)
image_contrasted = cv2.LUT(image, lut_8u)
cv2.imwrite('apple_dark.jpg', image_contrasted)
Here’s a way to do this with python PIL instead of OpenCV just in case anyone stumbles upon this answer as I did and doesn’t want to use OpenCV.
import numpy as np
from PIL import Image
im = Image.open("apple.png").convert("RGBA")
lut_x = [0, 127, 180, 255]
lut_y = [5, 80, 90, 255]
lut_u8 = np.interp(np.arange(0, 256), lut_x, lut_y).astype(np.uint8)
R, G, B, A = [0, 1, 2, 3]
source = im.split()
out = []
for band in [R, G, B]:
out.append(source[band].point(lut_u8))
out.append(source[A]) # Dont use LUT on the alpha band
merged_img = Image.merge('RGBA', out)
merged_img.show()
I have a series of tif images and was wondering if there is a possibility to write something in python (using maybe scikit-image or OpenCV) to apply a color curve. The data I have looks like the following, where we have a list of x, y, x, y… data like so: (0, 0, 32, 22, 64, 56, 128, 128, 192, 196, 255, 255).
In the comments, some already gave answers on how to apply a color LUT to an image. However when I read your question, I have the impression that you would like to have in fact a 2D colormap, where the color depends on two parameters. If this is the case, I would recommend to visit this post or this one.
Hope this helps!
With the new information you provided I think that the following code should do the trick. lut_in
is the vector of input gray levels and lut_out
the desired output level. Here it’s applied for all 3 channels (like in photoshop). The only thing you need is the interpolation to have a LUT (look up table) of 256 elements, that fits the 256 gray levels of the input. You can apply the same method for other color resolutions.
import cv2
import numpy as np
image = cv2.imread('apple.jpg')
lut_in = [0, 127, 255]
lut_out = [0, 80, 255]
lut_8u = np.interp(np.arange(0, 256), lut_in, lut_out).astype(np.uint8)
image_contrasted = cv2.LUT(image, lut_8u)
cv2.imwrite('apple_dark.jpg', image_contrasted)
Here’s a way to do this with python PIL instead of OpenCV just in case anyone stumbles upon this answer as I did and doesn’t want to use OpenCV.
import numpy as np
from PIL import Image
im = Image.open("apple.png").convert("RGBA")
lut_x = [0, 127, 180, 255]
lut_y = [5, 80, 90, 255]
lut_u8 = np.interp(np.arange(0, 256), lut_x, lut_y).astype(np.uint8)
R, G, B, A = [0, 1, 2, 3]
source = im.split()
out = []
for band in [R, G, B]:
out.append(source[band].point(lut_u8))
out.append(source[A]) # Dont use LUT on the alpha band
merged_img = Image.merge('RGBA', out)
merged_img.show()