Python中基于Delta E的CIELAB颜色与基准集批量匹配问题
解决CIELAB颜色批量匹配Delta E最小基准色的问题
问题描述
现有如下CIELAB颜色数据集:
ID L a b 1 29.13 15.82 5.40 2 25.23 17.89 7.32 3 28.10 18.23 7.40 4 26.39 17.18 7.32 5 26.08 14.20 5.59 6 29.62 18.23 6.73 7 32.96 20.82 9.56
需要为每个ID对应的颜色,计算与B1至B8基准色集的Delta E(CIELAB颜色空间的欧氏距离),并匹配Delta E值最小的基准色编号,最终生成包含CS列的数据集。
尝试批量处理时出现报错:
Traceback (most recent call last): File "d:\Análises\labels_nome\Programas\import_openpyxl.py", line 27, in <module> sh['cor_carne'] = str('B') + str(DEb.index(min(DEb)) +1) File "C:\Users\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pandas\core\generic.py", line 1442, in __nonzero__ raise ValueError( ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
错误原因
- 原代码中
DEb存储的是pandas Series对象(而非单个数值),因为sh['L']等是Series,计算后每个元素都是对应所有样本的Delta E序列。 - 调用
min(DEb)时,实际是在比较Series对象的大小,pandas无法直接判断Series的布尔值,因此抛出歧义错误。 - 最终赋值逻辑错误:试图给整列赋同一个全局最小的B编号,而非每个样本对应各自的最小编号。
解决方案
方法一:利用现有函数逐行处理(简单直观)
复用你已验证可行的单个样本处理函数,通过pandas.apply逐行批量处理:
import pandas as pd def meat_color(Lab): # 基准颜色集B1-B8 benchmark = [ [61.3989, 29.7278, 19.1271], # B1 [50.1579, 44.9554, 28.1963], # B2 [42.9522, 54.1075, 38.8624], # B3 [36.6442, 60.9148, 51.0431], # B4 [31.2828, 54.7112, 45.1422], # B5 [25.2966, 47.7847, 37.7562], # B6 [19.3373, 40.9029, 29.2594], # B7 [13.0943, 33.665, 20.5282] # B8 ] # 计算当前样本与所有基准色的Delta E delta_e_list = [] for ref in benchmark: de = ((ref[0]-Lab[0])**2 + (ref[1]-Lab[1])**2 + (ref[2]-Lab[2])**2)**0.5 delta_e_list.append(de) # 返回最小Delta E对应的基准色编号 return f"B{delta_e_list.index(min(delta_e_list)) + 1}" # 加载数据 filename = "my_file.xlsx" df = pd.read_excel(filename) # 对每行的L/a/b应用函数,生成CS列 df['CS'] = df[['L', 'a', 'b']].apply(meat_color, axis=1) # 输出结果 print(df)
方法二:向量化操作(高效适合大数据集)
利用numpy广播机制批量计算所有样本与基准色的Delta E,性能比逐行循环更优:
import pandas as pd import numpy as np # 加载数据 filename = "my_file.xlsx" df = pd.read_excel(filename) # 构建基准色DataFrame,索引为B1-B8 benchmark_df = pd.DataFrame( data=[ [61.3989, 29.7278, 19.1271], [50.1579, 44.9554, 28.1963], [42.9522, 54.1075, 38.8624], [36.6442, 60.9148, 51.0431], [31.2828, 54.7112, 45.1422], [25.2966, 47.7847, 37.7562], [19.3373, 40.9029, 29.2594], [13.0943, 33.665, 20.5282] ], columns=['L', 'a', 'b'], index=[f'B{i+1}' for i in range(8)] ) # 批量计算所有样本与基准色的Delta E sample_vals = df[['L', 'a', 'b']].values benchmark_vals = benchmark_df.values delta_e_matrix = np.sqrt( np.sum((sample_vals[:, np.newaxis] - benchmark_vals)**2, axis=2) ) # 找到每行最小Delta E对应的基准色编号 df['CS'] = benchmark_df.index[delta_e_matrix.argmin(axis=1)] # 输出结果 print(df)
结果示例
运行后,数据集将新增CS列,示例输出(以你的样本数据为例):
ID L a b CS 0 1 29.13 15.82 5.40 B5 1 2 25.23 17.89 7.32 B6 2 3 28.10 18.23 7.40 B5 3 4 26.39 17.18 7.32 B6 4 5 26.08 14.20 5.59 B6 5 6 29.62 18.23 6.73 B5 6 7 32.96 20.82 9.56 B5
内容的提问来源于stack exchange,提问作者Curious G.
相关产品推荐
相关产品推荐

