Processingで画像処理をする - クロスプロセス
今回は「procesingで画像処理をする」の続編になるが、「デジタルクロスプロセス」という処理方法を述べたい。
いや、実はこの画像処理は手法が確立されていない技術で、大学で僕が考えた方法を改めてここに書き留めておきたいと思うのだ。
クロスプロセスとは
そもそもクロスプロセスとは、写真を現像する際に用いられる技術である。写真を現像するときに持っていくフィルムにはポジフィルムとネガフィルムがある。いわゆる「ネガ」である。
これらにはそれぞれ対応する現像方法があり、それによって正しく現像されるのである。
クロスプロセスとは、この現像方法を入れかえてしまおうという手法である。
そして、これを現実のフィルムを使わずにデジタルで表現しようというのがデジタルクロスプロセスである。
デジタルにおけるクロスプロセス
おそらくもっとも身近なデジタルクロスプロセスといえば「Instagram」というアプリだろう。画像を共有するサービスで、
TwitterやFacebookなどへスマホの写真を投稿する時に画像を「ちょっといい感じ」に加工することができる。
こちらは専用のフィルターが用意されていて、非常にクロスプロセスっぽい画像ができあがる。ただ輝度をいじったりするのとは違い、独特の雰囲気が好まれているようだ。
Processingでクロスプロセス
前回、Processingを使うことで比較的簡単に画像処理ができることを述べた。
今回も、get()した情報に何らかの変更を加え、それをset()することで反映させる1ピクセル対1ピクセルの処理で実装したいと思う。
どう実装するか
前述したとおり、デジタルクロスプロセスには決まった手法がない。そこで、僕はまず既存のデジタルクロスプロセスがどのように行われているのかを調べてみた。
僕が参考になると思ったのはPhotoshopによる処理方法であった。Photoshopにはトーンカーブでのコントラスト調整をする際に、クロスプロセスのテンプレートがあるらしいのだ。
僕はPhotoshopのテンプレートの値をそのままプログラムに落とし込めば簡単に作れるのではないかと考えた。しかし、これではただのパクリだ。それによく調べてみると、多くの場合はこのテンプレートを画像によって好みになるように調節しながら使うらしいことが分かった。
そこで僕は、トーンカーブを使うというのはそのままに既存の数値にとらわれない新しい方法でデジタルクロスプロセスを実装することに決めた
トーンカーブ
いきなり「トーンカーブ」という言葉を出してしまったが、まずはこれがどんなものか説明したい。トーンカーブとは、入力されるデータ値をx軸に、出力されるデータ値をy軸にとった時のxとyの関係をグラフに表したものである。多くの場合は曲線になる(例外ももちろんある)ため、トーン(色調)のカーブ(曲線)ということでトーンカーブと呼ばれる。
画像処理をするときに、r,g,bの全域に対して、一つ一つ数字を対応させるのは大変である。そこで、曲線をマウスをつかってグニャグニャいじることで感覚的にフィルターを作れるのである。
それでは、トーンカーブを数式と考えてみたらどうだろう?もしデジタルクロスプロセスに使われるテンプレートの”形”を数式で定義できれば、パラメータを変えることでより本物のクロスプロセスに近い処理をすることができるのでないだろうか。
キーワードは”S字”
さっそくいろんなサイトでトーンカーブについてみて回る。そして気付いたのだが、デジタルクロスプロセスに使われるトーンカーブはS字の形をしていることが多い。曲率は違えど皆S字を使っている。これはラッキーである。S字なら高校数学で散々付き合ったではないか。「3次関数」があるじゃないか!
と、ここまでは安易に考えていたのだが、すぐに問題が発覚した。
3次関数では自由度が高すぎるのだ。高校のときに極値だか変曲点だか習ったが、いずれも「無い」場合がある。つまり、3次関数は必ずしもS字になるとは限らないのだ。
なんとかS字だけになるようにパラメータ(各項の係数)を制限しようと試みたものの、あれこれ数字が動くので難しすぎる。東工大の奴とかに解かせてみたいぐらいだ。「3次関数がS字となる係数を全てあげ、数式でその条件を述べよ」こんな問題を解く頭は僕にはないので、他の数式でS字を作るものはないかと考える。
シグモイド関数
そんな中で採用することにしたのがこのシグモイド関数。まさにS字を描く関数で、パラメータも2つですむことが分かった。
数式は以下の通りである。まず、
G0 = 255/(1+exp(-γ(u-127.5)))
とおく。ここでγ(ガンマ)を1/30にすることで、uが0~1のときちょうどgが0~255になる。
これを以下の式のように組み込む。
yc=kc{xc+bc(G0(xc)-xc)}
xcが入力でycが出力である。kc,bcがパラメータとなり、それぞれ0~1で指定すればよい。
これで準備は整った。
コーディングする
以下がコードである。
上のコードをただ写しただけでは真黒な画像になってしまう。パラメータとして、k(r,g,b),b(r,g,b)に0~1の値を入れることで、きちんと動くようになる。
処理前
処理後
終わりに
今回はデジタルクロスプロセスに焦点を当ててみた。実はこの勉強は続きがあるのだが…
次に画像処理について扱うときはグリッチとかテーマにしてみようと思う。