javascript - 如何使用 E-308 作为算法将 SRM 转换为 L*a*b*?
问题描述
我正在努力思考如何将 ASTM E-308 应用于啤酒的 SRM 测量。我正在工作的问题域要求我们通过转换为 L a进行从 SRM 到 RGB(或 sRGB)的体面转换 b* 进行从 SRM 到 RGB(或 sRGB)的体面转换。似乎我用来创建啤酒配方的每个网站都有自己的从 SRM 到 RGB 的转换,这是有道理的,因为这是一个棘手的问题。也就是说,我正在寻找一个开源的 js 库来解决这个问题。
基本上,我使用的是这里描述的算法:https://www.homebrewtalk.com/forum/threads/on-the-calculation-of-srm-rgb-values-in-the-srgb-color-space。 413581/#post-5232912
我相信这是 E-308 算法的简化。我遇到困难的地方是该帖子中提到的电子表格(http://wetnewf.org/pdfs/Brewing_articles/MOAWorkbook.xls)中提到的电子表格对我来说没有多大意义。该帖子说要根据电子表格中的观察者角度选择一个 XYZ 向量。如果我选择 10 度的观察角度,那么我希望 XYZ 向量应该是:(82.82, 3.48, 61.86)。这个对吗?
现在,选择光源光谱也有些混乱。如果我想要光源 C(我相信它是 6774K),我应该从该电子表格中提取哪些值来添加作为光谱的组件?此外,我如何计算这些组件?
我在色彩理论方面的背景有限,但我真正想要的是能够有一些输入标准,比如观察者角度和光源色温,以及 SRM 值,并计算 L a b*价值。
解决方案
这个问题确实需要一个可能不适合 Stack Overflow 格式的答案。
ASTM E308 本身是一个 50 页的复杂标准,其主体是关于从光谱分布到 CIE XYZ 三色值的转换。它还涉及转换为 CIE Lab 和 CIE Luv。
您链接的电子表格没有完全实现 ASTM E308,并且方便地使用积分方法进行 5 nm 测量间隔,如果光谱数据经过带通校正,则没有技术上需要的三色加权因子表。对于实际目的来说这很好,但如果需要精度,重要的是要知道 ASTM E308 非常严格。
电子表格非常复杂,因为它似乎使用了带有特征向量的增强 SRM 计算来处理一百左右的啤酒。
假设要使用ASBC 方法,流程应该如下:
- 使用以下等式计算给定 SRM 和路径长度的啤酒透射光谱分布:
- 使用 CIE 1964 10 度标准观察者和光源 C 的积分方法将光谱分布转换为 CIE XYZ 三色值
- 将 CIE XYZ 三色值转换为 CIE Lab
- 更进一步,将它们也转换为 sRGB
- 喝啤酒 :)
如果您不介意阅读 Python,我制作了一个Colab 笔记本,它使用Color并为 SRM 网格和路径长度计算啤酒颜色:
import colour
import colour.plotting
import numpy as np
colour.utilities.describe_environment()
colour.plotting.colour_style()
ASBC_SHAPE = colour.SpectralShape(380, 780, 5)
OBSERVER = colour.CMFS['CIE 1964 10 Degree Standard Observer']
ILLUMINANT = colour.ILLUMINANTS_SDS['C']
ILLUMINANT_XY = colour.ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['C']
def beer_transmission_sd(SRM, path=1, shape=ASBC_SHAPE):
e = np.exp(1)
wl = shape.range()
values = np.exp(
-(SRM / 12.7) * (0.018747 * e**(-(wl - 430) / 13.374) + 0.98226 * e**
(-(wl - 430) / 80.514)) * path)
return colour.SpectralDistribution(
values, wl, name='Beer - SRM {0} - Path {1}'.format(SRM, path))
PATHS = np.linspace(10, 1, 10)
SRM = np.linspace(1, 50, 50)
XYZ = []
for i in PATHS:
for j in SRM:
XYZ.append(
colour.sd_to_XYZ(
beer_transmission_sd(i, j),
cmfs=OBSERVER,
illuminant=ILLUMINANT) / 100.0)
# The Lab values for CIE Illuminant C are computed here:
Lab = colour.XYZ_to_Lab(XYZ, ILLUMINANT_XY)
# But we will be going further :)
RGB = colour.XYZ_to_sRGB(XYZ, illuminant=ILLUMINANT_XY)
figure, axes = colour.plotting.plot_multi_colour_swatches(
[colour.plotting.ColourSwatch(RGB=np.clip(i, 0, 1)) for i in RGB],
columns=len(SRM),
**{
'standalone': False,
'x_label': 'SRM',
'y_label': 'Path (cm)',
'xtick.bottom': True,
'ytick.left': True,
})
# Ugly ticks massaging that will not be needed in future versions.
axes.set_xticks(SRM)
axes.set_yticks(-PATHS + 2)
axes.set_yticklabels(reversed(PATHS))
colour.plotting.render(standalone=True);
请注意,通过 Flask 在后端的容器中运行 Color 并从 Javascript 调用它应该很简单。我们有一个先进的 3D 可视化器,如果您想走这条路,它会很有帮助。
推荐阅读
- nginx - 如何从虚 URL 重定向到我的实际网站?
- jenkins - OWASP 依赖检查和 Jenkins 流水线
- php - 警告:SQLite3::exec():靠近“.”:语法错误
- php - 使用 PHP/MYSQLI 进行多重登录
- java - CORS 策略不适用于特定端口。如何解决?
- vb6 - vb6中如何将水晶报表导出为excel
- c# - Double、Float 或 Decimal 的 SqlParameter
- database - 为什么我们只能通过 Tableau Public 连接(提取数据)文本和 excel 文件,而不能连接 Oracle 等数据库?
- python - model.predict 给出了 Tensorflow 错误 Inconsistent values for attr 'T' DT_INT16 vs. DT_FLOAT while building NodeDef using Op name=StridedSlice
- java - 如何遍历Java列表数组将对象键值对保存到自己的数组中