使用须知

感谢大家试用 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,但不清楚其作用。