toruのブログ

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

ColorCheckerのRGB値を分光反射率データから求める

1. 目的

  • ColorCheckerのRGB値を分光反射率(spectral reflectance)データから求める
  • Chromatic Adaptation や「新しいXYZ表色系」の簡単な実験をする(これは別記事にする予定)

2. 背景

色彩工学の理解を深めたかった。なんとなく理論は知っていたが、実際に計算したことが一度も無かったため手を動かして確かめることにした。

3. 結論

国際標準[1-3]に準拠した方法でRGB値の算出に成功した。結果を図1に示す。

f:id:takuver4:20190524223646p:plain
図1. 分光反射率からColorCheckerを算出した様子

4. 作業手順

4.0. 概要

作業手順を簡単にまとめると以下の3点となる。

  1. ColorChecker の24パッチの分光反射率データを準備
  2. ColorChecker の24パッチの XYZ値を計算
  3. XYZ to RGB 変換の実施

本記事では以後、手順1. および手順2. について詳しく解説する。手順3. は既に様々なところで解説記事があるため本記事では特に言及しない。

なお、本記事の内容は全て CIE 1931表色系での話となる。CIE 1964表色系でのRGB値の計算は行わない。

4.1. ColorChcker の24パッチの分光反射率データを準備

BabelColor がデータを公開している[4] のでそれを使う。2006年版と2012年版が存在するが、古い方を選択する理由が無いため2012年版を使用する。

4.2. ColorChecker の24パッチの XYZ値を計算

4.2.1. 数式の定義

物体色の X, Y, Z 三刺激値(tristimulus values) を求める数式は以下で定義されている[5]。

 \displaystyle
\begin{aligned}
X &= k \int \!{\scriptsize\text{vis}} \; \varphi(\lambda) \bar{x}(\lambda) d\lambda \\
Y &= k \int \!{\scriptsize\text{vis}} \; \varphi(\lambda) \bar{y}(\lambda) d\lambda \\
Z &= k \int \!{\scriptsize\text{vis}} \; \varphi(\lambda) \bar{z}(\lambda) d\lambda \\
\end{aligned}

ここで  \int {\scriptsize\text{vis}} は可視波長域で積分することを意味する。また  \varphi(\lambda) は物体色の色刺激(color stimulus) を意味する。  R(\lambda) を試料の分光反射率、 S(\lambda) を照明光の相対分光分布(relative spectral distribution) と置くと  \varphi(\lambda) = R(\lambda) S(\lambda) である。最後に  k は正規化の係数である。

しかし、実際は上記のような極小波長での積分は物理的に不可能であるため、一般的には以下のように  \Delta \lambda = 1 {\text{nm}} として計算を行う[3]。

 \displaystyle
\begin{aligned}
X &= k \sum_{\lambda} \varphi(\lambda) \bar{x}(\lambda) \Delta \lambda \\
Y &= k \sum_{\lambda} \varphi(\lambda) \bar{y}(\lambda) \Delta \lambda \\
Z &= k \sum_{\lambda} \varphi(\lambda) \bar{z}(\lambda) \Delta \lambda \\
\end{aligned}

ここで  \lambda の範囲は 360 nm ~ 830 nm である[3]。 また正規化係数  k は以下で計算する[3]。

 \displaystyle
\begin{aligned}
k &=100 / \sum_{\lambda} S(\lambda) \bar{y}(\lambda) \Delta \lambda
\end{aligned}

4.2.2. 計算に必要なデータの整理

4.2.1. にて数式は定義した。続いて準備が必要なデータを整理する。準備が必要なのは以下の3つである。

  • ColorChecker の分光反射率  R_i(\lambda) ( i は 0 ~ 23 の数値)
  • 照明光の相対分光分布  S(\lambda)
  • 等色関数  \bar{x}(\lambda), \bar{y}(\lambda), \bar{z}(\lambda)

4.2.3. ColorChecker の分光反射率  R_i(\lambda) の準備

4.1. でダウンロードした BabelColor の測定データを使用する。 ただし、このデータは 10 nm ステップのデータであるため、1 nm ステップへの補間計算が必要である。

補間アルゴリズムには Sprague Interpolation を用いる()[6]。

筆者は予算が尽きて[6]を購入できず読んでいない。従って補間アルゴリズムが本当に Sprague Interpolation で良いのかは裏が取れていない。しかし、Colour Science for PythonMultiSpectralDistribution クラスのコメント[7] を読む限りでは Sprague Interpolation で正しいようなので、本記事ではこの補間アルゴリズムを使用する。

また、BabelColor の測定データは 380 nm ~ 730 nm であった。一方で計算を行う範囲は 360 nm ~ 830 nm である。データの無い波長は値を0として計算した。CIE S 014-3 にて外挿(Extrapolation) によりデータを補間する方法も提案されているが[3]、使用が必須ではないため今回は外挿は行わないこととした。

4.2.4. 照明光の相対分光分布  S(\lambda) の準備

CIE S 014-2 に記載のD65の照明光を使う[2]。これは 1 nm ステップで定義されているためそのまま使用可能である。

4.2.5. 等色関数  \bar{x}(\lambda), \bar{y}(\lambda), \bar{z}(\lambda) の準備

CIE S 014-1 に記載の値を使う[1]。これは 1 nm ステップで定義されているためそのまま使用可能である。

4.2.6. 計算の実行

4.2.1 ~ 4.2.5 の内容を使って XYZ値を計算すればOK。

5. 計算例

筆者のコードはコレ

個人的に Colour Science for PythonMultiSpectralDistribution, SpectralDistribution クラスが大変便利だった。 波長の範囲の選択する trim と補間計算を行う interpolate の利用によって実装時間を大幅に短縮できた。感謝。

6. 感想

色彩工学の基本中の基本であるXYZ計算をやっと行うことができた。まだまだ勉強したい内容が山ほどあるので今後も頑張る。

参考文献

[1] ISO 11664-1:2007(E)/CIE S 014-1/E:2006. Colorimetry – part 1: CIE standard colorimetric observers.

[2] ISO 11664-2:2007(E)/CIE S 014-2/E:2006. .Colorimetry – part 2: CIE standard illuminants.

[3] ISO 11664-3:2012(E)/CIE S 014-3/E:2011. Colorimetry – Part 3: CIE Tristimulus Values.

[4] BabelColor. THE COLORCHECKER PAGES (2/3). http://www.babelcolor.com/colorchecker-2.htm (2019/05/25 確認)

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

[6] CIE 167:2005. Recommended practice for tabulating spectral data for use in colour computations. 2005.

[7] Colour Science for Python. colour.MultiSpectralDistribution. https://colour.readthedocs.io/en/v0.3.13/generated/colour.MultiSpectralDistribution.html#colour.MultiSpectralDistribution (2019/05/25 確認)