【Python】色温度の放射スペクトルやカラーチェッカーの反射スペクトルをプロットする

# はじめに

色のスペクトルを扱うためのライブラリでcolour というのがあります。
スペクトル情報を扱う SpectralDistribution というクラスがの使い標題のようなことができました。メモしておきます。

これ、教科書的でもあり、便利でもありすごいです。。。

https://colour.readthedocs.io/

# 内容

## SpectralDisbribuition を数値データから作成する

下記の内容をフォローしています。

https://colour.readthedocs.io/en/latest/basics.html

### 黒体輻射のスペクトルをプロットしてみる

放射スペクトルの情報を```colour.colorimetry.spectrum.SpectralDistribution```に保持するようにしてみます。
ある色温度のスペクトル情報のインスタンスは、波長と値のペアを持つ辞書から作成できます。
また、黒体輻射のプランクの公式は関数が用意された関数で計算できるのでそのまま利用させていただきました。

numpy に似た構造をしていますが、引数の波長にはもとのデータにない波長を指定することもできます。
波長について値を補間して計算してくれます。

```python
import math
import colour
from scipy.constants import c,k,h
import matplotlib.pyplot as plt

C1 =  2 * math.pi * h * c ** 2 # 2 * math.pi * PLANCK_CONSTANT * LIGHT_SPEED ** 2 = 3.741771e-16 
C2 =  h * c / k # PLANCK_CONSTANT * LIGHT_SPEED / BOLTZMANN_CONSTANT = 1.4388e-2

temperature = 5000
wavelengths = colour.colorimetry.spectrum.SpectralShape(350, 850, 5).range()
sd5000k = colour.colorimetry.spectrum.SpectralDistribution(
    name='{0}K Blackbody'.format(temperature),
    data=dict(zip(wavelengths,
                  colour.colorimetry.planck_law(wavelengths * 1e-9, temperature, C1, C2, 1))))

print("wavelength: ", sd5000k.wavelengths)
print("values: ", sd5000k.values)

print(f"Radiation of {temperature} K bloack body at 503[K] is {sd5000k[503]:12.4e}")

fig, ax = colour.plotting.plot_single_sd(sd5000k, cmfs = 'CIE 1931 2 Degree Standard Observer',)
fig.savefig("ct5000k_sd.png")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294040/8c4f36a9-cedf-6a65-0d43-9c9b22a3a95f.png)


波長とスペクトルのペアから作れます。スペクトルは放射や照明、反射係数など全ての場合に共通して使えるようです。
例えば照明情報として下記は ```colour.colorimetry.spectrum.SpectralDistribution```が出力されます。

```python
illuminant = colour.SDS_ILLUMINANTS["D65"]
print(type(illuminant))
```

また、波長分解能が２つのspectral distributionで異なる場合があります。そのときはalign というメソドを利用して所望のSpectralShape に割り当てなおしてくれるようです。あちこちで補間の計算を実行してくるます。
そして、スペクトル同士の加減乗除の計算ができます。

描画には単一のスペクトルと、複数のプロットを比較する場合で```plot_signal_sd(sd)``` や ```plot_multi_sds([sd1, sd2])``` がそれぞれ使えます。


## カラーパッチ

Color Checker に含まれている Spectral Disbribution もライブラリに含まれていました。
まず、下記でカラーチェッカーを保存できました。

```python
fig, ax = colour.plotting.plot_single_colour_checker()
fig.savefig('color_checker.png')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294040/c6a0de20-d44b-27cd-963b-e3b24821d4fc.png)


```python
checker = colour.characterisation.SDS_COLOURCHECKERS.get('BabelColor Average')
sd_red = checker.get('Dark Skin') 
```
でspectral distribution を取得できるので、いろいろできます。

# まとめ

とりあえずcolour をインストールして色温度に対応する黒体輻射スペクトルの情報を取得し、便利な描画もできました。いろいろ使えるかな。。。

下記は、調査の過程で出会ったサイトのメモです。世の中、情報を共有してくれて便利なツールを共有してくれて感謝。

- Find color temperature from spectral response
  https://stackoverflow.com/questions/62776729/find-color-temperature-from-spectral-response

- Converting a Spectrum to a Colour
  https://scipython.com/blog/converting-a-spectrum-to-a-colour/

- 日本語でカラーチェッカーの分光反射率の取得方法を記述
 https://yamagishi-2bit.blogspot.com/2022/01/colour-science-spectraldistribution.html

- HDRの計算
https://www.colour-science.org/colour-hdri/

- Colour Tutorial
  https://colab.research.google.com/drive/1Im9J7or9qyClQCv5sPHmKdyiQbG4898K

- Colour 
  https://readthedocs.org/projects/colour/downloads/pdf/latest/

  以上。
  (2024/5/18)