toruのブログ

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

公式チャンネルがアップロードした「水星の魔女」の OP が 30P だった

1. 内容

昨晩、水星の魔女の OP がガンダムチャンネルにアップロードされた。 ウキウキで視聴していたところ、映像が少しカクついているように感じた。

まさかと思い YouTube の Stats for nerds にて確認したところ、フレームレートが 24P ではなく 30P になっていた。 公式チャンネルがこうしたミスをするのは珍しい(少なくとも自分は初めて見た)。

2. 動画

自分が違和感を覚えた箇所 (00:57~01:00 辺り)。

YouTube 上で 「<」や「>」キーを使ってコマ送りをすると、30P に変換された弊害で 4フレームに1フレームくらいの割合で重複フレームが入っていることが分かる。これが原因で再生時にもカクつきを知覚できてしまう。

なお、本編に付属するOP映像がカクつかないことは、dアニメストアで配信中の OP と比較して確認済み (iPhone 13 で 240P 撮影をして確認した) (※)。

※本当は TV で録画したデータで確認したかったのだが、録画データはインターレースであり、かつ TV側でどのような補間をするのか不明確だったため、プログレッシブ版である dアニメストアの配信データで確認した。

3. YouTube の Stats for nerds のスクリーンショット

4. yt-dlp.exe -F で取得した情報 [1]

ID  EXT   RESOLUTION FPS │    FILESIZE   TBR PROTO │ VCODEC          VBR ACODEC      ABR     ASR MORE INFO
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
sb2 mhtml 48x27          │                   mhtml │ images                                      storyboard
sb1 mhtml 80x45          │                   mhtml │ images                                      storyboard
sb0 mhtml 160x90         │                   mhtml │ images                                      storyboard
139 m4a   audio only     │   534.94KiB   48k https │ audio only          mp4a.40.5   48k 22050Hz low, m4a_dash
249 webm  audio only     │   561.35KiB   51k https │ audio only          opus        51k 48000Hz low, webm_dash
250 webm  audio only     │   740.42KiB   67k https │ audio only          opus        67k 48000Hz low, webm_dash
140 m4a   audio only     │     1.38MiB  129k https │ audio only          mp4a.40.2  129k 44100Hz medium, m4a_dash
251 webm  audio only     │     1.42MiB  132k https │ audio only          opus       132k 48000Hz medium, webm_dash
17  3gp   176x144      8 │   836.38KiB   76k https │ mp4v.20.3       76k mp4a.40.2    0k 22050Hz 144p
394 mp4   256x144     30 │   771.79KiB   70k https │ av01.0.00M.08   70k video only              144p, mp4_dash
160 mp4   256x144     30 │   832.92KiB   76k https │ avc1.4d400c     76k video only              144p, mp4_dash
278 webm  256x144     30 │  1011.48KiB   92k https │ vp9             92k video only              144p, webm_dash
395 mp4   426x240     30 │     1.51MiB  141k https │ av01.0.00M.08  141k video only              240p, mp4_dash
133 mp4   426x240     30 │     1.50MiB  140k https │ avc1.4d4015    140k video only              240p, mp4_dash
242 webm  426x240     30 │     1.81MiB  169k https │ vp9            169k video only              240p, webm_dash
396 mp4   640x360     30 │     2.99MiB  279k https │ av01.0.01M.08  279k video only              360p, mp4_dash
134 mp4   640x360     30 │     2.96MiB  276k https │ avc1.4d401e    276k video only              360p, mp4_dash
18  mp4   640x360     30 │     7.21MiB  674k https │ avc1.42001E    674k mp4a.40.2    0k 44100Hz 360p
243 webm  640x360     30 │     3.25MiB  304k https │ vp9            304k video only              360p, webm_dash
397 mp4   854x480     30 │     5.36MiB  501k https │ av01.0.04M.08  501k video only              480p, mp4_dash
135 mp4   854x480     30 │     4.57MiB  427k https │ avc1.4d401f    427k video only              480p, mp4_dash
244 webm  854x480     30 │     4.90MiB  458k https │ vp9            458k video only              480p, webm_dash
398 mp4   1280x720    30 │    10.21MiB  956k https │ av01.0.05M.08  956k video only              720p, mp4_dash
136 mp4   1280x720    30 │     8.53MiB  798k https │ avc1.4d401f    798k video only              720p, mp4_dash
22  mp4   1280x720    30 │ ~  10.19MiB  927k https │ avc1.64001F    927k mp4a.40.2    0k 44100Hz 720p
247 webm  1280x720    30 │     9.11MiB  852k https │ vp9            852k video only              720p, webm_dash
399 mp4   1920x1080   30 │    17.84MiB 1670k https │ av01.0.08M.08 1670k video only              1080p, mp4_dash
137 mp4   1920x1080   30 │    28.41MiB 2660k https │ avc1.640028   2660k video only              1080p, mp4_dash
248 webm  1920x1080   30 │    20.59MiB 1927k https │ vp9           1927k video only              1080p, webm_dash

5. 感想

劣化した映像が配信されるのはとても悲しい。公式チャンネルはアップロードし直して欲しい。

あれですかね、テロップ入れるときに EDIUS か何かを使ったけれど、デフォルトのプリセットが 30P で、そのまま作業を続けちゃった感じですかね。 あるいは、普段は 29.94p or 59.94i の制作を担当している方に急に仕事が割り振られてうっかりミスが発生したとか?

いずれにせよ、ガンダムチャンネルではアップロード前に品質チェックするワークフローが存在しないことが良く分かった。残念。

参考資料

[1] yt-dlp, "yt-dlp - Video Format Options", https://github.com/yt-dlp/yt-dlp#video-format-options

表示デバイスの広色域化と観測者メタメリズムの組み合わせで生じる色ズレに関するシミュレーションの実施

1. 背景

  • 表示デバイスの広色域化(以後、WCG対応と呼ぶ ※1)が進んでいる
  • WCG対応は表現可能な色が増えるため良いこと尽くめの技術に見える
  • その一方で WCG対応には「原理的に色ズレが増加してしまう」という負の側面もある
  • これは観測者メタメリズム(等色関数※2の個人差)が関係している
  • WCG対応と観測者メタメリズムの問題は10年以上前から言及されてきた内容であり、もしかすると「今頃になってそれを話題にするのか?」と思われるかもしれない
  • しかし、WCG対応した表示デバイスはここ数年で着実に増えている(TV、スマートフォン、LEDディスプレイなど)
  • こうした状況を鑑みると、改めて WCG対応と観測者メタメリズムの関係を整理するのは意義のある行為だと筆者は考えた
  • 以上の理由により、筆者は表示デバイスの WCG対応と観測者メタメリズムの組み合わせで生じる色ズレに関してシミュレーションを行うことにした

※1 WCG = Wide Color Gamut
※2 本記事では「等色関数」をグラフなどで CMFs や Color Matching Functions と表記する場合がある

2. 目的

  • WCG対応と観測者メタメリズム(等色関数の個人差)の組み合わせが原因で色ズレが増加することを検証する (※3)
    • 同一の観測者内 (intra-observer) と複数の観測者間 (inter-observer) の双方について検証する
    • 検証はシミュレーションで行う
      • 表示デバイスとして、筆者が分光分布を定めた仮想的なディスプレイ を使う (※4)
      • 生身の観測者(被験者)は用意せず、代わりに MCSL (Munsell Color Science Laboratory) にて公開されている等色関数[1] を使い仮想的な観測者を用意する

※3 偉大なる先人達が既に検証済みであり新規性が無い事は重々承知している
※4 以後、本記事では表示デバイスのことを「ディスプレイ」または「3原色ディスプレイ」と呼ぶ

3. 結論

WCG対応と観測者メタメリズムの組み合わせが原因で、同一の観測者内と複数の観測者間の双方で色ズレが増加することを確認した。

同一の観測者内の色ズレ増加の様子の例を図1に、複数の観測者間の色ズレの様子を図2に示す。 検証条件が複雑であるため、ここでは「色域が広がると色ズレが大きくなる」ことを認識して頂くだけで十分だと考えている。 詳細は後半の「6. WCG対応 と観測者メタメリズムの関係を調べるためのシミュレーション」を参照。

図1. ある観測者 (Cat.Obs. 2) においてディスプレイの WCG対応が進むにつれて色ズレが増加する様子。縦軸は真の値との誤差値 (Δxy)

11_patch_color_checker_cmfs-only_no18_display-00 11_patch_color_checker_cmfs-only_no18_display-01 11_patch_color_checker_cmfs-only_no18_display-02
(a) 各観測者と表示位置の関係 (b) BT.709 ディスプレイ (c) DCI-P3 ディスプレイ (d) BT.2020 ディスプレイ
図2. 複数の観測者間での見え方の違いを可視化したもの。10種類の観測者を対象にキャリブレーションした仮想ディスプレイを、CIE1931 測色標準観測者が見た場合の色ズレを示している。各観測者と表示位置の関係は (a) を参照。

4. 観測者メタメリズムに関係する用語の整理

筆者が行った具体的な検証内容を説明する前に、観測者メタメリズムに関して簡単に説明する。 また補足説明として現実世界で観測者メタメリズムが問題となるシーンについても軽く触れておく。

なお、本記事では以下のような基礎的な内容は省略する。

  • 人間は3原色で色を知覚すること
  • 色を定量的に扱うために心理物理量として XYZ や L*a*b* などが使われること
  • XYZ は分光分布と等色関数を使って計算すること

4.1. メタメリズム (条件等色)

始めにメタメリズムについて説明する。日本語では条件等色と呼ぶ。

メタメリズムとは分光分布の異なる2つの色刺激が「特定の観測条件」で等しい色に見えることを意味する[2]。

最も身近な例は PCモニター、TV、スマートフォンなどの3原色ディスプレイだと考える。これらのデバイスはメタメリズムを利用して任意の色を再現している。

メタメリズムの具体例を出そう。以下の 図3 は D65光源下の Color Checker の分光分布を、図4 はそれを3原色ディスプレイで再現した際の分光分布を示している 。 図3 の分光分布と図4 の分光分布は形状が全く異なるが、メタメリズムが成立しているため人間は両方を同じ色として知覚する (※5)。

※5 厳密には後述する観測者メタメリズムや照明光メタメリズムが原因で色ズレを知覚するのだが、議論が循環してしまうので一旦無視する。

図3. D65光源下の ColorChecker の分光分布 図4. 3原色ディスプレイでメタメリズムが成立する際の分光分布

4.2. 観測者メタメリズム

さて、メタメリズムは素晴らしい特性に見えるが、残念ながら様々な要因で不成立となることが分かっている。 要因の一例を以下に挙げる。

  • 観測者の等色関数
  • 物体色の分光反射率
  • 照明光の分光分布

こうした要因のうち、観測者の等色関数の個人差が要因となってメタメリズムが不成立となることを観測者メタメリズムと呼ぶ[2-4]。

