import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
# 定义 BT2020 和普通显示器的三基色坐标
bt2020_primaries = np.array([[0.708, 0.292], [0.170, 0.797], [0.131, 0.046]])
display_primaries = np.array([[0.640, 0.330], [0.300, 0.600], [0.150, 0.060]])
# 定义转换损失函数
def color_loss_function(original_color, converted_color):
return np.sqrt(np.sum((original_color - converted_color) ** 2))
# 颜色空间转换函数
def color_space_conversion(color, source_primaries, target_primaries):
# 创建颜色变换矩阵
M = np.array([
[source_primaries[0][0], source_primaries[1][0], source_primaries[2][0]],
[source_primaries[0][1], source_primaries[1][1], source_primaries[2][1]],
[1.0, 1.0, 1.0]
])
M_inv = np.linalg.inv(M)
# 将颜色坐标转换为 XYZ 空间
xyz = np.dot(M_inv, [color[0], color[1], 1.0])
# 创建目标颜色变换矩阵
M_target = np.array([
[target_primaries[0][0], target_primaries[1][0], target_primaries[2][0]],
[target_primaries[0][1], target_primaries[1][1], target_primaries[2][1]],
[1.0, 1.0, 1.0]
])
# 将 XYZ 转换为目标颜色空间的坐标
converted_color = np.dot(M_target, xyz)
return converted_color[:2] # 返回 xy 坐标
# 模拟颜色转换和损失计算
original_color = np.array([0.3, 0.3]) # 示例原始颜色
converted_color = color_space_conversion(original_color, bt2020_primaries, display_primaries)
loss = color_loss_function(original_color, converted_color)
print(f"转换后的颜色: {converted_color}")
print(f"颜色转换损失: {loss}")
# 绘制 CIE1931 色彩空间(包括马蹄形曲线)
# 使用更准确的 CIE1931 数据
def generate_cie1931_data():
# 使用现成的 CIE1931 马蹄形数据,这里使用一个近似的方法
# 实际应用中,应该使用标准的 CIE1931 数据文件
# 这里使用一个简化的公式来生成马蹄形曲线(仅用于演示)
n = 1000
t = np.linspace(0, 2 * np.pi, n)
x = np.zeros(n)
y = np.zeros(n)
# 马蹄形曲线的上半部分
for i in range(n // 2):
angle = t[i]
x[i] = 0.5 * (1 + np.cos(angle))
y[i] = 0.5 * (1 + np.sin(angle))
# 马蹄形曲线的下半部分(直线)
for i in range(n // 2, n):
x[i] = (i - n // 2) / (n // 2 - 1) * 0.75 + 0.05
y[i] = 0.0
return x, y
# 使用更精确的 CIE1931 数据点生成马蹄形曲线
def generate_cie1931_standard_data():
# 使用标准的 CIE1931 xy 色度图数据(光谱轨迹和紫线)
# 这里使用一个简化的数据集,实际应用中应使用完整的数据
wavelengths = np.linspace(380, 780, 400)
x = np.array([0.0] * len(wavelengths))
y = np.array([0.0] * len(wavelengths))
# 这里应该填充实际的 CIE1931 数据
# 这个数据是示意性的,实际数据需要从标准或可靠资源获取
for i in range(len(wavelengths)):
if wavelengths[i] < 440:
x[i] = 0.38 + 0.18 * np.sin((wavelengths[i] - 440) / (400 - 440) * np.pi)
y[i] = 0.38 - 0.22 * np.cos((wavelengths[i] - 440) / (400 - 440) * np.pi)
elif wavelengths[i] < 500:
x[i] = 0.22 + 0.16 * np.cos((wavelengths[i] - 440) / (500 - 440) * np.pi)
y[i] = 0.38 - 0.16 * np.sin((wavelengths[i] - 440) / (500 - 440) * np.pi)
elif wavelengths[i] < 560:
x[i] = 0.22 - 0.16 * np.sin((wavelengths[i] - 500) / (560 - 500) * np.pi)
y[i] = 0.22 + 0.16 * np.cos((wavelengths[i] - 500) / (560 - 500) * np.pi)
elif wavelengths[i] < 620:
x[i] = 0.38 - 0.18 * np.cos((wavelengths[i] - 560) / (620 - 560) * np.pi)
y[i] = 0.22 + 0.18 * np.sin((wavelengths[i] - 560) / (620 - 560) * np.pi)
else:
x[i] = 0.38 + 0.18 * np.sin((wavelengths[i] - 620) / (780 - 620) * np.pi)
y[i] = 0.38 - 0.22 * np.cos((wavelengths[i] - 620) / (780 - 620) * np.pi)
return x, y
x, y = generate_cie1931_standard_data()
# 绘图
plt.figure(figsize=(10, 9))
plt.plot(bt2020_primaries[[0, 1, 2, 0], 0], bt2020_primaries[[0, 1, 2, 0], 1], 'orange', label='BT2020')
plt.plot(display_primaries[[0, 1, 2, 0], 0], display_primaries[[0, 1, 2, 0], 1], 'red', label='普通显示器')
plt.scatter(original_color[0], original_color[1], c='green', label='原始颜色')
plt.scatter(converted_color[0], converted_color[1], c='yellow', label='转换后的颜色')
# 绘制马蹄形曲线
plt.plot(x, y, 'black', label='CIE1931 马蹄形')
# 设置坐标轴范围和网格
plt.xlim(-0.1, 0.8)
plt.ylim(-0.1, 1.0)
plt.grid(True)
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.title('CIE1931 色彩空间和颜色转换')
plt.show()把马蹄形状改正确
最新发布