使用须知

感谢大家试用 HDR Conversion 并提出很多宝贵的反馈意见。

在使用各种代码库的时候,最痛苦的事莫过于“黑箱”和不一致,尤其是在面对 HDR 这种新兴的,较为复杂的图像格式时,用不同的库可能得到不同的数值结果。

为此,以 Google 开源的 libultrahdr 1.4.0 版本为基准,我对 HDR Conversion 0.1.5 版本进行了一些测试,并找到了一些待改进的方向和思考。

使用的三个样本是:

  • A: 手机 V 拍摄的 JPG,包含一个 1/4 分辨率的 Gainmap,色彩空间为 Display P3。
  • B: Adobe Lightroom 导出的 HDR JPEG,包含全分辨率的 Gainmap,色彩空间为 sRGB。
  • C: 手机 H 拍摄的 JPG,包含一个 1/4 分辨率的 Gainmap,Baseline 空间为 Display P3,Alternate 空间为 BT.2020。

元数据读取

Gainmap 的元数据是该 HDR 格式重要的组成部分。HDR Conversion 目前的行为如下:

  • 在读取 ISO 21496-1 时参考的是标准文件的数据结构,直接解析二进制数据得到的。在二进制中,一些浮点类型的元数据是以分子和分母的形式存放的,HDR Conversion 在读取时会将其转换为浮点数。
  • 在读取 UltraHDR 时,使用的是 xml.etree.ElementTree 解析 XML 部分。
ultrahdr_app -m 1 -P

三个样本的元数据读取结果如下(最大误差):

样本maxContentBoostminContentBoostgammaoffsethdrCapacityMax
A2.91e-62.12e-7002.91e-6
B2.27e-64.69e-7003.31e-6
C3.29e-70003.31e-6

误差可能来自 libultrahdr probe 的小数打印截断。可以认为 HDR Conversion 的元数据读取是可靠的。

读取 JPEG

ISO 21496-1 或 UltraHDR 包含至少两个 JPEG 图像:Baseline 和 Gainmap。HDR Conversion 目前使用的是 Pillow 读取 JPEG 图像。

在 libultrahdr 中,先输出原始的 YCbCr 平面,之后应用 BT.601 系数转换到 RGB。在测试中,部分像素出现了一个码值的差异,可能来源于整数舍入时的误差。尝试用 imagecodecs 读取 JPEG,结果与 Pillow 相同。

这一个码值的差异经过 Gainmap 应用过程后,在线性 RGB 上可能会带来最大约 0.034 的绝对差异。由解码 JPEG 带来的误差将不会被后续优化,完全依赖解码器实现。

Gainmap 使用

读取到两个图像和元数据后,HDR Conversion 会按照 ISO 21496-1 标准应用它们。主要包含以下几步:

  • 将 Baseline 图像从 JPEG 解码的整数码值转换为线性 RGB。
  • 将 Gainmap 重采样到 Baseline 的分辨率。
  • 如果颜色空间不一致,按照元数据中的标识转换其中一个。
  • 将 Gainmap 应用到 Baseline 图像,得到 HDR 线性图像。

HDR Conversion 目前的行为如下:

  • 线性化:如果有 ICC,按照 ICC 中的 TRC 进行线性化;如果没有 ICC,按照 sRGB EOTF 进行线性化。
  • 重采样:使用 opencv 提供的 Lanczos4。
  • 颜色空间转换:读取 ICC,构建 RGB 到 RGB 的转换矩阵进行转换。
  • Gainmap 应用:按照 ISO 21496-1 标准公式应用 Gainmap。

三个样本的在线性 RGB 上的绝对偏差如下,libultrahdr 输出为 linear RGBA half-float raw:

样本maxmeanmedianp99diff > 0.1
A1.79260.0027800.0001610.046540.3396%
B0.033920.0009330.0006330.0038760%
C0.55640.0043440.0011200.049420.1461%

差异来源按照影响大小排序如下:

  • Gainmap 重采样:无需重采样的样本 B 差异显著小于需要重采样的样本 A/C。在 libultrahdr 中,Gainmap 重采样使用的是 Shepard IDW,而 HDR Conversion 使用的是 Lanczos4。Lanczos4 在局部边缘可能会出现过冲,导致局部差异较大。
  • sRGB EOTF:HDR Conversion 使用了参数化的 sRGB EOTF,而 libultrahdr 使用了一个 1D LUT,可能存在部分差异。
  • ICC CMS:HDR Conversion 目前包括一个简单的 ICC 解析器,能够处理任意符合要求的 ICC 文件,并根据其实际情况进行颜色空间转换。libultrahdr 将颜色空间分为 BT.709 / Display-P3 / BT.2100 三类,并使用内置矩阵进行转换。

针对重采样的问题,HDR Conversion 已在 develop 分支中引入了手动实现的 Shepard IDW 插值方法,和可选的其它重采样算法。使用样本 A 测试结果如下:

resize methodmaxmeanmedianp99p99.9diff > 0.1
Shepard IDW1.02030.0010520.0001040.017560.059210.0293%
Lanczos41.79260.0027800.0001610.046540.217320.3396%

更加接近 libultrahdr 的结果,如果 ISO 21496-1 未来确定了重采样算法,HDR Conversion 将会默认使用。

关于 EOTF 和 CMS 导致的差异,我认为 HDR Conversion 的方案更适合科研和开发使用,也更贴合 ISO 21496-1 的定义。

关于 CICP

在 Gainmap JPEG 的 ICC 中,时常能发现一些 CICP tag,除了一些在标准中明确说明的,目前还不清楚它们的具体作用。

如果需要 Baseline 和 Alternate 使用不同的颜色空间,Gainmap 中的 ICC 需要包含 CICP Tag 来指示颜色空间。

CICP Tag 中的传递函数似乎不会起到作用,因为 Gainmap 的线性化使用的是 Gainmap metadata 而不是 ICC。有部分图片的 Gainmap ICC 中无 TRC 字段,在 CICP 中指定了 PQ 或者 HLG,但不清楚其作用。