mirror of
https://github.com/opus-tango/batch-color-deltaE.git
synced 2026-03-19 19:52:49 +00:00
126 lines
4.1 KiB
Python
126 lines
4.1 KiB
Python
'''
|
|
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) |