使用 CIEDE2000 找到真正相反颜色的更好算法
Better algorithm with CIEDE2000 to find true opposite colors
使用 Python 3.7 和 colormath 模块,我在尝试找到一种颜色的完全相反颜色时获得了一些乐趣(例如,黑色 [0, 0, 0] 的相反颜色是黄色 [255, 255, 0] 的 DE 为 101.20397657762743)或试图找到色差最大的两种颜色(即“海军蓝”[0, 0, 110] 和“黄绿色”[143, 255, 0] 的 DE 为 119.4740815993416 ,来自我可能不准确的测试)。
不幸的是,我发现找到与给定颜色相反的唯一方法就是通过将给定颜色与(几乎)每个 sRGB 颜色组合(或 [0 , 0, 0] 到 [255, 255, 255]).
Python 3.7代码:
from colormath.color_objects import sRGBColor as RGBC, LabColor as LabC
from colormath.color_conversions import convert_color as cv_c
from colormath.color_diff import delta_e_cie2000 as de2k
from time import perf_counter as clock
# Example: X11's "Midnight Blue", edit as 'RGBC(r, g, b,...'
reference = RGBC(25, 25, 112, is_upscaled=1)
lab_ref = cv_c(reference, LabC)
# Set max delta
max_delta = 0
# Set estimate calculation's range inverals as factors of 255 (1, 3, 5, 15, 17, 51, 85, 255)
resolution = 17
# Estimate the opposite color
for sample_r in range(0, 256, resolution):
for sample_g in range(0, 256, resolution):
for sample_b in range(0, 256, resolution):
# Convert the sample to Lab
sample = RGBC(sample_r, sample_g, sample_b, is_upscaled=1)
lab_samp = cv_c(sample, LabC)
# Find the color difference
delta = de2k(lab_ref, lab_samp)
# Compare current delta with previous highest delta
if delta > max_delta:
# Overwrite highest delta with current delta
max_delta = delta
# Save estimate for optimization
estimate = sample.get_upscaled_value_tuple()
# Keep any 255 values from estimate, leads to 'range(255, 256)'
low_r = 0 if estimate[0] != 255 else 255
low_g = 0 if estimate[1] != 255 else 255
low_b = 0 if estimate[2] != 255 else 255
# Keep any 0 values from estimate, leads to 'range(0, 1)'
high_r = 256 if estimate[0] != 0 else 1
high_g = 256 if estimate[1] != 0 else 1
high_b = 256 if estimate[2] != 0 else 1
# Reset max delta
max_delta = 0
# Find a better opposite color from estimate
for sample_r in range(low_r, high_r):
for sample_g in range(low_g, high_g):
for sample_b in range(low_b, high_b):
# Convert the sample color to Lab
sample = RGBC(sample_r, sample_g, sample_b, is_upscaled=1)
lab_samp = cv_c(sample, LabC)
# Find the color difference
delta = de2k(lab_ref, lab_samp)
# Compare current delta with previous highest delta
if delta > max_delta:
# Overwrite highest delta with current delta
max_delta = delta
# Overwrite best opposite color with current sample
opposite = sample
# Print the reference, opposite color, and delta E
print(f'{reference.get_upscaled_value_tuple()} with {opposite.get_upscaled_value_tuple()}, {max_delta}')
# Print program time
print(clock())
# Example:
# Returns '(25, 25, 112) with (166, 255, 0), 108.95350620860522
# 2.580066949'
上面的代码将 运行 2.5 秒到大约 19 分钟(假设第二次相反的计算需要 128^3 次跳跃,returns 相同的值)到大约 2 小时 15 分钟(假设最坏的可能在我的系统 (3.00 GHz)
上,情况是 254^3 次跳跃,因为没有优化发生)
CIEDE2000 的方程可在 this site 处查看。请注意页面底部的注释。
我想知道是否有更高效的算法可以找到与给定 RGB 颜色完全相反的颜色。我希望能够在 CIEDE202X 或 CIEDE20XX 出来之前使用所述算法创建包含每种 RGB 颜色及其相反颜色的电子表格。
注意:这是我在 Whosebug 上的第一个问题
编辑 1:
创建了更好的估计优化。如果估计有一个,我不会只保留 0 或 255,我会减少限制,使它们最多与估计相差 +-32。在 3.00 GHz 上运行时间减少到最多 4 秒。
# Red channel optimization
if estimate[0] == 0 or estimate[0] == 255:
low_r = estimate[0]
high_r = estimate[0] + 1
elif estimate[0] > 32 and estimate[0] < 224:
low_r = estimate[0] - 32
high_r = estimate[0] + 32
elif estimate[0] < 33:
low_r = 0
high_r = estimate[0] + 32
else:
low_r = estimate[0] - 32
high_r = 256
# Green channel optimization
if estimate[1] == 0 or estimate[1] == 255:
low_g = estimate[1]
high_g = estimate[1] + 1
elif estimate[1] > 32 and estimate[1] < 224:
low_g = estimate[1] - 32
high_g = estimate[1] + 32
elif estimate[1] < 33:
low_g = 0
high_g = estimate[1] + 32
else:
low_g = estimate[1] - 32
high_g = 256
# Blue channel optimization
if estimate[2] == 0 or estimate[2] == 255:
low_b = estimate[2]
high_b = estimate[2] + 1
elif estimate[2] > 32 and estimate[2] < 224:
low_b = estimate[2] - 32
high_b = estimate[2] + 32
elif estimate[2] < 33:
low_b = 0
high_b = estimate[2] + 32
else:
low_b = estimate[2] - 32
high_b = 256
CIE DeltaE 2000 不适用于较大的色差,因此 [10, 20]+ 范围内的较大差异根本无法使用此准度量进行评估,您可能应该查看其他内容,例如 HyAB 色差度量: https://onlinelibrary.wiley.com/doi/abs/10.1002/col.22451 或类似的。
使用 Python 3.7 和 colormath 模块,我在尝试找到一种颜色的完全相反颜色时获得了一些乐趣(例如,黑色 [0, 0, 0] 的相反颜色是黄色 [255, 255, 0] 的 DE 为 101.20397657762743)或试图找到色差最大的两种颜色(即“海军蓝”[0, 0, 110] 和“黄绿色”[143, 255, 0] 的 DE 为 119.4740815993416 ,来自我可能不准确的测试)。
不幸的是,我发现找到与给定颜色相反的唯一方法就是通过将给定颜色与(几乎)每个 sRGB 颜色组合(或 [0 , 0, 0] 到 [255, 255, 255]).
Python 3.7代码:
from colormath.color_objects import sRGBColor as RGBC, LabColor as LabC
from colormath.color_conversions import convert_color as cv_c
from colormath.color_diff import delta_e_cie2000 as de2k
from time import perf_counter as clock
# Example: X11's "Midnight Blue", edit as 'RGBC(r, g, b,...'
reference = RGBC(25, 25, 112, is_upscaled=1)
lab_ref = cv_c(reference, LabC)
# Set max delta
max_delta = 0
# Set estimate calculation's range inverals as factors of 255 (1, 3, 5, 15, 17, 51, 85, 255)
resolution = 17
# Estimate the opposite color
for sample_r in range(0, 256, resolution):
for sample_g in range(0, 256, resolution):
for sample_b in range(0, 256, resolution):
# Convert the sample to Lab
sample = RGBC(sample_r, sample_g, sample_b, is_upscaled=1)
lab_samp = cv_c(sample, LabC)
# Find the color difference
delta = de2k(lab_ref, lab_samp)
# Compare current delta with previous highest delta
if delta > max_delta:
# Overwrite highest delta with current delta
max_delta = delta
# Save estimate for optimization
estimate = sample.get_upscaled_value_tuple()
# Keep any 255 values from estimate, leads to 'range(255, 256)'
low_r = 0 if estimate[0] != 255 else 255
low_g = 0 if estimate[1] != 255 else 255
low_b = 0 if estimate[2] != 255 else 255
# Keep any 0 values from estimate, leads to 'range(0, 1)'
high_r = 256 if estimate[0] != 0 else 1
high_g = 256 if estimate[1] != 0 else 1
high_b = 256 if estimate[2] != 0 else 1
# Reset max delta
max_delta = 0
# Find a better opposite color from estimate
for sample_r in range(low_r, high_r):
for sample_g in range(low_g, high_g):
for sample_b in range(low_b, high_b):
# Convert the sample color to Lab
sample = RGBC(sample_r, sample_g, sample_b, is_upscaled=1)
lab_samp = cv_c(sample, LabC)
# Find the color difference
delta = de2k(lab_ref, lab_samp)
# Compare current delta with previous highest delta
if delta > max_delta:
# Overwrite highest delta with current delta
max_delta = delta
# Overwrite best opposite color with current sample
opposite = sample
# Print the reference, opposite color, and delta E
print(f'{reference.get_upscaled_value_tuple()} with {opposite.get_upscaled_value_tuple()}, {max_delta}')
# Print program time
print(clock())
# Example:
# Returns '(25, 25, 112) with (166, 255, 0), 108.95350620860522
# 2.580066949'
上面的代码将 运行 2.5 秒到大约 19 分钟(假设第二次相反的计算需要 128^3 次跳跃,returns 相同的值)到大约 2 小时 15 分钟(假设最坏的可能在我的系统 (3.00 GHz)
上,情况是 254^3 次跳跃,因为没有优化发生)CIEDE2000 的方程可在 this site 处查看。请注意页面底部的注释。
我想知道是否有更高效的算法可以找到与给定 RGB 颜色完全相反的颜色。我希望能够在 CIEDE202X 或 CIEDE20XX 出来之前使用所述算法创建包含每种 RGB 颜色及其相反颜色的电子表格。
注意:这是我在 Whosebug 上的第一个问题
编辑 1: 创建了更好的估计优化。如果估计有一个,我不会只保留 0 或 255,我会减少限制,使它们最多与估计相差 +-32。在 3.00 GHz 上运行时间减少到最多 4 秒。
# Red channel optimization
if estimate[0] == 0 or estimate[0] == 255:
low_r = estimate[0]
high_r = estimate[0] + 1
elif estimate[0] > 32 and estimate[0] < 224:
low_r = estimate[0] - 32
high_r = estimate[0] + 32
elif estimate[0] < 33:
low_r = 0
high_r = estimate[0] + 32
else:
low_r = estimate[0] - 32
high_r = 256
# Green channel optimization
if estimate[1] == 0 or estimate[1] == 255:
low_g = estimate[1]
high_g = estimate[1] + 1
elif estimate[1] > 32 and estimate[1] < 224:
low_g = estimate[1] - 32
high_g = estimate[1] + 32
elif estimate[1] < 33:
low_g = 0
high_g = estimate[1] + 32
else:
low_g = estimate[1] - 32
high_g = 256
# Blue channel optimization
if estimate[2] == 0 or estimate[2] == 255:
low_b = estimate[2]
high_b = estimate[2] + 1
elif estimate[2] > 32 and estimate[2] < 224:
low_b = estimate[2] - 32
high_b = estimate[2] + 32
elif estimate[2] < 33:
low_b = 0
high_b = estimate[2] + 32
else:
low_b = estimate[2] - 32
high_b = 256
CIE DeltaE 2000 不适用于较大的色差,因此 [10, 20]+ 范围内的较大差异根本无法使用此准度量进行评估,您可能应该查看其他内容,例如 HyAB 色差度量: https://onlinelibrary.wiley.com/doi/abs/10.1002/col.22451 或类似的。