如何用Python绘制可交互CIElab色彩空间并实现色差分析与可视化
Python实现交互式CIElab色彩空间可视化及色差分析
依赖库安装
打开终端执行以下命令安装所需工具库:
pip install plotly colormath numpy
完整代码实现
import numpy as np import plotly.graph_objects as go from colormath.color_objects import LabColor from colormath.color_diff import delta_e_cie76 from colormath.color_conversions import convert_color # ---------------------- 1. 色彩参数转换工具 ---------------------- def lab_to_ch(lab): """将L*a*b*转换为彩度C*和色相角h""" l, a, b = lab c = np.sqrt(a**2 + b**2) if a == 0 and b == 0: h = 0 else: h = np.degrees(np.arctan2(b, a)) h = h if h >= 0 else h + 360 return c, h def ch_to_lab(l, c, h): """将L*、C*、h转换为L*a*b*""" h_rad = np.radians(h) a = c * np.cos(h_rad) b = c * np.sin(h_rad) return (l, a, b) # ---------------------- 2. 色差计算 ---------------------- def calculate_color_diff(ref_lab, test_lab): """计算参考样与待测样的ΔE*ab色差(CIE76标准)""" ref_color = LabColor(*ref_lab) test_color = LabColor(*test_lab) return delta_e_cie76(ref_color, test_color) # ---------------------- 3. 交互式CIElab空间绘制 ---------------------- def plot_interactive_lab_space(ref_sample, test_samples): # 定义坐标轴范围 l_range = [0, 100] a_range = [-128, 127] b_range = [-128, 127] # 创建3D画布 fig = go.Figure() # 添加CIElab坐标轴参考线 # L*轴(a=0, b=0,从黑到白) fig.add_trace(go.Scatter3d( x=[0]*100, y=[0]*100, z=np.linspace(l_range[0], l_range[1], 100), mode='lines', line=dict(color='gray', width=2), name='L*轴' )) # a*轴(L=50, b=0,从绿到红) fig.add_trace(go.Scatter3d( x=np.linspace(a_range[0], a_range[1], 100), y=[0]*100, z=[50]*100, mode='lines', line=dict(color='red', width=2), name='a*轴(绿→红)' )) # b*轴(L=50, a=0,从蓝到黄) fig.add_trace(go.Scatter3d( x=[0]*100, y=np.linspace(b_range[0], b_range[1], 100), z=[50]*100, mode='lines', line=dict(color='yellow', width=2), name='b*轴(蓝→黄)' )) # 添加参考样品数据点 ref_l, ref_a, ref_b = ref_sample ref_c, ref_h = lab_to_ch(ref_sample) # 将Lab转换为RGB用于点的颜色显示 ref_rgb = convert_color(LabColor(ref_l, ref_a, ref_b), LabColor).get_rgb() ref_rgb = tuple(np.clip(np.array(ref_rgb)*255, 0, 255).astype(int)) fig.add_trace(go.Scatter3d( x=[ref_a], y=[ref_b], z=[ref_l], mode='markers+text', marker=dict(size=12, color=f'rgb{ref_rgb}'), text=f"参考样<br>L={ref_l:.1f}<br>a={ref_a:.1f}<br>b={ref_b:.1f}<br>C={ref_c:.1f}<br>h={ref_h:.0f}°", textposition='top center', name='参考样品' )) # 添加待测样品及色移连线 for idx, test_lab in enumerate(test_samples): test_l, test_a, test_b = test_lab test_c, test_h = lab_to_ch(test_lab) test_rgb = convert_color(LabColor(test_l, test_a, test_b), LabColor).get_rgb() test_rgb = tuple(np.clip(np.array(test_rgb)*255, 0, 255).astype(int)) # 计算色差 delta_e = calculate_color_diff(ref_sample, test_lab) # 添加待测样点 fig.add_trace(go.Scatter3d( x=[test_a], y=[test_b], z=[test_l], mode='markers+text', marker=dict(size=10, color=f'rgb{test_rgb}'), text=f"待测样{idx+1}<br>L={test_l:.1f}<br>a={test_a:.1f}<br>b={test_b:.1f}<br>C={test_c:.1f}<br>h={test_h:.0f}°<br>ΔE={delta_e:.2f}", textposition='top center', name=f'待测样品{idx+1}' )) # 添加色移连线(参考样→待测样) fig.add_trace(go.Scatter3d( x=[ref_a, test_a], y=[ref_b, test_b], z=[ref_l, test_l], mode='lines', line=dict(color='black', dash='dash', width=2), name=f'色移{idx+1} (ΔE={delta_e:.2f})' )) # 配置图表布局 fig.update_layout( scene=dict( xaxis_title='a*(绿→红)', yaxis_title='b*(蓝→黄)', zaxis_title='L*(黑→白)', xaxis_range=a_range, yaxis_range=b_range, zaxis_range=l_range, camera=dict(eye=dict(x=1.5, y=1.5, z=0.8)) ), title='交互式CIElab色彩空间及色差分析', showlegend=True ) # 显示交互式图表 fig.show() # ---------------------- 示例使用 ---------------------- if __name__ == '__main__': # 参考样品L*a*b*参数 reference_sample = (50, 20, 30) # 待测样品列表(可添加更多) test_samples = [ (55, 25, 35), (45, 15, 25), (50, 10, 40) ] # 生成交互式图表 plot_interactive_lab_space(reference_sample, test_samples)
代码说明
- 色彩参数转换:实现Lab与C(彩度)、h(色相角)的双向转换,适配不同参数输入场景。
- 色差计算:采用行业通用的CIE76标准计算ΔE*ab,数值越大代表色彩差异越显著。
- 交互式可视化:基于Plotly生成3D交互图表,支持旋转、缩放、悬停查看参数;每个数据点的颜色与对应Lab色彩一致,直观呈现色彩属性。
- 色移展示:用虚线连接参考样与待测样,标注ΔE值,清晰展示色彩偏移的方向和程度。
使用注意事项
- 若需添加更多待测样品,直接在
test_samples列表中补充Lab*参数组即可。 - 若使用C*、h参数输入,可通过
ch_to_lab函数转换为Lab*格式后传入。 - 支持将图表导出为HTML、PNG等格式,方便保存和分享。
内容的提问来源于stack exchange,提问作者Abhishek Kashyap
相关产品推荐
相关产品推荐

