豪鬼メモ

一瞬千撃

スケール対数曲線による自然な彩度補正

画像の輝度をスケール対数曲線で補正するという話を以前の記事で述べたが、それを彩度の調整に応用してみた。
f:id:fridaynight:20181121233638j:plain


冒頭に挙げた画像は、彩度を著しく高めてある。つまり色を濃くしてある。確かにかなり鮮やかな仕上げになっているが、そんなに不自然な感じもしないだろう。人の肌の色の違いは敏感に感じとるように人間はできているので、人が写っていない例も見てみよう。これも同じように彩度を劇的に高めているが、不自然さがあまりない。雑誌とかポスターとかだと目立つように濃い仕上げになっていることはよくあるので、見慣れた仕上げとも言える。
f:id:fridaynight:20181121234444j:plain

上の画像を見た後に、彩度を調整していないこの画像を見ると、なんだか味気なく感じてしまう。味の素のグルタミン酸で舌が麻痺した状態みたいな。
f:id:fridaynight:20181121234639j:plain


そんなわけで、彩度を高くして目立つ仕上げにしたいということはたまにあるだろう。その際には現像ソフトやレタッチソフトで彩度を上げる操作を行うことになるのだが、それを自動化するにはどうするか。ImageMagickでは例によって数式で全てを表現しなければいけない。RGB空間の輝度の調整にトーンカーブを適用するように、HSL空間の彩度の調整にトーンカーブを適用することもできる。例えば彩度を2倍にしたい場合には、以下のようなコマンドを実行する。画像の各チャンネルのデータをHSLに変換してから、その2番目のチャンネル(RGBのG、HSLだとS)に着目して、値を2倍にする。それから全チャンネルをsRGB空間に変換して、出力している。

$ convert input.jpg -colorspace hsl -channel g -evaluate multiply 2 +channel -colorspace srgb output.jpg

上記の-evaluateオペレータの部分を任意の数値処理に変えることで、彩度の自由な調整を行うことができるようになる。ところで、線形変換には常に飽和の問題がつきまとう。彩度の文脈で言うと、色飽和の問題がつきまとう。彩度の80%の画素を2倍したら160%になってしまうが、それは100%に切り下げられてしまう。つまり2倍にする操作では、彩度50%以上の画素の彩度は全て同じになってしまい、結果としてペンキ絵のように「のっぺり」とした仕上がりになってしまう。その対策として、彩度に対するガンマ補正をするという記事を以前に書いたが、今回はそこでスケール対数補正を適用してみることにした。上で挙げた例はその結果だ。こんなコマンドを実行すればよい。

$ convert input.jpg -colorspace hsl -channel g -evaluate log 1 +channel -colorspace srgb output.jpg

ちなみにLightroomでは、彩度の線形変換は「Saturation」とか「彩度」とかいうスライダーで調整して、非線形変換は「Vibrance」とか「自然な彩度」とかいうスライダーで調整する仕様になっている。非線形変換の数式が具体的にどのようになっているのかはしらないが、色飽和しないように気を使っていることは間違いない。すなわち低い彩度の画素は大幅に彩度を高くして、すでに高い彩度の画素はあまり変化させないようにする。経験上、色飽和が気にならない範囲であれば、彩度の補正は線形変換で行なった方が自然な結果が得られることが多い。線形変換してみて色飽和が気になった場合には、非線形変換を使うようにするとよい。しかし、自動化するとなると、そのような試行錯誤はできないので、とりあえず非線形変換に頼るというのが現実的だ。


線形補正、スケール対数補正、ガンマ補正の挙動を可視化して比較しよう。彩度50%の画素を60%に変換するとしてみよう。その場合、線形補正なら 0.5 * 1.2 = 0.6 という変換を行う。スケール対数補正の場合、log(1+1.3*0.5)/log(1+1.3) = 0.6 という変換を行う。ガンマ補正の場合、0.5 ^ (1/1.36) = 0.6 という変換を行う。その際の他の値がどうなるかを表とグラフで示す。各補正の逆関数についても載せている。

x linear 1 linear 1.2 liner 0.83 s-log 1.3 s-exp 1.3 gamma 1.36 gamma 0.73
0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
0.0250 0.0250 0.0300 0.0208 0.0384 0.0162 0.0664 0.0066
0.0500 0.0500 0.0600 0.0417 0.0756 0.0327 0.1105 0.0170
0.1000 0.1000 0.1200 0.0833 0.1467 0.0668 0.1840 0.0437
0.2000 0.2000 0.2400 0.1667 0.2775 0.1394 0.3062 0.1120
0.3000 0.3000 0.3600 0.2500 0.3954 0.2184 0.4126 0.1945
0.4000 0.4000 0.4800 0.3333 0.5027 0.3041 0.5098 0.2876
0.5000 0.5000 0.6000 0.4167 0.6012 0.3974 0.6007 0.3896
0.6000 0.6000 0.7200 0.5000 0.6923 0.4987 0.6869 0.4992
0.7000 0.7000 0.8400 0.5833 0.7769 0.6088 0.7693 0.6156
0.8000 0.8000 0.9600 0.6667 0.8560 0.7285 0.8487 0.7382
0.9000 0.9000 1.0800 0.7500 0.9301 0.8586 0.9255 0.8665
1.0000 1.0000 1.2000 0.8333 1.0000 1.0000 1.0000 1.0000

