toruのブログ

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

DaVinci Resolve を使って Apple Log の特性を調べてみた

1. 背景

  • 筆者は iPhone 15 Pro MAX を購入した
  • iPhone 15 では Blackmagic Cam App を使うことで Apple Log を使った HDR撮影が可能である
  • 筆者はウキウキでテスト撮影をしたのだが、撮影中のモニター表示は Log のままであり露出調整が困難だった
  • そこで EL Zone System [1] を参考に露出調整用の View LUT を作成しようと考えた
  • しかし残念なことに Apple Log の特性は一般公開されていないため View LUT が作成できない状況にあった
  • View LUT を作らずに撮影を行うことは困難だったため DaVinci Resolve を使って Apple Log の特性を調査することにした

2. 目的

  • Apple Log の Encode/Decode の特性を調べる
  • Apple Log の色域を調べる
  • 得られた特性を利用して撮影時の露出調整用の View LUT を作成する

3. 結論

Apple Log の Encode/Decode の特性

DaVinci Resolve を使うことで Apple Log の特性を得ることに成功した。 Apple Log 単体の Encoding Function (OETF) の特性を図1に、他の Encoding Function との比較を図2に示す。

図1. Apple Log の特性 図2. 様々な Log Encoding との比較
Apple Log の色域

DaVinci Resolve を使うことで Apple Log の色域が Rec.2020 であることが分かった。

撮影時の露出調整用の View LUT の作成

得られた Apple Log の特性を利用して露出調整用の View LUT を作成することに成功した。撮影に使用した様子を動画1 に示す。


動画1. 撮影用に EL Zone System を用いた Apple Log 用の View LUT を適用した様子

4. 結論に至るまでの経緯

4.1. 作業環境

今回、筆者が作業を行った環境は以下の通りである。

名称 Version
Python 関連 リンク先pip listの結果参照 ()
iPhone iPhone 15 Pro Max
iOS 17.0.3
Blackmagic Cam 1.1.00029

ちゃんと確認したら自前でコンパイルしたライブラリはリストに表示されてなかったですね…

4.2. Apple Log の Encoding Function の調査

実は筆者は Resolve を利用した Cmera Log の特性調査を 4年前に一度行ったことがあった。そのため今回も同様の考え方を用いて調査を行った。

trev16.hatenablog.com

おおまかな確認手順は以下の通りである。

  1. Resolve に読み込むテストパターン画像の作成
  2. Resolve を使いテストパターンに対して Apple Log の Encoding Function を適用し EXR形式で保存
  3. EXRファイルから Apple Log の Encoding Function を実現する 1DLUT を作成
  4. 1DLUT を使い Apple Log の特性をプロット
4.2.1. Resolve に読み込むテストパターン画像の作成

まず Resolve への入力となる Log2 スケールの Ramp パターン画像を作成した。 ここで Log2 スケールとは水平方向に Log2 の空間で等間隔になるスケールを意味する。

例として 0~16 までを Log2 で刻んだ結果を以下に示す(比較対象として Linearスケールも併記した)。

# Log2 Scale
[ 0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16 ]

# Linear Scale
[ 0, 2, 4, 6, 8, 10, 12, 14, 16 ]

画像の作成には以下のようなコードを使用した(別途 OpenImageIO が必要かも?)。

import numpy as np
from colour.io import write_image

def create_test_pattern_for_apple_log_encoding_analysis():
    width = 1920
    height = 1080
    ref_val = 0.18
    exp_range = 12

    def create_log2_x_scale(
            sample_num=32, ref_val=1.0, min_exposure=-6.5, max_exposure=6.5):
        x_min = np.log2(ref_val * (2 ** min_exposure))
        x_max = np.log2(ref_val * (2 ** max_exposure))
        x = np.linspace(x_min, x_max, sample_num)
        return 2.0 ** x

    def h_mono_line_to_img(line, height):
        return line.reshape(1, -1, 1).repeat(3, axis=2).repeat(height, axis=0)

    x = create_log2_x_scale(
        sample_num=width, ref_val=ref_val,
        min_exposure=-exp_range, max_exposure=exp_range)
    img = h_mono_line_to_img(x, height)
    fname = f"./img/src_log2_-{exp_range}_to_{exp_range}_stops.exr"
    print(fname)
    write_image(img, fname)