具体的な例を挙げよう。図5 には分光分布が異なる 2台のディスプレイ (Display1, Display2) が並んでいる。各ディスプレイは白色のパッチを表示している(図中では分光分布の違いを表すためにパッチの上に分光分布を重ねて表示している)。

2台のディスプレイは観測者A が見た際に色が一致するように調整済みとする。即ち 2台のディスプレイは観測者A に対してメタメリズムが成立しているとする。

観測者B がこの 2台のディスプレイを見ると、多くの場合は色が一致しない。なぜならば等色関数の個人差によって観測者B が得る色刺激は観測者A とは異なるからである。別の言い方をすると観測者B に対してはメタメリズムが不成立となるからである。

(a) (b)
図5. (a) 分光特性の異なる 2台のディスプレイを観測した際、等色関数の個人差で同一の色刺激を得られない様子。(b) 観測者A と観測者B の等色関数の違いの例。

4.3.1. 観測者メタメリズムが問題となる場面の例

観測者メタメリズムは、メタメリズムを利用して色再現を行っている表示システム全般で発生する可能性がある。 筆者が最近読んだの論文[5][6] を参考に3点ほど例を挙げる。

  • 分光分布の異なる2台のディスプレイに同じ絵を表示した際に、人によって「色が合っている」、「色が異なる」などと意見がばらつく
  • ポストプロダクションにおいて、キャリブレーションしたマスターモニターを使ってカラーグレーディングを行ったが、スクリーンにプロジェクターで映像を表示すると色が異なって見える
  • 液晶ディスプレイ上で色校正を行うソフトプルーフを行った際に、印刷物と液晶ディスプレイの表示で色が合わない

なお、色がどの程度のズレるかはケースバイケースである。ただし、今後に WCG対応が進むと観測者メタメリズムが原因の色ズレが増加するのは事実である。

用語についての説明が済んだので、ここから先はディスプレイのWCG対応と観測者メタメリズムによる色ズレの関係について調査を進めていく。

5. 3原色のディスプレイが任意の色を再現する仕組みと WCG について

5.1. はじめに

さて、これからディスプレイの WCG対応と観測者メタメリズムの組み合わせに関するシミュレーションを行うのだが、 筆者がシミュレーションで行った計算の内容を理解するためには、前提知識として以下の2点を理解しておく必要がある。

  • ディスプレイが任意の色を再現する仕組み
  • WCG対応とディスプレイの分光分布の関係

そのため、この2点について説明を行う。

筆者は当初、適当な文献を引用することでディスプレイの色再現に関する説明を省略しようと考えていた。 しかし、筆者が調べたところ 3原色ディスプレイの色再現の仕組みを解説している文献は少なかった(あるいは少々難解であった)。

そういった事情もあり、今回は筆者が自分で説明することにした。参考にした資料は文献[2][7][8] である。 基本的な色彩工学の知識があれば誰でも簡単に導出できる内容だと筆者は考えている。

それでは、以下で説明を行っていく。

5.2. 自宅の液晶ディスプレイを観察

どこから説明すべきか分からなかったので、まずは自宅の液晶ディスプレイを観察することにした。 自宅の液晶ディスプレイに対して様々な RGB 値 (Linear値) を入力し、それをマクロレンズで撮影した様子を図6 に示す。

図6. 自宅の液晶ディスプレイに様々な RGB値を入力し(左側)、それをマクロレンズで撮影した様子(右側)。

図6 から以下のことが分かる。

  • R, G, B の素子が独立して存在している
  • R, G, B の素子は入力の RGB値に連動して明るさが変わる

もう少し詳しく見ていこう。次は分光分布を観察する。 秋月電子で購入した分光器 (※6) を使って分光分布を調べた結果を図7 に示す。

※6 カラーコンパス MFA (SS) 。浜松ホトニクス製の分光器モジュール C12880MA(M-12673) を使用

図7. 自宅のディスプレイの分光分布。横軸は波長 [nm]。縦軸は分光器の出力値を 0xFFFF で割って正規化した値

さて、図7 を注意深く観察すると、分光分布にピークが生じる波長[nm] は(成分が 0 でなければ)どのグラフでも同じであることが分かる(例えば Red のピークはどのグラフでも 600 nm 付近にある)。 更に注意深く観察すると、上段の R, G, B の分光分布を加算すると左下の白色の分光分布が表現できそうなこともわかる。

ここから推測を更に重ねると、中段と下段の分光分布は上段の R, G, B 単色の分光分布の線形結合で表現できそうに見える。 ということで実際に試してみる。

入力した RGB値に対する分光分布を  S_{D}(\lambda)、R, G, B 単色の分光分布を  S_{D, r}(\lambda), S_{D, g}(\lambda), S_{D, b}(\lambda) とする。

 S_{D}(\lambda) および  S_{D, r}(\lambda), S_{D, g}(\lambda), S_{D, b}(\lambda) の線形和(係数は入力の RGB値)をプロットした様子を図8 に示す。

図8.  S_{D}(\lambda) S_{D, r}(\lambda), S_{D, g}(\lambda), S_{D, b}(\lambda) の線形和(係数は入力の RGB値)をプロットした様子

図8 を見ると 3原色ディスプレイの分光分布は R, G, B 単色の分光分布の線形結合で表現できることが分かる。

以上の観察により、液晶ディスプレイへの入力(RGB値)と分光分布の関係をおおまかに理解できた。最後に得られた知見をまとめておく。

  • R, G, B の素子が独立して存在しており、個別に明るさを変えることができる
  • ディスプレイの分光分布  S_{D}(\lambda) は R, G, B 単色の分光分布を  S_{D, r}(\lambda), S_{D, g}(\lambda), S_{D, b}(\lambda) の線形結合で表現できる
  • 数式で表現すると以下の (1)式となる


 \displaystyle
S_D(\lambda) = R_D S_{D, r}(\lambda) + G_D S_{D, g}(\lambda) + B_D S_{D, b}(\lambda)
\tag{1}


ここで  R_D, G_D, B_D はディスプレイの3刺激値(ディスプレイへの入力値)を意味する (※7)。

※7 今後はディスプレイ固有の RGB値であることを明確にするため、R, G, B ではなく  R_D, G_D, B_D と表記する。

5.3. メタメリズムを利用した任意の色の再現方法

さて、ここから先は数式を使ってディスプレイが任意の色を再現する仕組みを説明する。

5.3.1. 3原色ディスプレイの  XYZ の計算

「ディスプレイが任意の色を再現する」というのは「観測者が任意の  X Y Z を得られるようディスプレイの分光分布  S_D (\lambda) を変化させる」 と言い換えることができる。なぜならば、観測者が得る  X Y Z は以下の (2)式に示す通り  S_D (\lambda)等色関数から計算されるからである。


 \displaystyle
\begin{aligned}
X &= k \int_{vis}^{} S_D(\lambda) \cdot \bar{x}(\lambda) d\lambda \\
Y &= k \int_{vis}^{} S_D(\lambda) \cdot \bar{y}(\lambda) d\lambda \\
Z &= k \int_{vis}^{} S_D(\lambda) \cdot \bar{z}(\lambda) d\lambda \\
\end{aligned}
\tag{2}


ここで  \bar{x}(\lambda), \bar{y}(\lambda), \bar{z}(\lambda) は CIE1931 の 2°視野の等色関数意味する。 なお、係数  k は便宜的な理由で用いられる係数であるため[9] 以後の数式では省略する。

 S_D (\lambda) は (1)式で示した通り、ディスプレイの3刺激値  R_D, G_D, B_D によって一意に定まる。 よって (2)式に (1)式を代入して以下の (3)式を得る。


 \displaystyle
\begin{aligned}
X &= R_D  \int_{vis}^{} S_{D, r}(\lambda) \cdot \bar{x}(\lambda) d\lambda + G_D \int_{vis}^{} S_{D, g}(\lambda) \cdot \bar{x}(\lambda) d\lambda + B_D \int_{vis}^{} S_{D, b}(\lambda) \cdot \bar{x}(\lambda) d\lambda\\
Y &= R_D  \int_{vis}^{} S_{D, r}(\lambda) \cdot \bar{y}(\lambda) d\lambda + G_D \int_{vis}^{} S_{D, g}(\lambda) \cdot \bar{y}(\lambda) d\lambda + B_D \int_{vis}^{} S_{D, b}(\lambda) \cdot \bar{y}(\lambda) d\lambda\\
Z &= R_D  \int_{vis}^{} S_{D, r}(\lambda) \cdot \bar{z}(\lambda) d\lambda + G_D \int_{vis}^{} S_{D, g}(\lambda) \cdot \bar{z}(\lambda) d\lambda + B_D \int_{vis}^{} S_{D, b}(\lambda) \cdot \bar{z}(\lambda) d\lambda\\
\end{aligned}
\tag{3}


従って「ディスプレイが任意の色を再現する」とは「観測者が任意の  X Y Z を得られるようにディスプレイに 3刺激値  R_D, G_D, B_D を与える」 と言い換えることができる。

簡単に言うと、  X Y Z を入力として  R_D, G_D, B_D を出力する計算式を立てて解けば良い。 そしてそれは (3)式から導くことが可能である。

5.3.2. 積分計算を別の値で置き換える

それでは式の変形を続けていく。まずは積分計算を別の記号で置き換える。

(3)式の  X の計算式の右辺第一項の  \int_{vis}^{} S_{D, r}(\lambda) \cdot \bar{x}(\lambda) d\lambda に注目する。 この式はディスプレイの Red のみが光っている場合の  X の計算結果に等しい。

別の言い方をすると、ディスプレイに  (R_D, G_D, B_D) = (1, 0, 0) を入力した場合の  X の計算結果に等しい。

そこで Red のみが光っている場合の  X の計算結果を  X_r と置く。すると   \int_{vis}^{} S_{D, r}(\lambda) \cdot \bar{x}(\lambda) d\lambda = X_r と書ける。

同様に Green のみが光っている場合の  X の計算結果を  X_g と置く。すると   \int_{vis}^{} S_{D, g}(\lambda) \cdot \bar{x}(\lambda) d\lambda = X_g と書ける。

同様に Blue についても   \int_{vis}^{} S_{D, b}(\lambda) \cdot \bar{x}(\lambda) d\lambda = X_b と書ける。

これを  Y, Z についても適用し 以下の (4)式を得る。


 \displaystyle
\begin{aligned}
\int_{vis}^{} S_{D, r}(\lambda) \cdot \bar{x}(\lambda) d\lambda &= X_r\\
\int_{vis}^{} S_{D, g}(\lambda) \cdot \bar{x}(\lambda) d\lambda &= X_g\\
\int_{vis}^{} S_{D, b}(\lambda) \cdot \bar{x}(\lambda) d\lambda &= X_b\\
\int_{vis}^{} S_{D, r}(\lambda) \cdot \bar{y}(\lambda) d\lambda &= Y_r\\
\int_{vis}^{} S_{D, g}(\lambda) \cdot \bar{y}(\lambda) d\lambda &= Y_g\\
\int_{vis}^{} S_{D, b}(\lambda) \cdot \bar{y}(\lambda) d\lambda &= Y_b\\
\int_{vis}^{} S_{D, r}(\lambda) \cdot \bar{z}(\lambda) d\lambda &= Z_r\\
\int_{vis}^{} S_{D, g}(\lambda) \cdot \bar{z}(\lambda) d\lambda &= Z_g\\
\int_{vis}^{} S_{D, b}(\lambda) \cdot \bar{z}(\lambda) d\lambda &= Z_b\\
\end{aligned}
\tag{4}


