Created
August 12, 2016 10:34
-
-
Save manojpandey/f5ece715132c572c80421febebaf66ae to your computer and use it in GitHub Desktop.
RGB to CIELab color space conversion
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# RGB to Lab conversion | |
# Step 1: RGB to XYZ | |
# http://www.easyrgb.com/index.php?X=MATH&H=02#text2 | |
# Step 2: XYZ to Lab | |
# http://www.easyrgb.com/index.php?X=MATH&H=07#text7 | |
def rgb2lab(inputColor): | |
num = 0 | |
RGB = [0, 0, 0] | |
for value in inputColor: | |
value = float(value) / 255 | |
if value > 0.04045: | |
value = ((value + 0.055) / 1.055) ** 2.4 | |
else: | |
value = value / 12.92 | |
RGB[num] = value * 100 | |
num = num + 1 | |
XYZ = [0, 0, 0, ] | |
X = RGB[0] * 0.4124 + RGB[1] * 0.3576 + RGB[2] * 0.1805 | |
Y = RGB[0] * 0.2126 + RGB[1] * 0.7152 + RGB[2] * 0.0722 | |
Z = RGB[0] * 0.0193 + RGB[1] * 0.1192 + RGB[2] * 0.9505 | |
XYZ[0] = round(X, 4) | |
XYZ[1] = round(Y, 4) | |
XYZ[2] = round(Z, 4) | |
# Observer= 2°, Illuminant= D65 | |
XYZ[0] = float(XYZ[0]) / 95.047 # ref_X = 95.047 | |
XYZ[1] = float(XYZ[1]) / 100.0 # ref_Y = 100.000 | |
XYZ[2] = float(XYZ[2]) / 108.883 # ref_Z = 108.883 | |
num = 0 | |
for value in XYZ: | |
if value > 0.008856: | |
value = value ** (0.3333333333333333) | |
else: | |
value = (7.787 * value) + (16 / 116) | |
XYZ[num] = value | |
num = num + 1 | |
Lab = [0, 0, 0] | |
L = (116 * XYZ[1]) - 16 | |
a = 500 * (XYZ[0] - XYZ[1]) | |
b = 200 * (XYZ[1] - XYZ[2]) | |
Lab[0] = round(L, 4) | |
Lab[1] = round(a, 4) | |
Lab[2] = round(b, 4) | |
return Lab |
Great. Any feedback @i-make-robots? :)
Your work is appreciated and I thank you. :)
Super helpful stuff! Just used the alg and values (hard to find in a digestible way) in c#
im gonna convert it to javascript for a module im making
@JayRizuri feel free to :D Thanks!
Thanks for that! In case this helps someone, I ported to JS as follow:
function rgb2lab_normalizeRgbChannel(channel) {
channel /= 255;
return 100 * (channel > 0.04045
? Math.pow((channel + 0.055) / 1.055, 2.4)
: channel / 12.92
);
}
function rgb2lab_normalizeXyzChannel(channel) {
return (channel > 0.008856)
? Math.pow(channel, 1/3)
: (7.787 * channel) + (16 / 116);
}
function rgb2lab([r, g, b]) {
r = rgb2lab_normalizeRgbChannel(r);
g = rgb2lab_normalizeRgbChannel(g);
b = rgb2lab_normalizeRgbChannel(b);
let X = r * 0.4124 + g * 0.3576 + b * 0.1805;
let Y = r * 0.2126 + g * 0.7152 + b * 0.0722;
let Z = r * 0.0193 + g * 0.1192 + b * 0.9505;
// Observer= 2°, Illuminant= D65
X = rgb2lab_normalizeXyzChannel(X / 95.0470);
Y = rgb2lab_normalizeXyzChannel(Y / 100.0);
Z = rgb2lab_normalizeXyzChannel(Z / 108.883);
return [
(116 * Y) - 16, // L
500 * (X - Y), // a
200 * (Y - Z), // b
];
}
This is the code written in R.
I added a tiny extension, making the maximum of the RGB color value range variable instead of hard-coding it.
https://gist.github.com/TellAnAx/06ace666a92d0849d6b774de1790cc7a
rgb2lab <- function(inputColor, maxColorValue = 255){
num <- 1
RGB <- c(0, 0, 0)
for(value in inputColor){
value <- value / maxColorValue
if(value > 0.04045){
value <- ((value + 0.055) / 1.055)^2.4
} else{
value <- value / 12.92
}
RGB[num] <- value * 100
num <- num + 1
}
XYZ <- c(0, 0, 0)
X = RGB[1] * 0.4124 + RGB[2] * 0.3576 + RGB[3] * 0.1805
Y = RGB[1] * 0.2126 + RGB[2] * 0.7152 + RGB[3] * 0.0722
Z = RGB[1] * 0.0193 + RGB[2] * 0.1192 + RGB[3] * 0.9505
XYZ[1] = round(X, 4)
XYZ[2] = round(Y, 4)
XYZ[3] = round(Z, 4)
# Observer= 2°, Illuminant= D65
XYZ[1] = XYZ[1] / 95.047 # ref_X = 95.047
XYZ[2] = XYZ[2] / 100.0 # ref_Y = 100.000
XYZ[3] = XYZ[3] / 108.883 # ref_Z = 108.883
num = 1
for(value in XYZ){
if(value > 0.008856){
value = value ** (0.3333333333333333)
} else{
value = (7.787 * value) + (16 / 116)
}
XYZ[num] <- value
num <- num + 1
}
Lab <- c(0, 0, 0)
L = (116 * XYZ[2]) - 16
a = 500 * (XYZ[1] - XYZ[2])
b = 200 * (XYZ[2] - XYZ[3])
Lab[1] = round(L, 4)
Lab[2] = round(a, 4)
Lab[3] = round(b, 4)
return(Lab)
}
someome start a page on http://rosettacode.org/wiki/Rosetta_Code
Anyone have the numpy conversion for this code.. this takes too much time
This is really useful, thanks!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi! I used your RGB>LAB code as confirmation mine was working. I then used it in SLIC superpixel segmentation.