OpenCVで写真を漫画風に加工してみよう 〜手法編〜
最近iOS界隈では漫画風に画像を加工するカメラアプリが人気を博しております。写真に何らの加工を施すには、画像処理技術が必要です。画像処理と聞くと敷居が高そうに思われる方も多いかと思いますが、実はそんなに難しくありません。難しくないと言っても、じゃあ作ってみろよと言われると意外とわからないこともありますよね。実際に漫画風に加工するとなるとどのように実装するのか。。。
というわけで今回から2回に分けて写真を漫画風に加工するための画像処理について、手法と実装の2回に分けて解説していこうと思います。今回は手法の解説だけになるので、すぐにでも手を動かしたい方はこの記事をすっ飛ばして次の記事を読んでください。
使用する画像処理技術のあたりをつけよう
まずは加工後の写真をイメージして、使用する画像処理技術のあたりをつけていきましょう。
画像処理に関するアルゴリズムは既に一般化されているものがたくさんあります。今回のように目標(漫画風にする)がはっきりしている場合は、独自にどうこうするのではなく、まずは既にあるものから使えそうなものを探してみましょう。画像処理に関する情報はWEB、書籍ともに非常に充実しております。ここでは私が実際に読んだものを紹介しますが、とりあえず今の時点ですべて目を通す必要はありません。こんなものがあるんだぐらいに見といてください。
画像処理におけるアルゴリズム
画像処理におけるアルゴリズムの種類や内容を非常に簡単に解説しています。とても参考になりました。
Core Image Filter Reference(iOS Developer Library)
Mac OS X/iOSアプリで標準で使用できるCoreImage.frameworkを用いた画像処理について解説されています。ここで紹介されている画像処理をすべてiOSアプリ開発で使用できるわけではありませんが、Objecive-Cに慣れている方であれば、こういう切り口から画像処理の世界に入るのもありではないでしょうか。
opencv.jp - OpenCV: フィルタと色変換(Filters and Color Conversion)サンプルコード -
OpenCVを使用した画像処理をサンプルコードと一緒に解説しています。OpenCVはインテルが開発したオープンソースのC/C++、Java、Python用ライブラリで、iOS以外にもMac OS Xはもちろん、Linux、Windows、Androidなど様々なプラットフォームで動作します。iOSに関してはむしろ最近標準でサポート(armv7sでは動きませんが)されたばかりです。
画像処理に関してまだ駆け出しのひよっこの癖に生意気なことを書かせて頂きましたが本題に戻りましょう。私は写真を漫画風に加工する上で、以下の2つのフィルタ処理が近そうだなぁと考えました。
エッジ検出(輪郭検出)
Wikipediaによると、エッジ検出とは「画像処理やコンピュータビジョンの用語で、特徴検出や特徴抽出の一種であり、デジタル画像の画像の明るさが鋭敏に(より形式的に言えば不連続に)変化している箇所を特定するアルゴリズムを指す」とのことです(参考:エッジ検出 - Wikipedia)。わかりやすく言うと、画像中にあるモノの境界線を検出する処理です。実際にエッジ検出処理をかけた画像を見てみましょう。
これは輪郭を線でなぞったような効果を出すのに使えそうですね。
2値化
上で紹介した画像処理におけるアルゴリズムによると、「指定画像を白と黒の2階調の画像に変換する処理」とあります。具体的には、RGB各要素の平均値がしきい値より高ければ白、低ければ黒と言った具合に分けて、写真を真っ白と真っ黒の2色だけの画像を生成します。実際に2値化を施した画像を見てみましょう。
これも写真をモノクロにするために使えそうです。
この2つのアルゴリズムを使用すれば、写真を漫画風に加工したような効果を演出することができそうです。
画像処理工程の計画をたてよう
使えそうなフィルタは出揃いましたが、単体でみるとまだまだ完成にはほど遠いです。これらのフィルタを利用して、どうすれば完成に近づくか模索しながらどういう処理が必要か計画をたてていきましょう。
私は漫画風の写真を構成する要素として以下の3つに分けて考えました。
- 輪郭
- 白黒の部分
- スクリーントーンの部分
この3つの要素を合成させれば写真を漫画風に加工できそうです。それでは実際にどういう工程でこれらの要素を生成するか計画をたてましょう。
1.輪郭
撮影した写真から黒いペンで輪郭をなぞったような画像です。これは先ほどあたりをつけたエッジ検出が使えそうですが、エッジ検出処理を施した画像を見ると加工してやる必要がありそうです。そこで私は以下のような工程を考えました。
- エッジ検出する
- エッジ検出した画像の色を反転する
- 白い部分を透過する
2.白黒の部分
次に白黒の部分です。これは2値化が使えそうです。しかし、2値化してしまうと白黒だけになってしまい、淡い色の部分、すなわちスクリーントーン部分が表現できません。 ここは2値化のアルゴリズムを利用して、白と黒の2値化ではなく白・灰色・黒の3値化することで対応しましょう。工程としては以下の通りです。
- 画像を3値化する
- 灰色の部分を透過する
灰色部分を透過するのは、次に紹介するスクリーントーンの部分を表示するためです。
3.スクリーントーンの部分
最後のスクリーントーンの部分。こいつは非常に簡単で以下の画像を輪郭画像と白黒部分の画像の最背面に配置するだけです。
これで漫画風の写真が生成できそうですね。画像に施す処理の工程がはっきりしました。次回は実際に手を動かして画像を加工してみましょう。