mirror of
https://github.com/opus-tango/batch-color-deltaE.git
synced 2026-03-20 03:55:21 +00:00
Initial Commit
This commit is contained in:
126
batchColorDE.py
Normal file
126
batchColorDE.py
Normal file
@@ -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)
|
||||||
16
demo_key.csv
Normal file
16
demo_key.csv
Normal file
@@ -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
|
||||||
|
16
demo_sample.csv
Normal file
16
demo_sample.csv
Normal file
@@ -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
|
||||||
|
3
matrix.csv
Normal file
3
matrix.csv
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
0.4124564,0.3575761,0.1804375
|
||||||
|
0.2126729,0.7151522,0.0721750
|
||||||
|
0.0193339,0.1191920,0.9503041
|
||||||
|
27
readme.md
Normal file
27
readme.md
Normal file
@@ -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.
|
||||||
Reference in New Issue
Block a user