postprocess関数の引数をひとつづつ動かしながら確認していきます。今回はwhite balanceをいじってみます。
postprocessに関しての詳細はこちら。
white balance
言わずもがなですが、白基準を取ることです。照明色の影響をもろに受けているセンサのRGBの値を補正して、思った白に補正することです。詳細説明は圧愛しますが、ここでは画像処理の観点で説明します。
演算としては、センサで取得された値に対して、black levelを差し引いたRGBのデータに対して、ゲインをかけている(掛け算している)だけです。このゲインがRGB異なり、結果として全体の色合いが変化します。
通常Greenを1倍として、RedとBlueに対して何倍するか?というのが設定の基本になっているようです。たいていcamera autoの場合Greenが一番小さいです。もちろん得たい色次第でしょうけれど。具体的には
$$R_{out}=1.40\times R_{in}\\ G_{out}=1.00\times G_{in}\\ B_{out}=1.20\times B_{in} $$
なイメージ。被写体にあたる光の波長が違えば反射してセンサに届く波長も違うので、それを人の見た印象に補正してあげるイメージですかね。
おそらくセンサに張り付いているGreenのカラーフィルタが一番光を通すのだと思います。太陽光のようにどの波長の光もまんべんなくある白色光の場合、おそらくGreenがどうしても一番でかくなるのではないかと予想されます。たぶん。なので、光電変換の効率もよく、値も大きくなるのではなかろうか。もしくは他の色の倍センサがのっかっている分有利なのかな?真相はわかりません。
rawpyでのホワイトバランス補正
どうやら現像時postprocess関数では、3つのオート調整と、完全マニュアルの4通り選べそうです。
カメラホワイトバランス(use_camera_wb)
use_camera_wbがカメラで記録したホワイトバランスを使うオプションです。これをTrueに設定することで使用できるようです。(デフォルトはFalse)このホワイトバランスの値は別途、
import rawpy raw = rawpy.imread(filename) wb = raw.camera_whitebalance
でも取得可能です。ココには、長さ4のlistで値が入っています。例のごとく0, 1, 2, 3がそれぞれ何の色に対するゲインか定義は見つけりませんでしたが、実験より、RGB順で値が入っていそうです。
リファレンスには、ファイルから読み取るか、計算されます。とあるのでファイルについてなくてもなんらか返ってくるようです。
ここで取得される値の範囲がまた難しい。Canonのカメラだと1024とか整数値が取得されるのに対して、olympusでは、1.00とか1.97とか実数の値が入ってます。乗じる際には正規化が必要そうですね。
オートホワイトバランス(use_auto_wb)
use_auto_wbをTrueにすることで、オートでホワイトバランス調整をしてくれます。が、アルゴリズムがわかりません。camera_wbとも違う色合いになります。確かめてみながら、写真次第ですね。
ユーザーホワイトバランス(user_wb)
ここに長さ4の配列を設定することで、任意のホワイトバランス(RGBに対するゲイン)を設定することができます。camera_whitebalanceで取得した配列をそのまま渡すと、use_camera_wbと同じ結果が得られています。
相変わらず4の意味が分かりません。適当な値を入れておくと画像が壊れるので、意味はあるようです。正規化のための除算値かな?とも思ったのですが、olympusさんのcamera_wbはこの4番目が0.0なので、ゼロ除算です。ひとまずGreenと同じ値入れとけば大きな間違いは起こらなそうです。
user_wb = [1.40, 1.00, 1.20, 1.00]
としてpostprocess関数を呼ぶと、上述した、
$$R_{out}=1.40\times R_{in}\\ G_{out}=1.00\times G_{in}\\ B_{out}=1.20\times B_{in} $$
この演算がされているような結果に見えます。
デイライトホワイトバランス
一見これを指定するオプションが無いように見えますが、camera_wbもauto_wbもFalseで、user_wbに指定する配列もNoneにすると、このホワイトバランスになるようです。隠しオプションみたいですが、これがデフォルトです。わかりにくいです。
このデイライトホワイトバランス(日本語で言うと太陽光なのかな)の値も、取得可能です。
mport rawpy raw = rawpy.imread(filename) wb = raw.daylight_whitebalance
こんな感じ。これも同じように、リファレンスでは、「ファイルから読むか、計算するか、ハードコードされた値を使います。」とあり、場合によっては固定値かもしれません。センサの特性によって固定値では合わないのでは…?と心配になってしまいます。
実験
Camera WBの値が、R=2189, G=1024, B=1862のバランスから、じょじょにGreenの値を大きくしていき、Blueを追い抜き、最終的にRedと同じ値になるまでのヒストグラムの変化を見て行こうと思います。
ここで、注意事項。ガンマは1.0に設定しておきます。そうでないと乗算している様子がわかりにくい。あと、輝度補正もしない(no_auto_bright=True)。
そして最初これをしそびれていて、どうしても変化が思った通り行かなかったのですが、ColorSpaceをRAWに設定しておく必要がありました。デフォルトのsRGBとかだと、マトリクス演算が入って、cameraRGB から sRGBへの色変換が行われ、思った通りのヒストグラム変化をしませんでした。
img = raw.postprocess(output_color=rawpy.ColorSpace.raw, user_wb=usr_wb, no_auto_bright=True, gamma=[1.00,1.00] )[:, :, [2, 1, 0]]
やはりここから分かるのは、ホワイトバランス補正を行った後に、sRGBへの変換をしていそうです。まぁ当たり前か。
これがその結果。 R=2189, G=1024, B=1862のバランスなので、Redに注目すると、最初ほぼGreenの2倍のゲインがかかっている状態です。これで初めてGreenとRedのヒストグラムの幅がほぼ同じに揃います。最後はGreenとRedのゲインがそろうので、相対的にRedのヒストグラムの幅は、Greenの半分になっていく様子がわかります。(同じ幅にそろえようとすると、RedはGreenの2倍のゲインが必要。ということですね。)
GreenのWB値を大きくなるように動かしているのに、RedとBlueのヒストグラムが左に変化(しぼんでいく)しています。ここからGreenか、最小値での正規化が入っていることが予想されます。
その後GreenのWB値が、BlueのWB値(1862)を追い抜いたところで、BlueのWB値が最小値に入れ替わるので、GreenとRedのヒストグラムが動いていく。といった動きになっています。
まとめ
Rawpyには4つのホワイトバランス調整の手段があるようだ。
ホワイトバランスは4つの値の最小値で正規化(R, G, BのWB値の最小値を1.0倍として正規化)されたゲインをRGBに乗じることで計算されているようだ。
以上。ホワイトバランス調査でした。
コメント