This solution is based on Paul's code. I fixed DivByZero Bug and implemented RGB to HSL. There is also HSL to RGB:
import numpy
def rgb_to_hsl_hsv(a, isHSV=True):
"""
Converts RGB image data to HSV or HSL.
:param a: 3D array. Retval of numpy.asarray(Image.open(...), int)
:param isHSV: True = HSV, False = HSL
:return: H,S,L or H,S,V array
"""
R, G, B = a.T
m = numpy.min(a, 2).T
M = numpy.max(a, 2).T
C = M - m #chroma
Cmsk = C != 0
# Hue
H = numpy.zeros(R.shape, int)
mask = (M == R) & Cmsk
H[mask] = numpy.mod(60 * (G[mask] - B[mask]) / C[mask], 360)
mask = (M == G) & Cmsk
H[mask] = (60 * (B[mask] - R[mask]) / C[mask] + 120)
mask = (M == B) & Cmsk
H[mask] = (60 * (R[mask] - G[mask]) / C[mask] + 240)
H *= 255
H /= 360 # if you prefer, leave as 0-360, but don't convert to uint8
# Saturation
S = numpy.zeros(R.shape, int)
if isHSV:
# This code is for HSV:
# Value
V = M
# Saturation
S[Cmsk] = ((255 * C[Cmsk]) / V[Cmsk])
# H, S, and V are now defined as integers 0-255
return H.swapaxes(0, 1), S.swapaxes(0, 1), V.swapaxes(0, 1)
else:
# This code is for HSL:
# Value
L = 0.5 * (M + m)
# Saturation
S[Cmsk] = ((C[Cmsk]) / (1 - numpy.absolute(2 * L[Cmsk]/255.0 - 1)))
# H, S, and L are now defined as integers 0-255
return H.swapaxes(0, 1), S.swapaxes(0, 1), L.swapaxes(0, 1)
def rgb_to_hsv(a):
return rgb_to_hsl_hsv(a, True)
def rgb_to_hsl(a):
return rgb_to_hsl_hsv(a, False)
def hsl_to_rgb(H, S, L):
"""
Converts HSL color array to RGB array
H = [0..360]
S = [0..1]
l = [0..1]
http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSL
Returns R,G,B in [0..255]
"""
C = (1 - numpy.absolute(2 * L - 1)) * S
Hp = H / 60.0
X = C * (1 - numpy.absolute(numpy.mod(Hp, 2) - 1))
# initilize with zero
R = numpy.zeros(H.shape, float)
G = numpy.zeros(H.shape, float)
B = numpy.zeros(H.shape, float)
# handle each case:
mask = (Hp >= 0) == ( Hp < 1)
R[mask] = C[mask]
G[mask] = X[mask]
mask = (Hp >= 1) == ( Hp < 2)
R[mask] = X[mask]
G[mask] = C[mask]
mask = (Hp >= 2) == ( Hp < 3)
G[mask] = C[mask]
B[mask] = X[mask]
mask = (Hp >= 3) == ( Hp < 4)
G[mask] = X[mask]
B[mask] = C[mask]
mask = (Hp >= 4) == ( Hp < 5)
R[mask] = X[mask]
B[mask] = C[mask]
mask = (Hp >= 5) == ( Hp < 6)
R[mask] = C[mask]
B[mask] = X[mask]
m = L - 0.5*C
R += m
G += m
B += m
R *=255.0
G *=255.0
B *=255.0
return R.astype(int),G.astype(int),B.astype(int)
def combineRGB(r,g,b):
"""
Combines separated R G B arrays into one array = image.
scipy.misc.imsave("rgb.png", combineRGB(R,G,B))
"""
rgb = numpy.zeros((r.shape[0],r.shape[1],3), 'uint8')
rgb[..., 0] = r
rgb[..., 1] = g
rgb[..., 2] = b
return rgb