AfterEffects,blur,diffraction,plugin,初めて,回折,画像処理こんにちはー。開発室のひらく[@horonig]です。去年12月に始まった【DF_talk】も既に半年が経ち、続々とおもろいエントリーが公開されていますが、皆様お楽しみ頂けてますでしょうか?しかし、聡明な読者の中にはお気づきの方がいらっしゃると思いますが、未だメインソフトの中で言及されてないヤツが一つありますね。!AfterEffectsです!!(あれ?MotionBuilderは?とかいう突っ込みはナシで。(∩゚д゚)アーアーきこえなーい)AfterEffectsは会社によって呼び方が変わりますよね。AE(えーいー)、アフエフェ、アフター、AF(エーエフ)、AFX。最後から二つ目あたりからは18禁的な印象しか受けない僕は何か間違ってるのかもしれません。そんな僕はAE(えーいー)派です。ぽぽぽぽ~んのAC(えーしー)じゃないですよ。DFの人たちは、AEもしくはアフターと呼ぶ人が多い気がします。今回のエントリーではAEという呼称で進めていきましょう。DFでは現在、AEのインハウスツールがそれなりに揃ってきておりますが、その中でも僕が初めて作ったプラグインの話をさせて頂きます。あれは、むかーしむかしの事じゃった。えーしー♪(あ僕は元々、mayaとAEを使ってCM系のデザイナー業務をしていたのですが、ちょっと変わった3D的な表現はmel(mayaのスクリプト言語)やmayaの既存機能でなんとかなると思っていました。頑張っても手が出ないのが『2D的なギミック』、つまりピクセル単位で何かをするエフェクトでした。事は、画像処理が出来れば俺最強じゃね?という勘違い意識が僕の中で勃興し、意識し始めたのが僕の画像処理人生の始まりです。言え、前の会社ではほとんど画像処理プログラムを書いた事がなかったので、DFに入ってから本格的なR&Dの時間を頂き、初めてAEプラグインを作る事になりました。1.プラグインのアイディア社内で「どんなAEプラグインが欲しいか」というヒアリングをしてみたところ、多種多様なアイディアが出てきたのですが、その中でも僕が興味を持ったのは、某Mディレクターが提案してくれた≪光の回折プラグイン≫でした。これは、キャラと背景を合成したときに、背景の明るい部分がキャラの前方に回り込む光のにじみ効果を作っちゃおうというエフェクトです。要は、合成をなじませるためのエフェクトですね。検討した結果、この≪回折プラグイン≫を作ることにしたのですが、これを作ろうと思ったポイントは以下の三つです1間違いなくよく使うエッジ部分のマスクを作ってそこだけ明るくしたり背景色に転がしたりという事は良くやる手法ですが、意外と手間が掛かるんですよね(エフェクトを三つ四つぶら下げてさらにプリコンして...とか)。これが一発で出来るだけでも工数削減に繋がるはずだという読みがありました。2必ず役に立つコレを差し込むだけでコンポジットの馴染みが良くなるので、絵のクオリティアップが望めます。3なんとかインプリ(※)できそう(コレ重要!)アルゴリズムの検討をしてみた感じでは、僕のつたない画像処理知識の範囲でも何とかなりそうな気がしたんですよね。このあと地獄を見ることになるとは思いもしませんでしたが。実装すること2.仕様の策定とアルゴリズムの検証まずは仕様の策定に入ります。諸々検討した結果、以下の二つのモードを搭載する事にしました。作り、それを使って背景の色をのせるやり方です。やる手法ですが、要は以下の様な流れになります。元のマスク2で4を切り取る※4では、『最大最小』を使って食い込み具合を調整したりもしますこの5で出てきたマスク素材を使って、背景をぼかしたものを加算したりしてエッジをなじませます。すると以下のようになります。実際に背景の明るい部分から光が漏れるような、そこそこ本格的なマスクを作って合成する方法【flareモード】[其の1]は良くある例なので簡単ですが、更に凝った別の手法も実装しました。説明がメンドクサイので、兎にも角にもリザルトをどうぞ。【flareモード】と言ってもこうはならないので注意してネ!!この【flareモード】のアルゴリズムまで言及すると長くなるので、≪初めてのAEプラグイン。【後編】≫でまた詳しく説明しようと思っています。このように、【edgeBlendモード】は簡単なエフェクトの組み合わせで再現できているので、アルゴリズム的な問題はさほどないと思われます。【flareモード】はある程度頭の中で理論武装した上で、まぁいけるかな、という感じを持ってから臨んでいます(上ではリザルト出しちゃってますけど)。いう訳で、次のチャプターへ進みましょう。3.SDKの調査&コーディング開始ある程度の仕様とアルゴリズムが固まったところで、SDK周りの調査を開始したのですが、これがまた大変でした。言うと、AE_SDKの情報がWEBではほぼ皆無だったのです。SDKに入ってるサンプルがいくつかあるので、それとSDK_Guideを睨みながらコーディングを開始しました。コーディングを始めて僕が一番衝撃を受けたのは、AEに元から入っているエフェクトはSDKには含まれず、一から自分でインプリしないといけないという事でした。「ブラー」や「最大最小」なんかのエフェクトが普通にSDKから使えるもんだと勝手に思い込んでいたのですが、そうではないんですよね。(今思えば当たり前の事なんですが、ブラーくらいは用意してくれてもバチあたらないと思うww)なので、かつてインプリしたことのない「ブラー」エフェクトとかから始めたんですが、これがまたやっかいでした。(※詳しい方は「OpenCV使えば?」と思われるかもしれませんが、この当時、OpenCVの存在なんて毛ほども知らなかったのです)4.画像処理ェ..ちょっとAEから話は逸れるのですが、PhotoShopのフィルタに「カスタム」というものがあるのをご存知でしょうか?いわゆる『畳み込み演算』が実現できるフィルタで、この数値次第で画像をボカシたり、シャープにしたり、エッジ検出を掛けたりできます。以下の設定だと「ブラー」っぽい効果が得られます。「ブラー」的な設定例この数値の意味は、各ピクセル値を計算するときに、その周りのピクセル値を上の数値で乗算したものを合算し、最後に【スケール】の値で割り算する、という単純なものです。上の例で言うと、上下左右と斜め4つ、更に自分自身(中央)の9個の値を全て足し算(正確に言うと「1」を掛けて足し算)し、最後にスケール「9」で割ります。すると、周りのピクセル値と混ざっていく感じになるため、ブラーっぽい効果が出るわけです。ブラーを強くしたい場合は、以下のような設定で可能です。強い「ブラー」的な設定例(ブラー半径を”2′′にした状態)つまり、より遠くのピクセルをサンプリングする事で、より強いブラーになるわけですね。余談ですが、数値を変えると以下の様な効果も作れます。「エッジ抽出」的な設定例この辺は色々といじると効果が変わって面白いので、機会があれば是非触ってみてください。何が言いたかったかと言うと、上の「ブラー」的な例でも分かるとおり、より遠くのピクセルをサンプリングすればよりボケる、というのは僕の中では常識でした。そのため、『これと同じ事をAEで実装すれば「ブラー」エフェクトが作れるんでしょ?簡単じゃーん。』と勝手に思ってたのですが、これが運のつきでした...。半径(radius)が「1」とか「2」ならまだしも、「20」とか入れただけでAEが固まってしまいまうくらいの重さでした。このとき僕は悟ったのです。死ぬ運命(さだめ)ではないと。なくて、画像処理を甘くみ過ぎていたと。画像処理ってピクセル数分だけ処理するのが大前提なので、その各ピクセルで他のピクセルをたくさん参照したり余計な計算を入れ込むとハンパなく重くなるんですよね。当時の小さい解像度「640*480」だとしても、それだけで処理の数(ピクセル数)は”307,200′′にもなるんですよ!さ、30万。「えっと、じゃあどうやったらブラーってインプリできるの?教えて!googleせんせー(^q^)」的な感じでググッてようやく見つけた答えは。1横と縦で二回処理する事で、二次元的に処理したのと同じような結果が得られる(一次元的な処理×2で十分な結果が得られる)2ピクセルを順に処理する際に、前のピクセルで使った情報を再利用する事で処理が軽くなるという二点でした。どちらも、処理速度の向上という意味では欠かせない要素です。その当時は思いもしませんでしたが。1は具体的にどういう事かと言うと、『一度横方向にブラーを掛け、その後縦方向にブラーを掛ければそれっぽくなる』という事です。全体的にブラーが掛かったような結果を得られますこうする事で、二次元なピクセルサンプリングをしなくて済むようになるため、劇的に処理が速くなります。(ボックスブラーでブラー半径が「5」だとすると、二次元的なサンプリングでは11×11で121箇所をサンプリングする必要があるが、一次元ならば11箇所のサンプリングだけで済む)一方、2はどういう事かというと、以下の様な配列のピクセル値に簡単な「ボックスブラー」を半径”3′′の設定で掛ける場合で解説してみます。ブラー後のピクセル値を決定する処理の順番はa→hとし、ここではピクセルdとピクセルeの求め方のみを説明します。10ピクセルdの値を決める場合、半径は3′′なので、以下の青い部分のピクセル値と自分自身の値をまずは合算します。86(四捨五入)となり、これが答え(ブラー後のdの値)になります。73(四捨五入済み)が答え(ブラー後のeの値)になります。これを全てのピクセルで順次行って行くわけですが、実はここに巧妙なトリックを取り入れることで、計算が劇的に速くなります。それが、前回の情報の再利用です。dにしろeにしろ、値を計算するためには「6回の足し算、1回の割り算」が行われますよね。ところが、前の情報を再利用する事で「1回の足し算、1回の引き算、1回の割り算」で済むのです!やり方はこうです。dの値を計算するときに、a+b+c+d+e+f+gの値を$sumという変数で取っておきます。eの計算をする際には($sum+h-a)が実はeで必要な$sumとなるのです!何故かというと、eの計算をする際にはaが必要なくなるので$sumからaを引きます。今度はhが必要になるので$sumにhを足す事で必要な$sumが出来上がるわけです。このやり方は、半径が増えれば増えるほど効果が出ます。どれだけ半径が大きくても前の情報を再利用する事で、基本的に「1回の足し算、1回の引き算、1回の割り算」で済むからです。逆にこれをしないで半径が100だったりすると、「200回(!)の足し算、1回の割り算」という事になり、計算量ががっつり上がります。(実際には、200回の演算もさることながら、201個のピクセルをサンプリングする事自体がかなりのボトルネックとなります)このやり方を知ったときは、目から鱗でしたよ。コロンブスの卵でしたよ。馬の耳に念(ry今となっちゃ当たり前で、こういうテクニックを使わないと画像処理プログラムなんてアホらしくて書けないくらいには成長しました。実際には、重み付けナシ(正確に言うと全ての重みが「1」)のボックスブラーでは品質が落ちるので、重み付けアリのアルゴリズムでブラーをインプリしましたが、同様の考え方で高速化できます。そこまで言及するとややこいので、ここでは割愛させて頂きます。言うわけで、【edgeBlendモード】は無事インプリできたのでした。他にも「最大最小」などもインプリしつつ、諸々組み合わせてエフェクトを実現しています。–そして僕は羽ばたいた–≫はいかがだったでしょうか?内容としてはそんなに難しく無いと思うのですが、画像処理に慣れてないと意外と理解しづらいかもしれませんね。画像処理は面白いですよ。何と言ってもピクセル単位で絵をいじれるのは快感です(・∀・)今はPixelBenderなんて便利なものもありますし、openCVもありますし、気軽に画像処理プログラムを書ける時代になってますよね。そのうちポストします。忘れたらごめんなさい。それではまた!!アディダス!!TweetPocket<<前の記事へ次の記事へ>>コメントいつも拝見させて頂いております。sarataniこんにちはー(・∀・)いつも[DF_talk]を読んで頂きまして、ありがとうございます!ご質問の件ですが、「ガウシアン」ではなく、「一次関数的な重み付け」を使用しています。いう重み付けをなんと呼ぶのか良く分からないのですが、要は、一番遠い(半径距離の)点でのサンプリングの重みを「0.0」、一番近い自分自身のサンプリングの重みを「1.0」にして、その間はリニア補間という事です。本当はガウスブラーが品質としては一番良いと思うのですが、下記の理由により、ガウスブラーをインプリすることは見送りました。1「一次関数的な重み付け」でのインプリで、品質的には十分だった2AEのガウスブラーも昔は重かった記憶があるため、インプリしても処理スピードはたかが知れてると思った(記事中のような高速化が出来ない気がした)。※最近のAEだとあまり重くないみたいですけど。何か変わったのかしら...(汗)なので、ガウシアンの場合にどうインプリすればいいかは、僕の頭にはないんですよね。「一次関数的な重み付け」であれば、ちょっと計算してみると比較的簡単な事が分かると思いますよー。いう程度なら最近のPCではあまり問題にならないのかもしれませんね。sarataniこんにちはー。確かにテーブル作る部分では多少工夫したほうが良いでしょうね。僕が一番問題になりそうだなぁと思ったのは、5-2で言及した、『ピクセルを順に処理する際に、前のピクセルで使った情報を再利用する事で処理が軽くなる』という部分なんです。考えただけだと、前の情報をうまく利用してサンプリング回数を減らす、という事が簡単には出来ない気がしたんですよね。hiraku度々ですみません。確かに5-2が一番ネックですね。ガウシアンに関してはそのような処理は初めから諦めてました。sarataniちょっと難しい話になるかもしれませんが、各ピクセルを単純に処理するだけの画像処理を想定して計算量(オーダー)を考えると、O(n^2)と表せると思うんです。縦横(XY)のピクセル数があるので(この辺は考え方次第ではありますが)で、ガウスブラーにおいて5-2がうまく出来ないと仮定すると、計算量が一気にO(n^3)に跳ね上がります。これはかなり大きいかなと。僕の紹介したボックスブラーやリニア補間を使ったブラーであれば、単純な画像処理と同じO(n^2)で済むため、高速です。logn)という事になり、僕が紹介した方法に比べると遅くなります。やり方次第で綺麗なピンボケを作ったりも出来るので、どちらを取るか、という感じです。logn)になります)兎にも角にも、目的によって最適な手段を選ぶ事が重要だという事ですかね。hirakuなるほどO(n^2)とO(n^3)では大きな違いですね。logn)はO(n^3)に比べればまだ軽いので必要に応じて選べるとベストなのかもしれませんね..色々と勉強になりました。–そして僕は羽ばたいた–≫ですが、【前編】と書いてしまったからには【後編】を書かねばなりません。あー余計なことしたなー。なんで後編とか言っちゃったんだろうなー。編集してなかった事にしちゃおうかなー、、、なんて事を言ってる時間が勿体ないので、【後編】いきます。