(4)式を (3)式に代入して以下の (5)式を得る。


 \displaystyle
\begin{aligned}
X &= R_D X_r + G_D X_g + B_D X_b\\
Y &= R_D Y_r + G_D Y_g + B_D Y_b\\
Z &= R_D Z_r + G_D Z_g + B_D Z_b\\
\end{aligned}
\tag{5}


行列の形で書き直して以下の (6)式を得る。


 \displaystyle
\begin{aligned}
   \begin{bmatrix} X \\ Y \\ Z \end{bmatrix} =
   \begin{bmatrix}
     X_r & X_g & X_b \\
     Y_r & Y_g & Y_b \\
     Z_r & Z_g & Z_b
    \end{bmatrix}
    \begin{bmatrix} R_D \\ G_D \\ B_D \end{bmatrix}
\end{aligned}
\tag{6}


ここで (6)式の  R_D G_D B_D to  XYZ 変換行列を  M とする。

さて、 M はディスプレイの分光分布が既知であれば速やかに計算可能である (※8)。 その上で  M逆行列  M^{-1} を計算すれば、任意の  XYZ を再現する  R_D, G_D, B_D を求めることができる。

※8 あるいは分光分布が未知であっても  X, Y, Z を測定可能な計測器があれば容易に導ける

5.3.2. 一般的な変換式の導出

さて、ひとまず  M の求め方は分かったが実は他にも表記の仕方がある。 今回、筆者が参考にした資料でも別の表記で  M を求めている。 具体的には Red、Green、Blue の  xy色度と White の  X, Y, Z を使って  M を計算している[2][7][8] (※9)。

本記事でもその形式で  M を求めたいため 引き続き (6)式を変形していく。

※9 細かいことを言うと資料毎に式にバリエーションがある。今回は [7] と全く同じ形にする

まず  X_r の色度  x_r について考える。 x = \frac{X}{X + Y + Z} であるから

 \displaystyle
x_r = \frac{X_r}{X_r + Y_r + Z_r}
\tag{7}

である。同様に

 \displaystyle
\begin{aligned}
y_r &= \frac{Y_r}{X_r + Y_r + Z_r}\\
z_r &= \frac{Z_r}{X_r + Y_r + Z_r}
\end{aligned}
\tag{8}

である。同様に別の変数についても計算をすると以下を得る。


 \displaystyle
\begin{aligned}
x_g &= \frac{X_g}{X_g + Y_g + Z_g}\\
y_g &= \frac{Y_g}{X_g + Y_g + Z_g}\\
z_g &= \frac{Z_g}{X_g + Y_g + Z_g}\\
x_b &= \frac{X_b}{X_b + Y_b + Z_b}\\
y_b &= \frac{Y_b}{X_b + Y_b + Z_b}\\
z_b &= \frac{Z_b}{X_b + Y_b + Z_b}\\
\end{aligned}
\tag{9}


唐突だが、ここで  T_r, T_g, T_b を以下のように定義する。


 \displaystyle
\begin{aligned}
T_r &=X_r + Y_r + Z_r\\
T_g &= X_g + Y_g + Z_g\\
T_b &= X_b + Y_b + Z_b\\
\end{aligned}
\tag{10}


(10)式を (7)~(9)式に適用して (11)式を得る。


 \displaystyle
\begin{aligned}
X_r &= T_r \cdot x_r\\
Y_r &= T_r \cdot y_r\\
Z_r &= T_r \cdot z_r\\
X_g &= T_g \cdot x_g\\
Y_g &= T_g \cdot y_g\\
Z_g &= T_g \cdot z_g\\
X_b &= T_b \cdot x_b\\
Y_b &= T_b \cdot y_b\\
Z_b &= T_b \cdot z_b\\
\end{aligned}
\tag{11}


(11)式を (6)式の行列に代入して (12)式を得る。

 \displaystyle
\begin{aligned}
   \begin{bmatrix} X \\ Y \\ Z \end{bmatrix} =
   \begin{bmatrix}
     T_r \cdot x_r & T_g \cdot x_g & T_b \cdot x_b \\
     T_r \cdot y_r & T_g \cdot y_g & T_b \cdot y_b \\
     T_r \cdot z_r & T_g \cdot z_g & T_b \cdot z_b
    \end{bmatrix}
    \begin{bmatrix} R_D \\ G_D \\ B_D \end{bmatrix}
\end{aligned}
\tag{12}

更に変形して以下を得る。

 \displaystyle
\begin{aligned}
   \begin{bmatrix} X \\ Y \\ Z \end{bmatrix} =
   \begin{bmatrix}
     x_r & x_g & x_b \\
     y_r & y_g & y_b \\
     z_r & z_g & z_b
   \end{bmatrix}
   \begin{bmatrix}
     T_r & 0 & 0 \\
     0 & T_g & 0 \\
     0 & 0 & T_b
   \end{bmatrix}
    \begin{bmatrix} R_D \\ G_D \\ B_D \end{bmatrix}
\end{aligned}
\tag{13}


ここから  T_r, T_g, T_b を求めていく。

まず  T_r, T_g, T_b と White の XYZ値  X_n, Y_n, Z_n との関係を考える。

White とはディスプレイに対して  (R_D, G_D, B_D) = (1, 1, 1) を入力した場合の特性である。 従って (13)式に  (X, Y, Z) = (X_n, Y_n, Z_n) (R_D, G_D, B_D) = (1, 1, 1) を代入して以下の (14)式が得られる。


 \displaystyle
\begin{aligned}
   \begin{bmatrix} X_n \\ Y_n \\ Z_n \end{bmatrix} &=
   \begin{bmatrix}
     x_r & x_g & x_b \\
     y_r & y_g & y_b \\
     z_r & z_g & z_b
   \end{bmatrix}
   \begin{bmatrix}
     T_r & 0 & 0 \\
     0 & T_g & 0 \\
     0 & 0 & T_b
   \end{bmatrix}
    \begin{bmatrix} 1 \\ 1 \\  1 \end{bmatrix}\\
    &=
   \begin{bmatrix}
     x_r & x_g & x_b \\
     y_r & y_g & y_b \\
     z_r & z_g & z_b
   \end{bmatrix}
    \begin{bmatrix} T_r \\ T_g \\ T_b \end{bmatrix}\\
\end{aligned}
\tag{14}


よって  T_r, T_g, T_b は以下の (15)式で計算できる。


 \displaystyle
\begin{aligned}
   \begin{bmatrix} T_r \\ T_g \\ T_b \end{bmatrix} &=
   \begin{bmatrix}
     x_r & x_g & x_b \\
     y_r & y_g & y_b \\
     z_r & z_g & z_b
   \end{bmatrix}^{-1}
   \begin{bmatrix} X_n \\ Y_n \\ Z_n \end{bmatrix}\\
\end{aligned}
\tag{15}


5.3.3. ディスプレイが任意の色を再現する仕組みのまとめ

ということで、長々と数式の変換を行ってきた内容をまとめる。

  • ディスプレイは 3刺激値  R_D, G_D, B_D を制御することで任意の色 ( X, Y, Z) を再現する
    • (3) 式参照
  •  X, Y, Z R_D, G_D, B_D の関係は (13)式で表すことができる
  • (13)式の行列はまとめることで 3x3 R_D G_D B_D to  XYZ 変換行列  M として扱うことができる
  • 従って、 M^{-1} を計算すれば任意の  X, Y, Z を表示するための  R_D, G_D, B_D が計算できる
  •  M は(13)式と(15)式を使って計算可能であり、そのためには以下の情報があれば良い
    • Red, Green, Blue 単色の  xy色度
    • White の XYZ値

5.3.4. ディスプレイが任意の色を再現する具体例の提示

理論式が完成したので、実際に  R_D, G_D, B_D を計算してみよう。

まずは  M を計算する。自宅のディスプレイの 360~780 [nm] の分光分布のデータを使って 単色の  xy と 各色の  X, Y, Z を計算した結果は以下の通り。なお、今回は筆者の計算の都合で  Y=1.0 となるよう正規化してある。


 \displaystyle
\begin{aligned}
   \begin{bmatrix}
     X_r & X_g & X_b & X_n \\
     Y_r & Y_g & Y_b & Y_n \\
     Z_r & Z_g & Z_b & Z_n
    \end{bmatrix} = 
    \begin{bmatrix}
      0.5792 & 0.2603 & 0.1683 & 1.0078 \\
      0.3244 & 0.6208 &  0.0548 & 1.         \\
      0.0086 & 0.0883 & 0.9628 & 1.0597
    \end{bmatrix}
\end{aligned}
\tag{16}


 \displaystyle
\begin{aligned}
   \begin{bmatrix}
     x_r & x_g & x_b \\
     y_r & y_g & y_b \\
     z_r & z_g & z_b
   \end{bmatrix} = 
   \begin{bmatrix}
      0.6350 & 0.2685 & 0.1419  \\
      0.3556 & 0.6404 & 0.0462 \\
      0.0095 & 0.0911 & 0.8119
    \end{bmatrix}\\
\end{aligned}
\tag{17}


ここから  M, M^{-1} を計算した結果は以下の通り。

 \displaystyle
\begin{aligned}
M = 
   \begin{bmatrix}
      0.5792 & 0.2603 & 0.1683 \\
      0.3244 & 0.6208 &  0.0548 \\
      0.0086 & 0.0883 & 0.9628
    \end{bmatrix}\\
\end{aligned}
\tag{18}


 \displaystyle
\begin{aligned}
M^{-1} = 
   \begin{bmatrix}
      2.2273 & -0.8854 & -0.339  \\
      1.1714 &  2.0895 &  0.0859 \\
      0.0875 & -0.1838 &  1.0338 
    \end{bmatrix}\\
\end{aligned}
\tag{19}


それでは、お試しで Color Checker の No16 (Yellow) のパッチを再現してみよう。

No.16 のパッチに D65 光源を照らした際の XYZ値は  (X, Y, Z) = (0.5604, 0.5942, 0.0926) である (※10、※11)。 これを出力する  R_D, G_D, B_D の計算結果は以下となる。

※10 BabelColor で公開されている分光反射データ[10] を使って筆者が計算した。計算の詳細は省略する
※11 分光反射率が 1.0 の場合に  Y=1.0 となるよう  XYZ値を正規化した


 \displaystyle