4.2.2. Resolve を使いテストパターンに対して Apple Log の Encoding Function を適用し EXR形式で保存

生成した画像は前述のコードを見ればわかるように Linear データである。これを Resolve を使って Apple Log に変換した。 Resolve の Color Management 設定を図3 の通りに設定し、Apple Log に変換して EXR 形式で出力した (図4)。

図3. Color Management の設定 図4. 出力設定
4.2.3. EXRファイルから Apple Log の Encoding Function を実現する 1DLUT を作成

Resolve から出力された画像は Log2 スケール上の Linear データを Apple Log で Encode したデータ列 である。 そのため、このデータ列は Shaper を適用済みの 1DLUT とみなすことができる。

ということで、今回は このデータ列を Apple Log の Encoding function を得るための 1DLUT として利用した。 具体的には以下のようなコードを準備して Apple Log の Encoding function を実現した。

import numpy as np
from colour.utilities import tstack
from colour.io import read_image

def save_apple_log_as_1dlut():
    resolve_out_exr= "./secret/apple_log_encode_out.exr"
    img = read_image(resolve_out_exr)
    width = img.shape[1]
    ref_val = 0.18
    exp_range = 12

    x = create_log2_x_scale(
        sample_num=width, ref_val=ref_val,
        min_exposure=-exp_range, max_exposure=exp_range)
    y = img[0, ..., 1]  # extract horizontal green line data 
    lut = tstack([x, y])
    np.save("./secret/apple_log_encode_lut.npy", lut)

def log_encoding_apple_log(x):
    """
    Scence linear to Apple Log.

    Parameters
    ----------
    x : ndarray
        Scene linear light (1.0 is SDR diffuse white)

    Examples
    --------
    >>> log_encoding_apple_log(0.18)
    0.488271418052

    Note
    ----
    Valid range of `x` is from 2^-12 to 2^12
    """
    lut_1d = np.load("./secret/apple_log_encode_lut.npy")
    y = np.interp(x, xp=lut_1d[..., 0], fp=lut_1d[..., 1])

    return y

簡単に説明すると log_encoding_apple_log をコールすると save_apple_log_as_1dlut にて作成した 1DLUT を参照し、 np.interp を使って LUT から Apple Log の値を得る仕組みになっている。

以上により Apple Log の Encoding Function を得ることができた。

4.2.4. 1DLUT を使い Apple Log の特性をプロット

作成した log_encoding_apple_log を使い、以下のようなコードを用いて特性をプロットした。 結果は冒頭の図1、図2 を参照…なのだが見やすいように以下にも再掲しておく。

import matplotlib.pyplot as plt

def plot_apple_log_for_blog():
    x = create_log2_x_scale(
            sample_num=32, ref_val=0.18,
            min_exposure=-12, max_exposure=12)
    apple_log = log_encoding_apple_log(x)
    x_plot = x / 0.18  # To set 18% grey to 0.0 on a Log2 scale
    fig = plt.figure(figsize=(10, 6))
    ax = fig.add_subplot(111)
    ax.set_xscale('log', base=2)
    ax.plot(x_plot, apple_log, '-o')
    plt.show()


図1 (再掲) Apple Log の特性 図2 (再掲) 様々な Log Encoding との比較

図を見ると、Apple Log は S-Log3 や LogC4 などのシネマカメラで使用される Camera Log と比較すると 収録可能なダイナミックレンジが狭いことがわかる (携帯用デバイスの Log なので実運用上は全く問題はないだろうが)。

4.3. Apple Log の Decoding Function の調査

Encoding Function の逆の作業を行っただけなので省略。

4.4. Apple Log の色域の調査

Apple Log の色域に関しても Resolve を使うことで簡単に調べることができた。 色々とやり方はあるのだが、ここでは Video Scope にある CIE Chromaticity を使った確認方法を紹介する。

やり方は非常に簡単で、Color Management 設定で Output color space に Apple Log を指定した状態で Video Scope を CIE Chromaticity に変更するだけである。すると現在の Output color space の色域が右上に表示される (図5 の② を参照)

図5. CIE Chromaticity を使って色域を確認している様子

ということで Apple Log の色域は Rec.2020 であることが分かった。

4.5. Apple Log 用の撮影補助用 View LUT の作成

ここまでの内容により Apple Log の特性を理解することができた。ここから Apple Log 用の View LUT 作成の話をしていく。

