Using Python PIL, I'm trying to adjust the hue of a given image.
I'm not very comfortable with the jargon of graphics, so what I mean by “adjusting hue” is doing the Photoshop operation called “Hue/saturation”: this is to change the color of the image uniformly as shown below:
- Original:
- With hue adjusted to +180 (red):
- With hue adjusted to -78 (green):
FYI, Photoshop uses a scale of -180 to +180 for this hue setting (where -180 equals +180), that may represents the HSL hue scale (expressed in 0-360 degree).
What I'm looking for is a function that, given an PIL image and a float hue within [0, 1] (or int within [0, 360], it doesn't matter), returns the image with its hue shifted by hue as in the example above.
What I've done so far is ridiculous and obviously doesn't give the desired result. It just half-blend my original image with a color-filled layer.
import Image
im = Image.open('tweeter.png')
layer = Image.new('RGB', im.size, 'red') # "hue" selection is done by choosing a color...
output = Image.blend(im, layer, 0.5)
output.save('output.png', 'PNG')
(Please-don't-laugh-at-) result:
Thanks in advance!
Solution: here is the unutbu code updated so it fits exactly what I've described.
import Image
import numpy as np
import colorsys
rgb_to_hsv = np.vectorize(colorsys.rgb_to_hsv)
hsv_to_rgb = np.vectorize(colorsys.hsv_to_rgb)
def shift_hue(arr, hout):
r, g, b, a = np.rollaxis(arr, axis=-1)
h, s, v = rgb_to_hsv(r, g, b)
h = hout
r, g, b = hsv_to_rgb(h, s, v)
arr = np.dstack((r, g, b, a))
return arr
def colorize(image, hue):
"""
Colorize PIL image `original` with the given
`hue` (hue within 0-360); returns another PIL image.
"""
img = image.convert('RGBA')
arr = np.array(np.asarray(img).astype('float'))
new_img = Image.fromarray(shift_hue(arr, hue/360.).astype('uint8'), 'RGBA')
return new_img
h = hout
withh = (h + hout) % 1
– Matthew Wu