\begin{aligned}
  \begin{bmatrix}
    R_D \\
    G_D \\
    B_D
   \end{bmatrix} &= 
   \begin{bmatrix}
      &  &  \\
      & M^{-1} &  \\
      &  & 
   \end{bmatrix}
   \begin{bmatrix}
      X  \\
      Y \\
      Z
    \end{bmatrix} \\
    &=
   \begin{bmatrix}
      2.2273 & -0.8854 & -0.339  \\
      1.1714 &  2.0895 &  0.0859 \\
      0.0875 & -0.1838 &  1.0338 
    \end{bmatrix}
   \begin{bmatrix}
      0.5604 \\
      0.5942  \\
      0.0926
    \end{bmatrix}\\
  &=
   \begin{bmatrix}
      0.6908 \\
      0.5931  \\
      0.0355
    \end{bmatrix}\\
\end{aligned}
\tag{20}


ちなみに、これは Linear値なので画面に表示する場合は sRGB の OETF を適用する必要がある。 sRGB の OETF を適用し 8 bit で正規化した場合の値は  (R'_D, G'_D, B'_D) = (217, 202, 53) となる。

参考までに、上記の計算を行ったコードへのリンクを以下に貼っておく。

github.com

5.4. ディスプレイの WCG対応と分光分布の関係

本記事の目的は WCG対応と観測者メタメリズムの関係を調べることである。 そのため、WCG対応がディスプレイの特性(分光特性)に与える変化についても理解しておく必要がある。

ここでは、WCG対応によってディスプレイの分光分布がどのように変化するかを説明する。

5.4.1. ディスプレイの色域

まずは色域 (Gamut) の定義をおさらいする。 3原色ディスプレイにおける色域とは、xy色度図上において 3原色の色度を頂点とした三角形の領域を意味する[2][11]。

例として筆者の自宅のディスプレイの色域をプロットした様子を図9 に示す。図9 の青色の三角形が筆者のディスプレイの色域である。

図9. 自宅の液晶ディスプレイの色域

それでは分光分布と色域の関係を調べていこう。

まずはディスプレイを増やして傾向を観察する。新たに iPhone 13 Pro (WCG対応) の分光分布を測定し、 自宅ディスプレイとの分光分布の違いを比較した。

双方の分光分布および色域をプロットした様子を図10 に示す。

(a) 分光分布 (b) 色域の比較
図10. 自宅のディスプレイと iPhone 13 Pro の特性比較。(a) 分光分布、(b) 色域。

図10 を見ると単色の分光分布の幅が狭くなると色域が広がるように見える。

この仮説を検証してみる。

5.4.2. 分光分布と色域の関係をシミュレーションで確認

図10 から得た仮説を確認するためには、任意の分光分布を設定可能な 3原色ディスプレイがあると都合が良い。 しかし、そのようなデバイスはこの世に存在しない。そのため筆者は任意の分光分布を設定可能な仮想ディスプレイを作った。

作成した仮想ディスプレイを使い、様々な分光分布で色域を確認した様子を以下の動画1に示す。

動画1. 作成した仮想ディスプレイの特性と色域の関係を確認している様子

ここで、筆者が作成した仮想ディスプレイについて2点ほど補足しておく。
まず1点目、仮想ディスプレイの分光分布は正規分布で模倣した。正規分布の平均と標準偏差は、動画上では loc, scale のパラメータで変更可能とした。 続いて2点目、仮想ディスプレイの分光分布は白色点が D65 となるように白色点調整した。そのため 1色の loc, scale を変えると残り 2色もゲインが変わる。 白色点調整の詳細は「付録1. 白色点の調整」を参照。

さて、動画の内容を分析してみよう。注意深く観察すると以下のことが分かる。

  • loc のパラメータを変えると頂点の色度は変わるが、色域それほど変わらない
  • scale のパラメータを変えると色域が拡大・縮小する
  • scale のパラメータを大きくして分光分布の幅を狭くすると色域が拡大する

よって、ディスプレイが WCG対応するためには各色の分光分布の幅を狭くすれば良いことが分かる。 参考データとして、筆者が仮想ディスプレイで BT.709、DCI-P3、BT.2020 の色域を持つディスプレイの分光分布を求めた結果を図11に示す。

(a) BT.709 色域の例 (b) DCI-P3 色域の例 (c) BT.2020 色域の例
図11. 色域と分光分布の関係。狭帯域になると色域が拡大することが分かる。

図11 からも分光分布の幅が重要であることが分かる。

5.4.3. WCG対応とディスプレイの分光分布の関係のまとめ

仮想ディスプレイの分光分布を変化させ、色域の変化を観察することで以下のことが分かった

  • ディスプレイが WCG対応を行うと各色の分光分布の幅が狭くなる

6. WCG対応 と観測者メタメリズムの関係を調べるためのシミュレーション

さて、ここまでの内容でシミュレーションを行う際に必要な知識の説明は済んだ。 ここからは実際にシミュレーションを行って、WCG対応が進んだ際に観測者メタメリズムが原因の色ズレがどう変化するかを確認していく。

6.1. 検証環境の概要と評価基準

ここでは検証環境の概要と評価基準について説明する。

まず検証環境の概要を説明する。筆者は文献[6] を参考に以下の2種類の色ズレについてついてシミュレーションを行うこととした。

  • 同一の観測者内の色ズレ
  • 複数の観測者間の色ズレ

前者は個人で複数のデバイスを使う際の影響を調べるためのもの、 後者は複数人で単一のデバイスを使用する際の影響を調べるためのものである。

それぞれ図を使って簡単に説明をする。合わせて各検証環境での色ズレの定義についても述べる。

6.1.1. 同一の観測者内の色ズレ

図12. 本記事における「同一の観測者内の色ズレ」とは図中の観測者  p が知覚する色ズレを意味する

図12 は「同一の観測者内の色ズレ」について説明したものである。ここでは白色のパッチとディスプレイが並んでいる。白色のパッチは D65 の光源で照らされており、ディスプレイは CIE1931 の 2°視野の等色関数を使って D65 に調整されている。 別の言い方をすると、白色のパッチとディスプレイは CIE1931 測色標準観測者 (Standard Colorimetric Observer) に対してメタメリズムが成立している。 そしてそれらを観測者  p が視認している。

図12 をベースに、本記事では「同一の観測者内の色ズレ」の定義を「CIE1931 測色標準観測者に対してメタメリズムが成立している 2種類の色刺激を ある観測者  p が視認した際に知覚する色ズレ」とする。

図12 では観測者  p が2つの色刺激の色度をそれぞれ  (x_p, y_p) = (0.313, 0.330) (x_p, y_p) = (0.317, 0.338) として知覚しており色ズレが発生している。 なお、 x_p, y_p の添え字  p は観測者の識別インデックスを意味する。

6.1.2. 複数の観測者間の色ズレ

図13. 本記事における「複数の観測者間の色ズレ」とは図中の CIE1931 標準測色観測者が知覚する色ズレを意味する

図13 は「複数の観測者間の色ズレ」について説明したものである。ここでは  P個の白色パッチと P台のディスプレイが並んでいる。各ディスプレイは  P人の観測者それぞれに対して白色パッチとメタメリズムが成立するよう調整されている。 そしてそれらを CIE1931 測色標準観測者 が見比べている。

図13 をベースに、本記事では「複数の観測者間の色ズレ」の定義を「複数の観測者に対してメタメリズムが成立している複数のディスプレイを CIE1931 測色標準観測者が視認した際に知覚する色ズレ」とする。

図13 では CIE1931 標準測色観測者が各ディスプレイを異なる色度で知覚しており、色ズレが発生している。

6.2. 準備

シミュレーションで評価する「色ズレ」の定義が終わったので、より具体的な準備に入る。 シミュレーションに必要な以下の4つを準備する。

  • 仮想ディスプレイ
  • 等色関数
  • 分光反射率が既知のカラーパッチ
  • 光源

6.2.1. 仮想ディスプレイ

今回のシミュレーションを行うにあたり、筆者は以下の3種類の仮想ディスプレイを用意することにした。

  • BT.709 色域のディスプレイ (WCG非対応)
  • DCI-P3 色域のディスプレイ (WCG対応済)
  • BT.2020 色域のディスプレイ (WCG対応済)

WCG対応済みのディスプレイを2種類用意した理由は、DCI-P3色域と BT.2020色域とでは分光分布の形状が大きく異なるからである。

また、仮想ディスプレイを作るにあたり、筆者は現実に存在するディスプレイの分光分布を参考にした。 それぞれの色域に対して参考にした分光分布は以下の通り。

色域 参考にしたディスプレイ
BT.709 色域 自宅の液晶ディスプレイ
DCI-P3 色域 iPhone 13 Pro
BT.2020 色域 三菱電機のレーザーバックライトディスプレイ [12]

作成した仮想ディスプレイの分光分布を図14 に示す。

色域 分光分布と xy色度図
BT.709
DCI-P3
BT.2020
図14. 作成した仮想ディスプレイの分光分布

1点補足しておく。図14 を見ると分かるように、作成した仮想ディスプレイの色域は、ターゲットの色域と完全には重なっていない。 理由は、仮想ディスプレイの分光分布が参考にしたディスプレイの分光分布になるべく近づくようパラメータ調整したからである。

6.2.2. 等色関数

観測者メタメリズムに関するシミュレーションを行うためには、個人差が反映された等色関数のデータセットが必要である。 今回は MCSL にて Categorical Observers として公開されている10種類の等色関数[1] を使用した (※13)。 これは Asano らによって開発された[15] 優れたデータセットであり、観測者メタメリズムに関する様々な検証で利用可能となっている。

※13 データセットには lms-CMFs と xyz-CMFs の双方が含まれているが、今回は XYZ を計算するのが目的なので xyz-CMFs のみを使用した

生データは [1] の PDF の "CMFs, ages, and physiological parameters" のリンクからダウンロードできる。

この等色関数は正式には「カテゴリカル観測者  p の xyz等色関数 ( p は 1~10 の整数) 」と呼ぶべきだが、 本記事では短く「観測者  p等色関数」と呼ぶ(ただし図では Cat.Obs  p と表記する場合がある)。

参考までに観測者1~観測者10 の等色関数をプロットした結果を図15 に示す。

図15. 観測者1~観測者10 の等色関数をプロットした結果

なお、これらの等色関数のデータの波長は 390~780 nm となっている。そのため、シミュレーションで XYZ を計算する際に照明光やディスプレイの分光分布も 390~780 nm の範囲のデータのみを使うこととした (※14)。

※14 後述の Color Checker は 380~730 nm のデータであるため、最終的には 390~730 nm の範囲のデータのみを使用した

6.2.3. 分光反射率が既知のカラーパッチ

筆者はシミュレーションを行うにあたり、白色のパッチだけでなく様々な分光分布のデータを使いたいと考えた。 そこで BabelColor で公開している Color Checker の 24パッチの分光反射率のデータ[10] を使い検証を行った。

6.2.4. 光源

D65 の光源を用意した。

6.3. 同一の観測者内 (intra-observer) の色ズレに対するシミュレーション

WCG化が進んだ際に「同一の観測者内の色ズレ」どのように変化するか調査した内容の詳細を記す。

6.3.1. 検証環境

図12 をベースに、以下の拡張を加えたものを検証環境とした。

  • 図12 左側の白色のパッチを、Color Checker の 24個のパッチの中から任意の1つを選ぶように拡張
  • 図12 右側のディスプレイの特性を、作成した 3種類の仮想ディスプレイの中から任意の1つを選ぶように拡張
  • 図12 下側の観測者を、観測者1~観測者10 の中から任意の1人を選ぶように拡張

観測者  p が左側の D65光源下のパッチを見て得られる色度  x_{p, i}, y_{p, i}正しい色とし、 右側のディスプレイで再現した色度  x_{p, i, n}, y_{p, i, n} との差  \Delta x_{p, i, n} y_{p, i, n} を 色ズレ指標とした。

 \displaystyle
\begin{aligned}
\Delta x_{p, i, n} y_{p, i, n} = \sqrt{ (x_{p, i} - x_{p, i, n} )^2 + (y_{p, i} - y_{p, i, n})^2 }
\end{aligned}
\tag{21}

ここで  p は観測者の番号を、 i は Color Chekcer のパッチの番号を、 n はディスプレイの番号を示す。  n=0 が BT.709色域のディスプレイを、 n=1 が DCI-P3、 n=2 が BT.2020 を意味する。

具体例を 図16 に示す。なお、図中では  xy色度は  x_{p}, y_{p} と表記しており、 i, n の添え字は省略してある (図が見づらくなったため)。

図16. 同一の観測者内の色ズレ評価の具体例

以下に  \Delta x_{p, i, n} y_{p, i, n} を算出するまでの手順を示す (添え字は省略してある)。

  • D65光源下のパッチ  i XYZ 値を CIE1931 2°視野の等色関数で計算
  • (13)式を使い、計算した  XYZ 値に対してメタメリズムが成立するように、仮想ディスプレイの 3刺激値  R_DG_DB_D を計算 (※15)
  • (1)式を使い、メタメリズムが成立する仮想ディスプレイの分光分布  S_D (\lambda) を計算
  • (3)式を使い観測者  p に対する  XYZ 値を計算 (※15)
  • 得られた  XYZ 値から  xy 色度を計算

※15 等色関数は CIE1931 2°視野ではなく観測者  p等色関数を使用

6.3.2. 検証結果

10人の観測者に対して、3種類の仮想ディスプレイを使い ColorChecker の各パッチに対する色ズレ  \Delta x_{p, i, n} y_{p, i, n} を調べた結果を 図17 に示す。ここでは観測者ごとに結果をまとめてある。各パッチに重ねて描画した棒グラフの高さが色ズレを意味する。

観測者の番号 各観測者に対する観測者内の色ズレ量
 p=1
 p=2
 p=3
 p=4
 p=5
 p=6
 p=7
 p=8
 p=9
 p=10
図17. 観測者、仮想ディスプレイ毎に同一観測者内の色ズレ量をプロットしたもの

観測者によって値の大小はあるものの、WCG対応が進むと色ズレが大きくなることが分かった。

参考までに、検証に使用したソースコードのリンクを貼っておく。

github.com

6.4. 複数の観測者間 (inter-observer) の色ズレに対するシミュレーション

6.4.1. 検証環境

図13をベースとして、以下の拡張を加えたものを検証環境とした。

  • 図13 左側の白色のパッチを、Color Checker の 24個のパッチの中から任意の1つを選ぶように拡張
  • 図13 右側のディスプレイの特性を、作成した 3種類の仮想ディスプレイの中から任意の1つを選ぶように拡張

CIE1931 標準測色観測者が D65光源で照らされたパッチを見て得られる色度を正しい色とし、各ディスプレイで再現された色との色差を色ズレの指標とした。

図18. 複数の観測者間の色ズレ評価の具体例

検証は以下の手順で行った。

  • (3)式を使い D65 光源で照らしたパッチの各観測者  p に対する  XYZ 値を計算 (※16)
  • (13)式を使い得られた  XYZ 値に対してメタメリズムが成立するように、仮想ディスプレイの 3刺激値  R_DG_DB_D を計算 (※16)
  • (1)式を使い観測者  p に対してメタメリズムが成立する仮想ディスプレイの分光分布  S_D (\lambda) を計算
  • (3)式を使い 観測者  p に対してメタメリズムが成立する仮想ディスプレイを CIE1931標準測色観測者が見た際の  XYZ 値を計算
  • 得られた  XYZ 値から色ズレを評価

※16 等色関数は CIE1931 2°視野ではなく観測者  p等色関数を使用

6.4.2. 検証結果

今回の色ズレは CIE1931 標準測色観測者の XYZ値で算出した。従って色ズレの量を sRGB空間で表現することも可能である。

11人 (うち1人は CIE1931 標準測色観測者) の色の見え方の違いを sRGB画像として可視化したものを図19、図20 に示す。 図19 は可視化の際の各観測者の結果の配置位置を示している。

図19. 各観測者と表示位置の関係

仮想ディスプレイの色域 複数の観測者間の色ズレを可視化したもの
BT.709 11_patch_color_checker_cmfs-display-00
DCI-P3 11_patch_color_checker_cmfs-display-01
BT.2020 11_patch_color_checker_cmfs-display-02
図20. CIE1931 標準測色観測者から見た各観測者のズレを可視化したもの

WCG対応が進むと(色域が広がると)色ズレが大きくなる様子が確認できる。

また、この色ズレは CIE1931 標準測色観測者に対するものであるため、 L^*a^*b^* 空間に変換することも可能である。 そこで  L^*a^*b^* 空間に変換し、 a^*b^* 平面上でのユークリッド距離を色差量とした場合の比較を計算した。 結果を図21 に示す。

仮想ディスプレイの色域 複数の観測者間の色ズレを棒グラフで表示したもの
BT.709
DCI-P3
BT.2020
図21. CIE1931 標準測色観測者から見た各観測者のズレを棒グラフで表示したもの

図21 からも、観測者によって値の大小はあるものの、WCG対応が進むことで色ズレが大きくなることが分かった。

参考までに、検証に使用したソースコードのリンクを貼っておく。

github.com

6.5. 考察

筆者は 図17、図20、図21 を見て以下を理解した。

  • ディスプレイの WCG対応が進むと観測者メタメリズムが原因の色ズレは大きくなる
  • これは「同一の観測者内」と「複数の観測者間」の双方で共通している
  • 図20、図21 より色ズレの大きさには観測者ごとに大きく異なる

これらの原因について簡単に考察したい(人によっては自明に感じるかもしれないが)。

まず、WCG対応が進むと色ズレが大きくなる原因について考える。筆者は分光分布の幅が狭くなると「等色関数の個人差」が強調されるからだと考える。 具体例を図22 に示す。図22 は以下の3つをプロットしたものである。

図22. 各等色関数と仮想ディスプレイの分光分布の比較

もともと個人の等色関数にはバラツキが存在しているが、分光分布が狭いディスプレイと組み合わせた場合は、バラツキがピンポイントで強調されやすいことが分かる。 WCG対応が進めば進むほど分光分布の幅は狭くなるため、WCG対応が進むと色ズレが増加する結果が得られたのだと考える。

次に、観測者ごとにズレ量の大小が大きく異なる点についても考える。筆者は CIE1931 2°視野の等色関数とのズレが強調されやすかったか、そうでなかったかの違いだと考える。 各観測者の等色関数を注意深く観察すると、CIE1931 2°視野の等色関数とのズレが大きい波長、小さい波長が存在することが分かる。 この部分とディスプレイの分光分布が重なるか否かで、色ズレの大小が生まれていると考えている。

この考えが正しい場合、分光分布のピーク位置の波長がズレると、観測者メタメリズムが原因の色ズレ量が変化することを意味する。 従って 図17、図20、図21 の結果は、あくまでも筆者が分光分布を定めた仮想ディスプレイの結果であり、 現実世界の 3原色ディスプレイを使って検証した場合は、各観測者の色ズレ量が大きく変わる可能生があることには注意したい。

とはいえ変わる可能生があるのは色ズレの大小であり、「WCG対応が進むことで色ズレが増える」という傾向は変わらないと考える。

最後に「どうしたら観測者メタメリズムによる色ズレを抑制できるか」についても考察したいが、残念ながら良いアイデアが無いので特に言及しない。 今のところは、なるべく色域の狭いディスプレイを使うのが良いと個人的には考えている。

7. 感想

ようやく観測者メタメリズムのシミュレーションを実施することができた。個人的にとても勉強になったと考えている。

「観測者メタメリズム」という用語は以前から知っており、実際に現実世界でも苦しめられてきた存在ではあるが、 こうして真面目にシミュレーションを行うのは初めての経験だった。

筆者は、普段はスペクトルベースの計算を殆ど行わないので色々と戸惑うことが多かったが、 今回の経験を経てスペクトルベースで様々な色処理を行うことのモチベーションが上がった。大変有意義な調査だった。

今回の色処理の計算も Colour Science for Python のライブラリに大いに助けられた。 偉大なライブラリを開発・メンテナンスしている方々には大変感謝している。

特に、v0.4.0 以降で colour.sd_to_XYZMultiSpectralDistributions に対応したおかげで、計算が大幅にしやすくなった。 マジで神ライブラリなので興味のある方はぜひ使って欲しいと考えている。

付録1. 白色点の調整

筆者が最初に作った仮想ディスプレイは、R, G, B の Primary colors は所望の特性を有していたが、 R + G + B で表現される White は何も調整しておらず酷い特性であった。

この状態だと各種シミュレーションを行う際に弊害が出る可能生があった。 そこで 仮想ディスプレイの白色点を D65 に調整することにした。

白色点の調整(ホワイトバランス調整と呼ぶこともある)には幾つかの方法がある。 例えば Wikipedia では (3x3 の行列を使う手法として) 以下の4手法が紹介されている[16]。

  • (a) Scaling monitor R, G, and B
  • (b) Scaling X, Y, Z
  • (c) Von Kries's method
  • (d) Scaling camera RGB

今回は (a) の方式で調整を行う。理由は以下の3点である。

  • (a) は RGB空間で各色にゲインを適用するだけであり、数式がシンプルで良い
  • 本記事の検証は色順応の評価を目的としていないため (c) は使う必要性が無い
  • 筆者が自宅で使っている2台のディスプレイの動作を確認したところ、2台とも白色点を変更すると R, G, B のゲインが変わる仕様となっていた(ディスプレイ1 の測定結果ディスプレイ2 の測定結果

それでは、筆者が仮想的に作成したディスプレイの白色点を D65 に調整するための係数  G_r, G_g, G_b を算出しよう。

まずディスプレイの3刺激値  R_D, G_D, B_D X, Y, Z の関係を復習する。2つの3刺激値は行列  M を使って以下の通りに計算できる ( M の求め方は (13), (15)式を参照)。

 \displaystyle
\begin{aligned}
   \begin{bmatrix} X \\ Y \\ Z \end{bmatrix} &=
   \begin{bmatrix}
      &  &  \\
      & M &  \\
      &  & 
   \end{bmatrix}
   \begin{bmatrix} R_D \\ G_D \\ B_D \end{bmatrix}\\
\end{aligned}
\tag{A.1.1}

さて、ここで白色点が D65 になるということは3刺激値として  (R_D, G_D, B_D) = (1, 1, 1) を与えた際に  (X, Y, Z) = (X_{D65}, Y_{D65}, Z_{D65}) が得られると言うことである。

そして、それが  R, G, B に対してゲイン  G_r, G_g, G_b をかけることで達成されるため、 以下の式が成立する。

 \displaystyle
\begin{aligned}
   \begin{bmatrix} X_{D65} \\ Y_{D65} \\ Z_{D65} \end{bmatrix} &=
   \begin{bmatrix}
      &  &  \\
      & M &  \\
      &  & 
   \end{bmatrix}
   \begin{bmatrix}
     G_r & 0 & 0 \\
     0 & G_g & 0 \\
     0 & 0 & G_b
   \end{bmatrix}
   \begin{bmatrix} 1 \\ 1 \\ 1 \end{bmatrix}\\
    &=
   \begin{bmatrix}
      &  &  \\
      & M &  \\
      &  & 
   \end{bmatrix}
   \begin{bmatrix} G_r \\ G_g \\ G_b \end{bmatrix}\\
\end{aligned}
\tag{A.1.2}

さて、今必要なのは  G_r, G_g, G_b である。これらの値は  M逆行列をかけて求めることができる。

 \displaystyle
\begin{aligned}
   \begin{bmatrix} G_r \\ G_g \\ G_b \end{bmatrix} &=
   \begin{bmatrix}
      &  &  \\
      & M &  \\
      &  & 
   \end{bmatrix}^{-1}
   \begin{bmatrix} X_{D65} \\ Y_{D65} \\ Z_{D65} \end{bmatrix}\\
\end{aligned}
\tag{A.1.3}

これで  R_D, G_D, B_D に適用する白色点調整用のゲイン  G_r, G_g, G_b を求めることができた。 白色点調整前の 3刺激値を  R_{D}, G_{D}, B_{D}、調整後の 3刺激値を  R'_{D}, G_{D}, B'_{D} とすると、以下の式で白色点調整できる。

 \displaystyle
\begin{aligned}
   \begin{bmatrix} R'_D \\ G'_D \\ B'_D \end{bmatrix} &=
   \begin{bmatrix}
    G_r  & 0 & 0 \\
     0 & G_g & 0 \\
     0 & 0 & G_b
   \end{bmatrix}
   \begin{bmatrix} R_D \\ G_D \\ B_D \end{bmatrix}\\
\end{aligned}
\tag{A.1.4}

参考資料

[1] Munsell Color Science Laboratory, "Observer Function Database", https://www.rit.edu/science/sites/rit.edu.science/files/2019-01/MCSL-Observer_Function_Database.pdf

[2] 太田 登, "色彩工学 第2版", 東京電機大学出版局, 2005.

[3] Mark D. Fairchild & David R. Wyble, "Mean Observer Metamerism and the Selection of Display Primaries", http://markfairchild.org/PDFs/PRES14.pdf

[4] Wikipedia (EN), "Metamerism (color)", https://en.wikipedia.org/wiki/Metamerism_(color)

[5] T. D. Canham, D. L. Long, M. D. Fairchild and M. Bertalmío, "Physiologically Personalized Color Management for Motion Picture Workflows," in SMPTE Motion Imaging Journal, vol. 131, no. 2, pp. 8-16, March 2022, doi: 10.5594/JMI.2022.3143608.

[6] Asano, Yuta & Fairchild, Mark & Blond´e, Laurent & Morvan, Patrick. (2014). "Observer Variability in Color Image Matching on a LCD monitor and a Laser Projector". Color and Imaging Conference. 2014.

[7] T. Fujiwara, "RGB → XYZ 変換行列の求め方", http://web.archive.org/web/20170810033453/http://w3.kcua.ac.jp/~fujiwara/infosci/colorspace/rgb_xyz.html

[8] Katoh, Naoya & Deguchi, Tatsuya & Berns, Roy. (2001). "An Accurate Characterization of CRT Monitor (I) Verifications of Past Studies and Clarifications of Gamma". Optical Review. 8. 305-314. 10.1007/s10043-001-0305-0.

[9] 日本色彩学会, "新編 色彩科学ハンドブック" 第3版", 東京大学出版会, 2011.

[10] BabelColor, "ColorChecker data", https://babelcolor.com/colorchecker-2.htm#xl_CCP2_data

[11] Wikipedia (EN), "Gamut", https://en.wikipedia.org/wiki/Gamut

[12] 新倉栄二, "RGBレーザーバックライト液晶ディスプレイ", ITUジャーナル, 2016, vol. 46, no. 2, p.32-235, https://www.ituaj.jp/wp-content/uploads/2016/01/2016_02-08-laserback.pdf

[13] ISO/CIE 11664-4:2019, Colorimetry - Part 4: CIE 1976 Lab* colour space

[14] Wikipedia (EN), "Color difference", https://en.wikipedia.org/wiki/Color_difference

[15] Asano, Y, Fairchild, MD. "Categorical observers for metamerism". Color Res Appl. 2020; 45: 576– 585. https://doi.org/10.1002/col.22493

[16] Wikipedia (EN), "Color balance", https://en.wikipedia.org/wiki/Color_balance

OBS Studio 28.0 が HDR のライブ配信に対応したので試してみた

1. 背景と目的

  • 筆者は以前より HDR対応ゲームを YouTube で配信することに興味があった
    • 昨年は 4K HDR 対応のキャプチャデバイスを購入して HDR配信に挑戦した(失敗に終わった)

trev16.hatenablog.com

  • 先日にニュースで OBS Studio 28.0 Beta 1 が HDR の配信に対応したことを知った[1]
  • まだ Beta版だが 実際に HDR配信が可能か試すことにした

おことわり

本記事は OBS Studio 28.0 Beta 1 を使って検証しました。 まだ Beta版ということもあり、記事で紹介した設定値は将来的に変更となる可能性があります。ご了承下さい。

3. 結論

  • OBS Studio 28.0 Beta 1 を使い YouTubeHDR配信が可能であることを確認した

    • HDR配信に必要な OBS の設定値は 4. 詳細 を参照
  • 加えて OBS の制御が SDRのモニターでも可能であることを確認した

    • 例えば以下のデュアルモニター環境を想定する
      • ①メインのゲーミングモニターに PS4 や PS5 の HDRのゲーム画面を表示して実況プレイする
      • ②サブモニターに OBS の画面を表示して配信を制御する
    • この際に②のサブモニターは SDR でも問題ない(Windows OS の「Use HDR」オプションを有効化する必要は無い)
      • OBS が良い感じに HDR to SDR 変換をしてくれる
  • テスト配信の結果は以下を参照

    • OBS の操作が下手でもたついてるので概要欄のタイムスタンプからジャンプすることを推奨

4. 詳細

ここでは 筆者が HDR配信を行うために OBS に設定した内容を書く。 また、確認のため使用したテストパターンも参考資料として添付する。

4.1. OBS で設定した内容

OBS で以下の通りに設定を変更した。

  • ① Stream 設定で Service を「YouTube - HLS」に変更
  • ② Output 設定で Encoder を 「Hardware (NVENC, HEVC)」に変更
  • ③ Advanced 設定で Color Format、Color Space をそれぞれ「P010 (10-bit, 4:2:0, 2 planes)」、「Rec.2100 (PQ)」 に変更
  • ④ キャブチャデバイスの設定で Color Space を「Rec.2100 (PQ)」に変更
説明番号 スクリーンショット

4.2. テストパターンを使用した動作確認

筆者は上記の設定が正しく機能することを確認するため、以下のテストパターンを使ったテスト配信を行った。

筆者はテスト配信を iPhone, iPad, Bravia の3デバイスで見た。 Rampパターンが 768 CV あたりまで白飛びせずに意図通りに光ることを確認した。よって OBS の設定は問題ないと判断した(※)。

冒頭のテスト配信では 03:21 辺りを見るのが分かりやすい。 配信では SDR TP と HDR TP を交互に切り替えて表示しており、HDR ではキッチリと光る様子が確認できる。

※ 筆者が判断した例を以下の図に示す(あいまいな表現なのは何卒ご容赦を)

テストパターンを使って 配信が HDR10 かどうか判断する例

なお、上記のパターン一式 (4K版を含む) は以下の URL からダウンロード可能である(再配布さえしなければ自由に使って構わない)。

drive.google.com

4.3. その他

  • テキストなどの素材は SDRレンジで描画される

    • 冒頭のテスト配信動画の 05:43 辺りを参照
  • 1920x1080 だとノイジーな配信になるのが少々気になった

  • 一方で 3840x2160 で配信した場合はノイズは抑制された
  • PS4 / PS5 を使う場合に「HDR調整」の結果が配信映像として流れるのが少し気になった
    • PS4、PS5 は HDRのゲームをプレイする前に「配信者が使用する TV/ゲーミングモニター」に対して HDR調整を行う
    • この HDR調整結果は配信者が見るのには適しているが、視聴者の HDRバイスでは意図しない表示となる可能性がある
      • この問題をどう解決すれば良いかは分からない
      • 事前のテスト配信で複数の HDR対応デバイスで表示してみて、極端な破綻が起こらなければ OK とする?

5. 感想

こういう検証をするのは楽しい!

そして1ヵ月以上前から書き始めている別記事はいつになったら書き上がるのだろうか…。 (車輪の再発明的な記事なので、結論は出ていてデータも集まってるんだけど、先行事例の資料が読み終わらなくて記事としてまとめられない)

参考資料

[1] obsproject/obs-studio, "OBS Studio 28.0 Beta 1", https://github.com/obsproject/obs-studio/releases/tag/28.0.0-beta1

ゲーム配信を行うための機材構成を検討した(家庭用ゲーム機を使用)

1. 背景と目的

  • ここ数年、YouTube や Twitch などのプラットフォームでゲーム配信が流行っている[1]
  • 筆者は配信を行うための機材構成やソフトウェアの設定に興味があった
  • そこで、複数の家庭用ゲーム機が混在する環境での機材構成を考えてみた
  • 実際に機材を準備し、複数回のテスト配信を経て、概ね想定通りに動くことを確認したので記事を残すことにした

2. おことわ り

筆者はゲーム配信を通じて視聴者数を増やすことに興味がありません。 ゲーム配信に必要な機材構成ソフトウェアの設定に強い関心があるだけです。 その点にご注意下さい。

3. 結論

自宅にある PS2PS4 Pro、Nintendo Switch を以下の構成で接続し、ゲームプレイとゲーム配信が両立できることを確認した。

図1. 筆者の自宅の機材構成

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

4.1. 配信環境に対する要求

筆者は配信環境に対して以下の要求があった。

  • ① 以下の音量を別々に調整できること
    • 配信者がゲームをしながらヘッドホンで聞くゲーム音
    • 配信を見ている視聴者が聞くゲーム音
  • ② ゲームプレイ時の遅延が気にならないレベルであること

①の背景は以下である。

筆者は経験的に、発話をしている時と発話していない時で聴覚特性が変化することが分かっている。 配信中は多くの時間を発話しながら過ごすため、配信者が耳にする音量と、視聴者が耳にする音量は別々に調整したいと考えた。

また、筆者は OBS を使い配信を開始する前に、ゲームの起動とOBS上でのゲームキャプチャを済ませたいと考えている(※1)。 その場合、(機材構成にも依るが)何もしないと配信開始直後からゲーム音が配信者のヘッドホンで流れてしまう。

これは、ゲーム開始前にオープニングトーク等の別作業をする際に大変に耳障りとなる。 そのため配信者が耳にするゲーム音を任意のタイミングで音量できる仕組みが必要だと考えた。

※1 Capture Device がゲーム画面を認識できないトラブルを未然に防ぐため。配信開始後だと対応が困難。

②の背景は、遅延があるとゲームのプレイが困難になるからである。

4.2. 要求を満たすための対応

4.2.1. ①の要求に対する対応

①の要求を満たすため、今回の構成では HDMI Audio Extractor を用意し、 配信者が耳にするゲーム音と Capture Device に入るゲーム音を完全に分けた。

配信者がモニタリングするゲーム音は Audio I/F にて音量調整を行い、配信に乗るゲーム音は Capture Device の後の OBS 上で音量調整を行った。 これにより ① の要求を満たすことに成功した (※2)。

※2 OBS の音量つまみだけでなく、Audio I/F のミキサーも操作する必要があるため、やや操作が煩雑になるが、それほど難しくないと考えている

4.2.2. ②の要求に対する対応

Capture Device の HDMI OUT (Passthrough) をディスプレイに直接入力し、この画面を見てゲームをプレイすることで対応した。 従って OBS の画面はゲームプレイ用としては参照しない(今回の構成では OBS の画面表示には 239ms 程度の遅延がある)。

PS2 などのアナログ出力のゲームの接続についても補足する。今回の構成では最初に Analog (Composite/S-Video) to HDMI Converter を使用して HDMI に変換している。 こうすることで PS4 や Switch と共通のパスで処理が可能となり、①と②の要求を簡単に満たすことができた(※3)。

※3 最初は I-O DATA製の GV-USB2 を使たのだが、これだと①の要求を満たせず、かつ②を満たそうとすると Interlace解除に失敗する問題があり断念した。

5. 感想

こういう構成を考えるのは個人的に好きである。楽しみながら作業することができた。

本記事はテキストばかりになってしまった。本当は対策の内容を理解しやすいように、筆者が行ったテスト配信の YouTube 動画を添付したかったのだが、死ぬほど OBS のオペレーションをミスってたので載せるのは断念した(オイオイ)。

参考資料

[1] Stream Hatchet, "VIDEO GAME STREAMING TRENDS REPORT 2021 YEARLY REPORT", https://insights.streamhatchet.com/-2021-live-streaming-report-0

黒フレーム挿入と黒ライン挿入を組み合わせて CRTライクなインターレース表示を試した

1. 背景と目的

  • 以前の記事iPhone 13 Pro の 120Hz ディスプレイを活用したテストパターンを作成した
  • この時は黒フレーム挿入を試したのだが、加えて黒ライン挿入も試せば CRTライクなインターレース表示が可能になると考えた
  • ということで実際に動画を作成して iPhone 13 Pro で再生することにした

2. 結論

60fps の動画に対して 黒ライン挿入 と 黒フレーム挿入 を行い 120fps の検証用動画を作成した。この動画を iPhone 13 Pro で再生して CRTライクなインターレース表示になることを確認した (※1 ※2)。

作成した動画を iPad で 240fps 撮影し、1/32倍速再生した様子を以下に示す。動画は明るさ不足でノイジーだったため、黒ライン挿入の様子が分かるスクリーンショットも合わせて示す。

zu1
動画1 1/32倍速再生した様子 図1. 黒ライン挿入の様子(拡大表示推奨)

作成した動画は以下のリンクからダウンロードできる (サイズは 1.3GB)。iPhone 13 Pro を所有している方は Files アプリを使えば確認できる(※3)。

quasi_interlacing_video_120fps.mov - Google ドライブ

※1 リファレンスとなる CRTモニターを準備できなかったので筆者の主観的な感想である。加えて特に良い印象も受けなかった(若干の企画倒れ感あり)。

※2 筆者が使用した iPhone の解像度は 2778x1284 であるため、iPhone 上で 1:1 pixel mapping の表示になっていない。これが動画の見え方にどのような悪影響を及ぼしているかは不明

※3 nPlayer などのサードパーティー製のプレイヤーでは 120fps 再生とならない可能性がある。注意して頂きたい。

3. 動画の作り方

以下で動画の作り方を説明していく。

が、まずは前提となる CRTライクなインターレース表示について説明する。

3.1. CRTライクなインターレース表示とは?

本記事で筆者はプログレッシブ信号に対して以下の2点を行った表示を CRTライクなインターレース表示と呼んでいる。

  • 偶数ラインのみの表示と奇数ラインのみの表示を、黒ライン挿入を行うことで擬似的に OLED 上で実現する
  • 以前の記事 で試した黒フレーム挿入を行い、OLED の表示を CRTのようなインパルス発光型[2] に近づける
図2. フレーム番号 0 図3. フレーム番号 1 図4. フレーム番号 2 図5. フレーム番号 3

3.2. DaVinci と Python を使った動画の作り方

具体的な動画の作り方は以下の通り。なお、インターレース表示は擬似的に行うため、動画データは常にプログレッシブ形式で良い。

  • ①60fps のソースを準備

    • 使いたい動画を 60fps の静止画連番ファイルで吐き出す
    • 解像度は 1080x1920 (9:16) にしておく
      • 1920x1080 だと縦方向の大きさが不足しており、黒ライン挿入の効果を確認しづらかったので 1080x1920 とした
  • ②黒ライン挿入を実施

    • 静止画連番ファイルに対して Python で黒ライン挿入を行う
    • 奇数フレームと偶数フレームとて黒ラインの挿入位置が入れ替わるようにする
    • 黒ラインの高さは 2px とする
      • 1px だと「インターレース感」を知覚しづらかったため
      • また、iPhone 側のスケーリングの影響を受けにくくするため(効果があったかは不明)
  • ③黒フレーム挿入を実施

    • 60fps の黒ライン挿入済み静止画連番ファイルに黒フレームを挿入して 120fps の静止画連番ファイルにする
  • ④DaVinci で 120fps の H.265動画としてエンコード

    • プロファイルは Main 4:4:4 を選択すること[3]
    • 可逆圧縮となるようにすること
      • 少々乱暴だが今回は DaVinci の Deliverページにて Rate Control を Constant QP に設定した上で、各種 QP値を 0 に設定した

4. 感想

とりあえず作ってみたが、色々と問題点があると痛感した。ザッと列挙するだけでも以下がある。

  • iPhone の特殊な解像度の影響でスケーリングが適用されてしまう
  • iPhone の画面が小さすぎて 14型~21型の CRT と見え方が大きく異なる(今回は縦長表示とせざるを得なかった)
  • レトロな雰囲気を再現するなら、オリジナルコンテンツのスケーリングアルゴリズム[4] も考慮しなくてはならない

ここから更に検討を続けるのであれば、CRTの実機の準備、120Hz表示可能な大型の OLEDモニターの準備が必要になる。 これらの準備は困難であるため、本件はしばらく寝かせておくことにする。

参考資料

[1] みるみるコラム(TOA株式会社), "インターレース方式とプログレッシブ方式", https://www.toa.co.jp/miru2/column/column6.htm

[2] 栗田 泰市郎, "ディスプレイの時間応答と動画表示画質", 2012, VISION Vol. 24, No. 4, 154–163, http://www.visionsociety.jp/vision/vol24-4/vision2404_154-163.pdf

[3] toruのブログ, "可逆圧縮する場合に Chroma subsampling に 4:2:0 を指定するのはキケン", https://trev16.hatenablog.com/entry/2022/05/27/203620

[4] Wikipedia (EN), "Pixel-art scaling algorithms", https://en.wikipedia.org/wiki/Pixel-art_scaling_algorithms

可逆圧縮する場合に Chroma subsampling に 4:2:0 を指定するのはキケン

1. 背景

  • 前回の記事 の応用として「iPhone 13 を使った CRTライクなインターレース表示」用の動画をエンコードしていた
  • インターレース用に挿入する黒ラインの太さは 2px に設定していたため「まあ、Main プロファイル (4:2:0) でも大丈夫やろ」と思っていたのだが、全然そんなことはなく、色の破綻が発生した
  • 原因究明に至るまでに Chroma subsampling に関して幾つかの知識を得られたので、それをメモとして残すことにした

2. おことわり

例によって未来の自分向けの記事です。前提条件など色々と飛ばして書いています。ご了承下さい。

3. 結論

  • 筆者が日常的に使用しているエンコーダーでは、4:2:0 を指定した場合は可逆圧縮でも想定通りの結果が得られなかった
    • 原因は 4:4:4 to 4:2:0 変換時の Cb、Cr 値が筆者の想定と異なっていたため
    • また残念ながら、4:4:4 to 4:2:0 変換時の Cb、Cr 値の算出方法は外部から制御することができなかった
  • テストパターン作成時に 4:2:0 を指定するのはキケンだからやめよう
    • テストパターン作成時は 4:4:4 を指定しよう

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

4.1. そもそも何をしようとしていたのか

始めに、そもそも何をするつもりだったのか概要を書いておく。

4.1.1. CRTライクなインターレース表示

諸事情により筆者は図1~図4に示すようなインターレース表示を iPhone 13 Pro で試していた(※1)。 具体的には 60 fpsプログレッシブ信号に対して 2px または 4px の高さの黒ラインを挿入した動画を作成し、iPhone 13 Pro で表示していた。 筆者はこれを「CRTライクなインターレース表示」と呼んでいる。

※1 厳密に言うと黒フレーム挿入も行うのだが、本記事の本筋とは異なるためここでは特に触れない。

図1. フレーム番号 0 図2. フレーム番号 1 図3. フレーム番号 2 図1. フレーム番号 3

4.2. 発生した問題の詳細

前述の通り、黒ラインの高さは 2px or 4px としていた。そのため筆者は動画を H.265 の Mainプロファイル (Chroma subsampling 4:2:0) で可逆圧縮しても問題ないと考えていた。なぜならば、図5 に示すように 4:2:0 は 2x2 px の領域で Cb, Cr 成分を決定する方式だからである。黒ラインの高さが 2の倍数である分にはエンコード時の情報欠損が無いと考えていた(※2)。

※2 もう少し細かく書くと、Cb, Cr 成分は 2x2 px の加重平均で求まると考えていた。そのため、黒ラインの垂直方向の開始位置が偶数px であれば問題ないと考えていた。

図5. 4:2:0 における Cb, Cr 成分のマッピング(黄色枠の部分)。Wikipedia[1] より引用

しかし予想と異なり、実際は Main プロファイルで可逆圧縮すると予期せぬ色ズレが生じた。DaVinci Resolve で Main プロファイル (4:2:0) で圧縮した結果と Main 4:4:4 プロファイルで圧縮した結果の比較を図6に示す。

図6. 4:2:0 と 4:4:4 の違い

見て分かるとおり、Main プロファイルでは絵が暗くなっていることが分かる。

筆者は、どうしてこのような結果になったのか気になったため、追加調査を行うことにした。

4.3. 追加調査

適当なキーワードで Google 検索したところ、ITU-T H-series Recommendations - Supplement 19 [2] で気になる記述を見つけた。該当箇所を引用する(日本語訳は DeepL を使用した)。

For 4:2:0 chroma subsampling operations, it is important to make known the relative location alignment of the initial subsampling location processing of the content to avoid unnecessary quality degradation upon further content processing. For the purposes of this document, this property is described in terms of the ChromaLocType variable as defined in HEVC, which further corresponds with the value of the syntax elements chroma_sample_loc_type_top_field and chroma_sample_loc_type_bottom_field in HEVC and AVC. For NCG material, the usual alignment corresponds to ChromaLocType equal to 0 (vertically interstitial). For WCG material, the usual alignment corresponds to ChromaLocType equal to 2 (co-sited).


4:2:0 のクロマサブサンプリング処理では、コンテンツの最初のサブサンプリング位置処理の相対的な位置合わせを知ることが、その後のコンテンツ処理での不要な品質劣化を避けるために重要である。本書では、この特性を HEVC で定義されている ChromaLocType 変数で記述し、さらに HEVC および AVC のシンタックス要素 chroma_sample_loc_type_top_field および chroma_sample_loc_type_bottom_field の値で対応するものとする。NCG 素材の場合、通常のアライメントは ChromaLocType=0 (vertically interstitial) に相当する。WCG 素材の場合、通常のアライメントは ChromaLocType が 2(co-sited) に相当する。

筆者は ChromaLocType が何か知らなかったので H.265 の仕様書 [3] を参照した。すると以下の図7が見つかった。

図7. ChromaLocType の説明。H.265 の仕様書[3] より引用

これにより 4:2:0 において Cb, Cr は 2x2 px の加重平均とは限らないことが分かった。例えば ChromaLocType 2 では中心を含めた周囲の 9 px から Cb, Cr 値を決定している。この場合、冒頭で説明した CRTライクなインターレース表示の動画は可逆圧縮エンコードしたところで、確実に色ズレが発生してしまう。

以上の結果より冒頭の結論に書いた内容に至った。以上!

付録. FFmpeg と x265 を使った確認

以下の内容は本記事の主題からすると完全に蛇足なのだが、せっかく調査したのでメモを残しておく。

筆者は ChromaLocType = 1 を指定すれば、CRTライクなインターレース表示においては Main プロファイル (4:2:0) でも意図した可逆圧縮が可能になると考えた。 そこでパラメータの細かい制御ができない DaVinci Resolve ではなく FFmpeg と x265 を使って確認をしてみることにした。

x265 でエンコードを行うには、事前に 4:2:0 の YUV形式に変換が必要である。 YUV形式への変換は FFmpeg-c:v rawvideo -pix_fmt yuv420p オプションを指定すれば良い<要出典>。

今回は、図8 の画像を以下のオプションで変換した。

図8. FFmpeg を使った 4:4:4 to 4:2:0 変換の確認用パターン

ffmpeg -color_primaries bt709 -color_trc bt709 -colorspace bt709 -r 24 -loop 1 -i ./img/ana_420_offset_0-0.png -t 1 -c:v rawvideo -pix_fmt yuv420p -chroma_sample_location center ./videos/ana_420_offset_fmt-yuv420p_0-0.yuv

図8 は 16x12 のパターンである。dot mesh のサイズは 2x2、左端には 1px 幅の白ラインがある(バイナリエディタ確認用)。 理論値は以下である。

  • White: (Y, Cb, Cr) = (0xEB, 0x80, 0x80)
  • Magenta: (Y, Cb, Cr) = (0x4E, 0xD6, 0xE6)
  • Black: (Y, Cb, Cr) = (0x10, 0x80, 0x80)

なお理論値は以下で求めた。

    from colour import RGB_to_YCbCr, WEIGHTS_YCBCR
    K_709 = WEIGHTS_YCBCR['ITU-R BT.709']
    rgb = np.array([1, 1, 1])
    ycbcr = RGB_to_YCbCr(
        rgb, K=K_709, in_int=False, out_int=True,
        in_legal=False, out_legal=True, out_bits=8)
    print(f"0x{ycbcr[0]:02X}, 0x{ycbcr[1]:02X}, 0x{ycbcr[2]:02X}")

    rgb = np.array([1, 0, 1])
    ycbcr = RGB_to_YCbCr(
        rgb, K=K_709, in_int=False, out_int=True,
        in_legal=False, out_legal=True, out_bits=8)
    print(f"0x{ycbcr[0]:02X}, 0x{ycbcr[1]:02X}, 0x{ycbcr[2]:02X}")

    rgb = np.array([0, 0, 0])
    ycbcr = RGB_to_YCbCr(
        rgb, K=K_709, in_int=False, out_int=True,
        in_legal=False, out_legal=True, out_bits=8)
    print(f"0x{ycbcr[0]:02X}, 0x{ycbcr[1]:02X}, 0x{ycbcr[2]:02X}")

変換後の .yuv ファイルを VS Code の Hex Editor で確認したところ以下だった。

図9. .yuvファイルを Hex Editor で見た様子

そもそも H.265 でエンコードする前に 4:4:4 to 4:2:0 変換した時点で微妙にズレている。これではテストパターン生成時には使えない。残念無念。

ということで 4:2:0 を使うのは完全に諦めた。

感想

やっぱり検証用の動画は 4:4:4 でエンコードしないとダメですね…。

参考文献

[1] Wikipedia, "Chroma subsampling", https://en.wikipedia.org/wiki/Chroma_subsampling

[2] ITU-T H-series Recommendations - Supplement 19, "Usage of video signal type code points", https://www.itu.int/rec/T-REC-H.Sup19/en

[3] Recommendation ITU-T H.265, "High efficiency video coding", https://www.itu.int/rec/T-REC-H.265

[?] Douglas A Kerr, "Chrominance Subsampling in Digital Images", "http://dougkerr.net/Pumpkin/articles/Subsampling.pdf"

iPhone 13 Pro 用に 120 fps のテストパターンを作って遊んだ

1. 背景

  • 筆者は昨年、非常に高価な iPhone 13 Pro を購入した
  • ふと「スクリーンタイム」を使って使用時間の多いアプリを確認したところ以下だった
  • 筆者の使い方では先々代スマホiPhone 7 Plus でも全く問題がないことに気づいてしまった
  • これはマズいと思い、iPhone 13 Pro のスペックを活かせるテストパターンを作ることにした

2. 目的

  • iPhone 13 Pro のスペックを活かしたテストパターンを作って遊ぶ

3. 結論

iPhone 13 Pro の ディスプレイが 120 Hz 表示可能な点を利用して、以下の特徴を持つテストパターンを作成した。

  • 60 Hz と 120 Hz の違いが目視確認できる
  • 60 Hz の信号に黒のフレームを挿入することで動画ぼやけの軽減を目視確認できる

作ったものは残念ながら iPhone 13 Pro 上でしかデモができない。どうにか雰囲気を伝えるために iPhone の画面を 240 fps 撮影して 1/8倍速再生したものを以下に示す。

上段のパターンは 60 fps で動いており、再下段の 120 fps と比較して動画ぼやけが目立つことを確認できる。 また中段のパターンは、黒フレームを挿入したことで動画ぼやけの改善を確認できる(繰り返すが iPhone の実機を使わないと効果は目視確認できない)。

作成したファイルは以下に置いた。

drive.google.com

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

4.1. テストパターンを 120 Hz で表示する方法の確認

まず、どうすれば iPhone 13 Pro を使い 120 Hz でテストパターンを表示できるか調べた。 調査の結果、以下の手順で表示できることが分かった。

  • ① テストパターンを 120 fps の静止画シーケンスファイルとして作成する
  • ② DaVinci Resolve を使って 120 fps の動画ファイルにエンコードする (コーデックは H.265)
  • ③ 動画ファイルを iPhone の Files アプリを使って再生する

4.2. 60 fps と 120 fps の違いを確認するパターンの作成

まず手始めに、白 Window を左右に動かすパターンを作り 60 fps と 120 fps の違いを比較した。 120 fps の方がカクつきが無く良い見た目となることが分かった(当たり前だが)。

ただ、非常に簡素なテストパターンであり、正直見ていて面白くなかった

4.3. 少し凝ったパターンへの改良を実施

白 Window は動かしても面白くなかった。そこで模様を付けることにした。 高周波成分が存在し、動かすことで動画ぼけを視認できるような模様を考えて付与した。

熟考の結果、以下に示す3種類の模様を付与した。60 fps で動かした様子を以下に示す。

4.4. BFI (Black Frame Insertion) の実施

少し話が逸れるが、筆者は RTINGS.com で TV のスペックを確認することが多い[1]。 先日も LG OLED TV の 2022年モデルのスペックを確認していた。

OLED TV の "Black Frame Insertion (BFI) " の項目を見ていた際、筆者は「これと同じことは iPhone 13 Pro でも実現できるのでは?」と思った。

BFI とは LCD や OLED の「ホールド型」表示が原因で生じる動画ぼやけを改善するための機能である (※)。 ひとまず LG C2 OLED の特性を真似して、120Hz 駆動の iPhone 上で BFI を試すことにした。

※10年以上前からある考え方であり、少し検索するだけで様々な論文や解説記事が出てくる[2][3]。よって原理などは本記事では説明しない。

具体的にはテストパターンに対して以下を施した。

  • 60 fps on 120 fps の動画の奇数フレームを黒画面に変更
  • パターンの輝度を2倍に上げる (黒フレーム挿入で輝度が半分に落ちるため)

作成した動画を 1/16倍速再生している様子を以下に示す(画面が明滅しますのでご注意下さい)。

こうして作成した動画を iPhone 上で再生した結果が冒頭の動画である。

5. 感想

スマホと PC があれば、誰でも簡単にこうしたパターンを作って遊ぶことができる。楽しい!

本当は iPhone 上で CRT っぽくインターレース表示をする動画も作りたかったが、GW中は別件の調べ物があるので断念した。モチベが残ってたらそのうち作りたい。

参考資料

[1] RTINGS.com, "TV REVIEWS", https://www.rtings.com/tv/reviews

[2] 栗田 泰市郎, "ディスプレイの時間応答と動画表示画質", 2012, VISION Vol. 24, No. 4, 154–163, http://www.visionsociety.jp/vision/vol24-4/vision2404_154-163.pdf

[3] Capriccioso Assai, "液晶の応答速度と残像の関係", https://capricciosoassai.blog.fc2.com/blog-entry-116.html