f:id:fridaynight:20181122000843p:plain

既述のように、線形補正の欠点は色飽和である。上記だと、彩度80%くらいから上は全て100%に張り付いてしまう。一方でスケール対数補正とガンマ補正は変域を維持するので、飽和は起きない。輝度の補正と同様、ガンマ補正は値が低い部分の影響がとても大きいという特徴がある。つまり彩度の文脈で言えば、色がとても薄いものをやたらと濃くしてしまう。スケール対数補正は低い彩度の部分の挙動は線形補正に近く、それでいて高い彩度の部分の挙動はガンマ補正と似たものになる。したがって、ガンマ補正よりもスケール対数補正の方が良い結果が得られるのではないかという仮説が立つ。


実際の画像に適用するとどうなるか。

元画像。
f:id:fridaynight:20181122003125j:plain

線形補正1.2。
f:id:fridaynight:20181122003259j:plain

スケール対数補正1.3。
f:id:fridaynight:20181122003314j:plain

ガンマ補正1.36。
f:id:fridaynight:20181122003327j:plain

元画像。
f:id:fridaynight:20181122003405j:plain

線形補正1.2。
f:id:fridaynight:20181122003518j:plain

スケール対数補正1.3。
f:id:fridaynight:20181122003500j:plain

ガンマ補正1.36。
f:id:fridaynight:20181122003532j:plain

元画像。
f:id:fridaynight:20181122003645j:plain

線形補正1.2。
f:id:fridaynight:20181122003657j:plain

スケール対数補正1.3。
f:id:fridaynight:20181122003714j:plain

ガンマ補正1.36。
f:id:fridaynight:20181122003730j:plain

元画像。
f:id:fridaynight:20181122003754j:plain

線形補正1.2。
f:id:fridaynight:20181122003827j:plain

スケール対数補正1.3。
f:id:fridaynight:20181122003846j:plain

ガンマ補正1.36。
f:id:fridaynight:20181122003858j:plain

予想通り、多くの場合で、線形補正が最良になっている気がする。ただ、トマトの例のように色飽和しがちな場合、スケール対数補正の方がより自然な仕上がりになっている。全体として線形補正とスケール対数補正は区別がつかないくらい似ているので、スケール対数補正だけ使っていれば潰しがきくともいえる。Lightroomの彩度調整のデフォルト表示が非線形のVibranceなのはその汎用性が理由かもしれない。ガンマ補正は、本来色が薄いはずのものが不自然に濃くなりすぎるので、あまり良いところがない。


色を薄くしたい場合にはどう考えればいいか。彩度を低める分には色飽和の心配はしなくていいので、常に線形補正を使えばいいというのが現実的なところだ。でもいちおうそれぞれの補正で逆関数が定義できることだから、試してみよう。線形補正の逆関数はただ割り算をすればよい。スケール対数ログの逆関数は (exp(v*log(1+C))-1)/C だ。ガンマ補正の逆関数は v^C だ。

元画像。
f:id:fridaynight:20181122003754j:plain

逆線形補正1.2。
f:id:fridaynight:20181122005040j:plain

逆スケール対数補正1.3。
f:id:fridaynight:20181122005052j:plain

逆ガンマ補正1.36。
f:id:fridaynight:20181122005116j:plain

元画像。
f:id:fridaynight:20181122003645j:plain

逆線形補正1.2。
f:id:fridaynight:20181122004821j:plain

逆スケール対数補正1.3。
f:id:fridaynight:20181122004849j:plain

逆ガンマ補正1.36。
f:id:fridaynight:20181122004908j:plain

やはり線形補正の結果が最も違和感がなく鑑賞できる気がする。とはいえ、線形補正だと彩度の最大値が低くなるので、いかにも加工した感が出てしまう。加工したんだか本当に色が薄かったのだかバレないようにしたい場合には、逆スケール対数補正を検討してもいいかもしれない。逆ガンマ補正に出番はなさげ。


まとめ。輝度の補正にスケール対数補正が活躍するように、彩度の補正でも結構使えることがわかった。各種補正方法を試しても、それぞれの出力例を並べて比較しないとわからないような微妙な違いしか生じないことも多いだろうが、ならば最も潰しがきくスケール対数補正をとりあえず使っておくというのは実践的な解だと思う。君もやってみてネ。

ソニー SONY デジタルカメラ Cyber-shot DSC-RX10M4

ソニー SONY デジタルカメラ Cyber-shot DSC-RX10M4