Poisson Image Editing はSIGGRAPH 2003で発表された画像合成手法の1つで、Poisson方程式の境界値問題を画像処理に応用しています。
ただ画像の一部を切り取って貼り付けるだけだと特に領域境界部分の継ぎ目が目立ってしまいますが(左画像)、Poisson Image Editingを用いると領域周辺の画素値から領域内側の画素値を推定して滑らかに合成することができます(右画像)。
僕が学生時代、VC++でこの手法を使った画像合成ソフトをゼミ仲間といっしょに作って遊んでいた記憶があります。今回はその頃を懐かしみながらJavaScriptで実装してみました。なんでもブラウザ上で試せる便利な時代になりましたよね。僕も歳を取りました。
Demo: Poisson Image Editing
(IE10.0, Firefox22.0, Chrome28.0, Safari6.0で動作確認済)
今回作成したデモでは手動で一回ずつ数値計算のイテレーションを回す機能も提供していますので、”iterate”ボタンを何度も押して少しずつ滑らかに合成されていく様子を確認してみてください。
ちなみに、C++やPythonでの実装例は既にあるようです。
Poisson Blending – OpenCV.jp
Pythonでポアソン画像合成のコード書いたよー – ぱろすけのメモ帳
JavaScriptだとC++やPythonのように十分にテストされた高速な科学技術計算ライブラリなんて揃っていませんので、素朴に式をぺたぺた書いていくしかない上に、Canvas APIが低レベルな機能しか提供していないのでロジックに集中できないことも多いです。しかし、Webブラウザ上で動くという大きなメリットを前にして労を惜しむのはもったいないと思います。
iPadやGalaxy S2などのスマートデバイス上のブラウザでも動作することを確認済みです(重いですけど)。ここではあらかじめ用意したマスクを使っていますが、指などでインタラクティブにマスクを作る仕組みを入れたりするとより面白いデモが作れると思います。
コードはGithubにも置いてあります。もちろん自由に利用していただいて構いません。
cv/poisson_blending/poisson.js at master from wellflat/javascript-labs – GitHub
以下のように使います。
1 2 3 4 5 6 7 8 9 |
var ctx = document.querySelector('#Canvas').getContext('2d'); // 貼り付け元画像名、貼り付け先画像名、マスク画像名、 // 画像読み込み完了後のコールバック関数をそれぞれ指定 Poisson.load(srcImgName, dstImgName, maskImgName, function() { // 最大反復回数、X軸オフセット(px)、Y軸オフセット(px)を指定して画像合成 var result = Poisson.blend(100, 10, -20); // 合成結果画像をCanvasにレンダリング ctx.putImageData(result, 0, 0); }); |
画像合成部のコードは外部ライブラリ等の依存はなく、Canvas APIのみを利用したPure JavaScriptなコードになっています。スマートフォンでもなんとか動作させたかったので、画像端での判定などいくらか妥協している部分もあります。また、高解像度画像で検証する場合はWeb Workersやasm.js対応が必要になるでしょう。
息抜きにこういった要素技術のプログラムを書くのはやっぱり楽しいです。
参考:
Poisson Image Editing (元論文、PDF)
Poisson Image Editing (PDF)
Gradient Domain Imaging
勾配ベースの画像編集 : Poisson Image Editing (PDF)
Poisson Image Editing – ますぽんの雑記
素晴らしいデモですね。
この記事のお陰で興味の幅が広がりました。
自分もいつかこういうツールを作ってみたいです。