diff --git a/batchColorDE.py b/batchColorDE.py new file mode 100644 index 0000000..01d0b5c --- /dev/null +++ b/batchColorDE.py @@ -0,0 +1,126 @@ +''' + batchColorDE.py + Batch calculates CIE76 DeltaE values from RGB values in csv files. I plan to add a + CIE2000 DeltaE implementation in the future. + by Nayan Sawyer + started Jan 19 2022 + version 1.0.0 Jan 22 2022 + + This is an implementation of the math on http://brucelindbloom.com for comparing + a large number of RGB pairs using the CIE76 standard. All credit for the math goes to + Bruce Lindbbloom and the Commission Internationale de l'Eclairage which defines the + standards. + + This program is fairly straight forward to use, however it does not sanitize the csv + that you point it towards, so it is important to double check your files before use. + The csv format to use is three integer RGB values seperated with commas, and a return + character at the end of the line. This is the format output by google sheets when you + export to csv. Like so + + 162,101,45 + 197,136,109 + 221,221,217 + 185,115,8 + 187,145,20 + + The first RGB group on line 1 of the csv of the sample data set will be compared to + the first RGB group on line 1 of the csv of the reference data set. + + {0} - There is only one page + {1} In the RGBtoLab() function, the variable names in the XYZ to Lab section match the + variable names used on http://brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html + to make the code implementation more legible. +''' +import numpy as np + +def RGBtoLab(colorArray): + # To convert RGB to XYZ a conversion matrix is required. + # This one is for sRGB and is based on the D65 reference white. + # For more information see above {0} + RGBtoXYZ_D65_matrix = np.array([[0.4124564,0.3575761,0.1804375], + [0.2126729,0.7151522,0.0721750], + [0.0193339,0.1191920,0.9503041]]) + + ''' + Scale RGB to pref for matrix multiplication + ''' + # Scale RGB values between 0 and 1 + colorArray = colorArray / 255 + + # Inverse sRGB companding + colorArray = np.where((colorArray <= 0.04045) & (colorArray > 0.04045), colorArray / 12.92, ((colorArray + 0.055)/1.055) ** 2.4) + + + ''' + Matrix multiplication to produce XYZ format + ''' + # Requires transposition because the color triads are row wise, not column wise in the csv format. + # This turns the tall, 3 wide matrix into a wide, 3 tall matrix so that the multiplication can take place, + # then transposes it back for the later steps. + colorArray = np.transpose(np.matmul(RGBtoXYZ_D65_matrix, np.transpose(colorArray))) + #print("XYZ\n" + str(colorArray)) + + + ''' + Convert XYZ to Lab using D65 reference white {1} + ''' + # Ref white in XYZ (D65) + Xr = 0.950470 + Yr = 1.0 + Zr = 1.088830 + + e = 0.008856 + k = 903.3 + + # Get xr yr zr + for i in range(len(colorArray)): + colorArray[i][0] = colorArray[i][0] / Xr + colorArray[i][1] = colorArray[i][1] / Yr + colorArray[i][2] = colorArray[i][2] / Zr + + # get fx fy fz + colorArray = np.where((colorArray > e), colorArray ** (1/3), (k * colorArray + 16) / 116) + + # get Lab + for i in range(len(colorArray)): + fx = colorArray[i][0] + fy = colorArray[i][1] + fz = colorArray[i][2] + colorArray[i][0] = (116 * fy) - 16 + colorArray[i][1] = 500 * (fx - fy) + colorArray[i][2] = 200 * (fy - fz) + + #print("\nLab\n" + str(colorArray)) + + return(colorArray) + +def CIE76DeltaE(sample, reference): + out = [] + for i in range(len(sample)): + out.append(((sample[i][0] - reference[i][0]) ** 2 + (sample[i][1] - reference[i][1]) ** 2 + (sample[i][2] - reference[i][2]) ** 2) ** (1/2)) + return out + + +''' +PROGRAM START +''' +verbose = True # Print extra information + +# Digest csv +sample = np.genfromtxt(".\\demo_sample.csv",delimiter=',') +key = np.genfromtxt(".\\demo_key.csv",delimiter=',') + +if verbose: print("sample\n" + str(sample)) +if verbose: print("key\n" + str(key)) + +# Covert to Lab color space +sample = RGBtoLab(sample) +key = RGBtoLab(key) + +if verbose: print("\nLab sample\n" + str(sample)) +if verbose: print("Lab key\n" + str(key)) + +# Output the DeltaE for each pair +print("\nDeltaE") +for i in CIE76DeltaE(key,sample): + print(i) \ No newline at end of file diff --git a/demo_key.csv b/demo_key.csv new file mode 100644 index 0000000..41e08c6 --- /dev/null +++ b/demo_key.csv @@ -0,0 +1,16 @@ +165,124,126 +175,147,176 +184,176,193 +173,154,144 +172,165,152 +171,139,144 +181,168,198 +148,139,183 +181,174,191 +187,178,195 +194,185,204 +189,182,196 +174,161,177 +158,103,69 +124,80,24 +40,66,106 \ No newline at end of file diff --git a/demo_sample.csv b/demo_sample.csv new file mode 100644 index 0000000..fb5b832 --- /dev/null +++ b/demo_sample.csv @@ -0,0 +1,16 @@ +162,101,45 +197,136,109 +221,221,217 +185,115,8 +187,145,20 +171,111,46 +215,155,170 +144,94,140 +202,186,171 +209,203,200 +210,202,199 +107,198,199 +209,199,202 +151,59,26 +153,103,5 +22,48,40 \ No newline at end of file diff --git a/matrix.csv b/matrix.csv new file mode 100644 index 0000000..d3d4a73 --- /dev/null +++ b/matrix.csv @@ -0,0 +1,3 @@ +0.4124564,0.3575761,0.1804375 +0.2126729,0.7151522,0.0721750 +0.0193339,0.1191920,0.9503041 \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..c9299a3 --- /dev/null +++ b/readme.md @@ -0,0 +1,27 @@ +# Batch Color DeltaE CIE76 +## CIE2000 support planned for future + +This is an implementation of the math on http://brucelindbloom.com for comparing + a large number of RGB pairs using the CIE76 standard. All credit for the math goes to + Bruce Lindbbloom and the Commission Internationale de l'Eclairage which defines the + standards. + +This program is fairly straight forward to use, however it does not sanitize the csv + that you point it towards, so it is important to double check your files before use. + The csv format to use is three integer RGB values seperated with commas, and a return + character at the end of the line. This is the format output by google sheets when you + export to csv. Like so + + 162,101,45 + 197,136,109 + 221,221,217 + 185,115,8 + 187,145,20 + +The first RGB group on line 1 of the csv of the sample data set will be compared to + the first RGB group on line 1 of the csv of the reference data set. + + {0} - There is only one page + {} In the RGBtoLab() function, the variable names in the XYZ to Lab section match the + variable names used on http://brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html + to make the code implementation more legible.