toruのブログ

月1くらいで記事書きたい。

ACES の Linear to Log2 に関するメモ

目的

  • ACES の Linear to Log2 変換を理解する

背景

知的欲求を満たすため ACES2065-1 のデータに RRT+ODT を適用する 3DLUT をカスタムで作ることになった。 一般に Linear のデータに対して 3DLUT を適用する場合は、低階調の精度低下を防ぐために[1] shaper と呼ばれる 1DLUT を適用する。

OpenColorIO-Configs の aces_1.0.3 では shaper LUT の作成に ACES の "Linear to Log2", "Log2 to Linear" の CTL を利用している[2]。 この CTL はとても簡単な数式だが、In-Out の関係が筆者の予想と異なっていたので備忘録として記事を残す。

用語の定義

  • Log2空間: ACES の CTL(ACESutil.Lin_to_Log2_param.ctl) を使って変換した後の空間
    • 筆者が勝手に名付けた空間なので、この記事内でのみ有効な名称であることに注意。

結論

  • Log2空間は middleGray, minExposure, maxExposure を使い正規化された空間である
  • Linear to Log2 の変換は2段階で行われる
    1. Log2 関数で対数に変換する (変換時に middleGray0.0 となるよう調整する)。
    2. minExposure, maxExposure がそれぞれ 0.0, 1.0 になるよう正規化する。
  • minExposure, maxExposure はそれぞれ、middleGrey に対する露出を意味する。
    • 例: maxExposure = 6.0 の場合、Linear値で 0.18 * (2^6.0) = 11.52 が Log2空間の 1.0 に対応する
    • 例: minExposure = -6.0 の場合、Linear値で 0.18 * (2^6.0) = 0.0028125 が Log2空間の 0.0 に対応する
  • middleGrey = 0.18, minExposure = -6.0, maxExposure = 6.0 の例を図1に示す。

f:id:takuver4:20190620005217p:plain
図1. Linear to Log2 の例

解説

ACES の Linear to Log2 変換は以下の関数で定義されている[3]。

float lin_to_log2_32f
(
  float lin,
  float middleGrey,
  float minExposure,
  float maxExposure
)
{
  if (lin <= 0.0) return 0.0;

  float lg2 = log2(lin / middleGrey);
  float logNorm = (lg2 - minExposure)/(maxExposure - minExposure);

  if( logNorm < 0.0) logNorm = 0;

  return logNorm;
}

具体的な例を見るために lin_to_log2_32f()lg2logNorm をそれぞれプロットする。パラメータはそれぞれ以下とした。

  • lin: 2-6.5 ~ 26.5
  • middleGrey: 0.18
  • minExposure: -6.0
  • maxExposure: 6.0

図2に lg2 のプロット結果を示す。

f:id:takuver4:20190620005241p:plain
図2. lg2 のプロット

図2は横軸が Linear スケールのため大変見づらい。横軸を対数スケールに変換したものを図3に示す。

f:id:takuver4:20190620005309p:plain
図3. lg2 のプロット。横軸を対数スケールにした。

図3を見ると分かる通り、lg2 の値は単純に log2(x / middleGrey) の計算を行っただけなので、[0:1] には正規化されていない。これを minExposure, maxExposure に対応する値で [0:1] に正規化した値が logNorm である。プロット結果を図4に示す。

f:id:takuver4:20190620005333p:plain
図4. logNorm のプロット

そして logNorm に対して負の値を 0.0 でクリップしたものが Linear to Log2 変換の出力値となる。 プロットした結果は冒頭の図1で示した通りである。

感想

minExposuremaxExposuremiddleGrey に対する露出値として設定するのは良い方法だと思った。 minExposuremaxExposureを (-6.0, 6.0) や (-10.0, 10.0) のように絶対値が同一となるように設定すると、Log2空間では middleGray0.5 となるため気持ちが良い。

ACES の RRT+ODT 以外でも shaper を作る機会があれば積極的に使いたいと思った。

参考資料

[1] OpenColorIO. How to Configure ColorSpace Allocation. https://opencolorio.org/configurations/allocation_vars.html (2019/06/15確認)

[2] OpenColorIO-Configs. aces.py. https://github.com/imageworks/OpenColorIO-Configs/blob/master/aces_1.0.3/python/aces_ocio/colorspaces/aces.py (2019/06/15確認)

[3] AMPAS. ACESutil.Lin_to_Log2_param.ctl. https://github.com/ampas/aces-dev/blob/master/transforms/ctl/utilities/ACESutil.Lin_to_Log2_param.ctl (2019/06/15確認)