4.5.1. そもそも View LUT が必要になった理由について

初めに View LUT が必要となった理由を簡単に述べておく。

iPhone 15 Pro で動作する Blackmagic Cam App は Color Space に「Apple Log - HDR」を指定した場合、以下の図6 のような表示となる。 これは SDRモードで表示している iPhone のディスプレイに Apple Log が表示される形となっており、 自分のような素人にとっては露出調整が極めて困難であった。

図6. Apple Log が SDRレンジにマッピングされて表示される様子

一応、Blackmagic Cam App には標準でフォルスカラー表示も用意されていたのだが、 Apple Log の Code Value の 0~100% に対して色付けをする仕様となっており、やはり自分のような素人には扱いが困難であった。

そこで今回は EL Zone System を利用した View LUT を自作して適用することにした。

4.5.2. EL Zone System の概要および本記事での実装方針

ここで EL Zone System について補足説明しておく。EL Zone System は Webページ を見ると分かるように Linear値の 18% Gray を基準したフォルスカラー表示を行う技術である。 そのため Log Encoding の特性に依らず、HLG でも S-Log3 でも LogC4 でも一貫したフォルスカラー表示が可能となる素晴らしい技術である。

当然、Apple Log に関しても Decoding Function の特性が分かっていれば利用可能である。 しかし EL Zone System は詳細仕様が公開されていないため、今回は筆者の独自解釈による実装を行うことにした (そのため作成した View LUT は非公開とする)。

4.5.3. View LUT の作成および動作確認

ということで、以下で EL Zone System を用いた View LUT の生成方法および動作確認の方法について述べていく。

View LUT は 65x65x65 の 3DLUT として作成した。アルゴリズムの説明は非常に簡単なので省略する。 生成用のサンプルコードは リンク先に掲載した。興味のある方は確認して頂きたい。

続いて作成した View LUT の動作確認を行った。 動作確認用に「水平方向に Log2 スケールで増加する Scene Linear Light」を「Apple Log で Encode」したテストパターンを作成し、 Resolve 上でテストパターンに View LUT を適用して 18% Grey基準のフォルスカラー表示となるか確認した。

テストパターンの生成コードを以下に、テストパターンの様子を図7に、Resolve上で View LUT を適用した結果を図8 に示す。

def create_tp_for_verify_el_zone_system_lut_apple_log():
    width = 1920
    height = 1080
    num_of_sample = width
    ref_val = 0.18
    exp_range = 8
    x = create_log2_x_scale(
        sample_num=num_of_sample, ref_val=ref_val,
        min_exposure=-exp_range, max_exposure=exp_range)
    y = log_encoding_apple_log(x)
    img = h_mono_line_to_img(y, height)
    fname = "./img/src_apple_log_log2_"
    fname += f"-{exp_range}_to_{exp_range}_stops.exr"
    print(fname)
    write_image(img, fname)


図7. テストパターンの見た目 図8. テストパターンに View LUT を適用した様子

今回、このテストパターンは 18% Grey 基準で -8 stops ~ +8 stops のレンジで作成した。 そのため EL Zone System の黒色~白色までの 17色が等間隔で表示されれば良い (-0.5, 0.0, +0.5 stops は 1/2 の間隔)。

右端が白色 (Over Exposed) にならずに 16色表示となってしまっているが、 これは 図1 を見ればわかるように Apple Log が +6 Stops までのレンジしかないことが原因である。よって問題ではない。

よって図8 の結果から View LUT は狙い通りに作成できたと判断した。

作成した View LUT は iPhone 15 Pro にコピーを行い、Blackmagic Cam で読み込んで View LUT として使用した。 実際に適用している様子が冒頭の動画である。こちらの動画も以下に再掲しておく。


動画1. 撮影用に EL Zone System を用いた Apple Log 用の View LUT を適用した様子

4.6. ソースコード

確認に使用したソースコード一式は以下にある。例によって筆者の環境でないと正常に動作しないと思われるが、参考データとして提供する。

github.com

5. 感想

筆者の知的好奇心は満たされた。満足した。

次は Gain Map HDR について調査してまとめる予定である(スペクトルの勉強はどうした?センサーも買ったのに全然使ってないぞ??)。

6. 参考資料

[1] Cinecam Inc. "EL Zone System", https://www.elzonesystem.com/