色彩分析工具开发日志
色彩分析工具的实现记录、Imatest 对比排查、已知风险和后续修正计划。
工具简介
色彩分析工具用于在浏览器本地分析 ColorChecker 24 色卡照片。用户上传图片后,工具通过 ROI 区域采样 24 个色块,计算色差、饱和度偏差、白平衡、曝光和噪声相关指标。
相关链接
实现方式、计算公式与参考值
本工具仿照 Imatest 的 Colorcheck 模块,通过计算分析上传色卡照片的对应色块,并与标准色块参考值比较,得到色差、饱和度、白平衡、曝光和噪声结果。
当前核心流程:
- 用户上传照片。
- 用户调整 ROI,使 6 x 4 网格对应 ColorChecker 24 个色块。
- 工具采样每个色块中心区域的平均 RGB。
- 将采样 RGB 转换到 Lab。
- 将采样 Lab 与标准 Lab 参考值比较。
- 输出 ΔE00、ΔC00、白平衡、曝光和噪声相关结果。
当前色差计算使用:
- ΔE00:用于衡量整体色差。
- ΔC00:用于观察色彩饱和度/色度方向的差异。
当前颜色转换链路:
sRGB -> 线性 RGB -> XYZ -> CIELAB
参考值来源于 Imatest 内置的 X-Rite default: post-Nov2014 D50 ColorChecker 图卡数据。当前项目使用 STANDARD_COLORCHECKER_LAB 作为主要参考值来源。
附件
开发日志
2026-06-23|Imatest 对比排查:曝光口径差异
修改结论
本次没有修改算法。当前结论是:网页端工具与 Imatest 的色差结果在标准参考图场景下较接近;曝光相关差异更可能来自亮度口径不一致,但这仍然是推测,需要后续通过小实验验证。
当前应优先验证的方向是:保留现有 Lab / 色差计算链路,同时为曝光相关字段新增一个更接近 Imatest Pixel 字段的 8-bit sRGB 像素亮度口径。
问题现象
网页端标准参考图结果与 Imatest summary 存在差异,尤其是曝光相关字段。
Imatest 灰阶曝光区使用 Pixel 字段,例如:
- 19 white: 241.3
- 22 neutral 5: 121.0
- 24 black: 50.0
网页端当前导出的 Y_meas 使用线性亮度乘以 255。对于中灰块,线性亮度数值会显著低于 gamma 编码像素亮度。
标准参考图场景下,网页端的 Delta-E 00 / Delta-C 00 与 Imatest summary 中对应字段接近:
| Patch | 网页端 DE00 | Imatest DE00 | 网页端 DC00 | Imatest DC00 |
|---|---|---|---|---|
| 1 dark skin | 0.2595 | 0.26 | 0.2579 | 0.26 |
| 2 light skin | 0.1746 | 0.18 | 0.1634 | 0.17 |
| 18 cyan | 3.2842 | 3.29 | 3.0750 | 3.08 |
| 24 black | 0.5047 | 0.49 | 0.4941 | 0.48 |
这些数值接近是结果事实。是否完全由四舍五入造成,仍属于推测,需要更细粒度的原始计算过程验证。
排查过程
本次对比使用了三份文件:
- Imatest 读取下载参考图的 summary CSV。
- 网页端直接读取默认参考图导出的 CSV。
- 网页端上传本地下载参考图导出的 CSV。
网页端默认参考图和网页端上传本地下载参考图的对比结果显示:
R_detected / G_detected / B_detected一致。R_ref / G_ref / B_ref一致。DE00 / DC00一致。Y_meas / Y_ref一致。- 主要差异是
SampledPixels。
本地上传参考图每个色块采样像素约为 33.5 万,网页端默认参考图每个色块采样像素约为 1.7 万。
Imatest summary 写明:
Color space: sRGBReference: X-Rite default, post-Nov2014 D50Fill factor: 0.65ROI WxH pixels: 8000, 5333
Imatest 表中 L-ideal / a*-ideal / b*-ideal 与项目 STANDARD_COLORCHECKER_LAB 基本对应。
基于以上事实,当前推测如下:
- 曝光口径不一致是主要候选原因。依据是 Imatest 使用接近 gamma 编码 8-bit 像素亮度的
Pixel字段,而网页端当前Y_meas使用线性亮度。 - ROI / canvas 缩放不是当前最强候选原因。依据是网页端默认参考图与网页端本地上传参考图在 RGB、DE00、DC00、Y 字段上保持一致。
- 参考 Lab 与色差公式目前看起来不是主要问题。依据是标准参考图场景下,网页端与 Imatest 的
Delta-E 00 / Delta-C 00接近。
这些仍然只是当前阶段的分析,不是最终定位结论。
2026-06-23|Imatest 对齐排查:CSV 口径与前端显示对齐
修改结论
本次已完成三类轻量修改:
- 曝光相关字段改为使用更接近 Imatest
Pixel字段的 8-bit sRGB 像素亮度口径。 - CSV 导出字段改为更接近 Imatest summary 的展示顺序,先展示结果,再展示参与计算的数据,最后展示辅助参考数据。
- 页面色块表中的参考 RGB 显示改为 Imatest
R-ref / G-ref / B-ref小数值,避免页面与 CSV 参考值口径不一致。
当前页面主结果仍使用项目原有的未四舍五入计算结果。Delta-E 00 / Delta-C 00 公式本身没有修改。
问题现象
网页端与 Imatest 的 Delta-E 00 / Delta-C 00 已经非常接近,但部分色块仍存在约 0.01 级别差异,例如标准参考图场景下:
| Patch | Imatest DE00 | 网页端 DE00 | 差异 |
|---|---|---|---|
| 18 cyan | 3.290 | 3.284 | -0.006 |
| 19 white | 0.470 | 0.483 | +0.013 |
| 24 black | 0.490 | 0.505 | +0.015 |
本次对比还确认:Lab 保留 2 位后再计算、保留 3 位后再计算、以及原始未四舍五入计算三种方式中,保留 3 位与原始未四舍五入结果最接近 Imatest。保留 2 位并不能解释差异。
排查过程
本次使用网页端导出的 color-analysis-result CSV 与 Imatest summary CSV 对比。
对比结果事实:
R-meas / G-meas / B-meas与 Imatest 表格在 3 位小数显示层面一致。L-meas / a*-meas / b*-meas与 Imatest 表格基本一致,典型差异约为 0.00 到 0.01。L-ideal / a*-ideal / b*-ideal与 Imatest 表格一致。- 因为输入 Lab 已基本一致,0.01 级别的
Delta-E 00 / Delta-C 00差异目前不应再优先归因于 RGB 或 Lab 输入数据。
已完成的代码事实:
pixelLuminance使用0.2126729 * R + 0.7151522 * G + 0.072175 * B,不做 sRGB 线性化,用于曝光Y19 / Y22 / Y24、CSVPixel value / Y_meas。- CSV 当前按以下顺序导出:
Pixel value、Saturation%、Delta-E 00、Delta-C 00、Delta-C 00(corr)、WB_ERR_S_HSV、L-meas / a*-meas / b*-meas、L-ideal / a*-ideal / b*-ideal、R-meas / G-meas / B-meas、R-ideal / G-ideal / B-ideal、R-ref / G-ref / B-ref。 R-ideal / G-ideal / B-ideal与R-ref / G-ref / B-ref当前写入的是本次 Imatest summary 表中的参考数据。Delta-C 00(corr)当前项目没有对应计算公式,CSV 暂时保留空列,没有伪造数据。
当前只保留以下判断:
- 0.01 级别差异是事实。
- RGB 与 Lab 输入基本一致是事实。
- 差异是否来自 CIEDE2000 / Delta-C00 公式实现细节、内部精度或 Imatest 的校正项,目前仍未定位,不能下结论。
2026-06-23|噪声与 SNR 对齐:二阶去趋势版本
修改结论
本次完成噪声与 SNR 的第一版 Imatest 对齐:
- CSV 主表继续保留色准相关结果。
- CSV 下方新增独立的
Noise / SNR for gray patches 19-24区域,输出 19-24 灰阶块的Y-SNR(dB) / R-SNR(dB) / G-SNR(dB) / B-SNR(dB)。 - 噪声计算改为先对采样区域做二维二阶趋势拟合,再使用残差标准差计算 SNR。
- 前端 SNR 模块统一显示 19-24 色块的
Y-SNR(dB)。 - CSV 和前端增加视觉噪声名称:
Omega (Total Visual Noise 1) @ L*=50。
阶段性结论:色差、曝光、CSV 口径、灰阶 SNR 与前端显示已经达到基本可用状态。后续仍可以继续优化与 Imatest 的少量差异,但当前不再属于阻塞基本功能的问题。
问题现象
初版 SNR 使用采样区域内原始像素标准差计算:
SNR(dB) = 20 * log10(signal / noise)
公式本身与 Imatest 说明一致,但实拍图中网页端的 SNR 明显低于 Imatest。对比发现主要原因是网页端直接把色块内部渐变、照明不均、局部阴影也计入 noise,导致 noise 偏大。
排查过程
查阅 Imatest 噪声资料后确认:Imatest 会对色块区域的低频趋势进行处理,再计算 noise。基于该事实,本次实现了轻量二阶去趋势:
value = a + b*x + c*y + d*x*x + e*x*y + f*y*y
noise = std(value - fittedValue)
SNR(dB) = 20 * log10(signal / noise)
实拍图 D65-300LUX-1 对比结果显示,二阶去趋势后 19-24 灰阶块 SNR 已明显接近 Imatest:
| 指标 | 平均绝对差 | 最大差 |
|---|---|---|
| Y-SNR(dB) | 0.17 dB | 0.31 dB |
| R-SNR(dB) | 0.08 dB | 0.21 dB |
| G-SNR(dB) | 0.17 dB | 0.31 dB |
| B-SNR(dB) | 0.18 dB | 0.52 dB |
对比事实:
- 二阶去趋势前,
Y-SNR(dB)最大差异约 6.73 dB。 - 二阶去趋势后,
Y-SNR(dB)最大差异约 0.31 dB。 - 这说明主要差异来自 noise 口径,而不是 SNR(dB) 公式本身。
仍需保留的限制说明:
- 当前实现是轻量拟合版本,不声称完整复刻 Imatest 所有噪声选项。
Delta-C 00(corr)当前仍未实现,CSV 保留空列。Omega (Total Visual Noise 1) @ L*=50使用项目当前视觉噪声估算逻辑,后续如需严格对齐 Imatest,需要单独继续排查。