こんにちは。プロダクト開発部の中屋敷です。当社では毎年、新入社員でグループ研修を行います。今年度、私達が研修で作成したのが「画像のレイヤー分割」と「水彩画効果を用いた動画化」システムです。本記事では、このシステムの開発の目的や原理、実現したことについてご紹介いたします。
概要
皆さんはデジタルで絵を書いたことはありますか?デジタルではアナログと違い、元に戻したりコピーしたりと便利な機能がありますが、その中でも特に重要なのがレイヤー機能です。風景・人・犬といった描写物を別々の透明フィルムに書き込み、それらを重ね合わせることで一枚の絵とするものです。このレイヤー機能により、人のポーズを変えたり位置を動かしたりしても背景を書き換える必要がないため、非常に便利なものとなっています。
そしてもう一つ、撮った写真を加工することも身近になってきました。文字やスタンプでデコるだけでなく、写りこんだ人を消したり、逆に人を増やしたり。ですが、単に写真の上に追加するだけならともかく、加工をしようとすると途端に難しくなります。(柵の奥に人を追加しようとすると切り抜きが大変ですし、中にはスタイルを良くしようと加工したら背景の人が歪んでしまったなんてケースも・・・)
そこで私達は、写真を複数のレイヤーに分割できれば様々な加工処理が楽になるのではと考え、これを実現するシステムを開発しました。 加えて、この分割結果を用いることで面白いエフェクトも実現しましたのでご紹介します。
レイヤー分割アルゴリズム
まずレイヤーを分けるための情報として、depth map(写真内の相対距離を表した画像)を用いました。
depth mapは当社のMorpho Single Camera Bokeh™を使用することで、1枚の画像から取得することができます。また、これから撮る写真であれば、Morpho Dual Camera Solutions™を使用することで視差情報を用いたより精度の高いdepth mapを取得することもできます。
depth mapを用いたレイヤー分割で最も単純なのは、指定した距離(depth値)より手前か奥かで分割する方法です。ですが、どの値なら適切に分割できるのか、何個に分けるのかを指定するのは手間がかかります。そこで私達は、複数の手法を用いて適切な分割値や分割数を推定する処理を実装しました。
クラスター分析による分割
まず、depth mapを適切な値で分割するためにクラスター分析を用いました。depth値を1次元データとして扱い、クラスターに分けることで分割depth値を算出しました。また、クラスター分析には様々な手法があるため、複数の手法を実装しました。
- クラスター数(レイヤー分割数)を指定して分割する手法
- クラスター数を推定する手法(推定結果をk-means法などに使用)
- クラスター数を推定しつつ分割する手法
多項式回帰を用いたレイヤー分割提案手法(多項式回帰+)
クラスター分析とは異なる手法のアルゴリズムも一つ実装しました。基本理論として、depth mapをヒストグラムにすると物体がある付近の値は高く山のようになり、何もない距離は0(谷)に近くなります。そのため谷の位置で分割すれば、きれいな分割結果になるはずです。ですがヒストグラムは非常に凸凹しているため、単に移動平均+増減チェックでは谷の位置を判定するのは困難です。そこで、このヒストグラムの近似曲線を用いることで、細かな凸凹をなくしつつ、もとのヒストグラムに近い山・谷を表現できると考えました。 手法としては、depthマップをヒストグラムにかけ、その結果を多項式回帰分析(scikit-learn)を用いて近似曲線を計算します。その曲線の山となる頂点を算出し、山同士の間で最も値が小さい点を谷として分割点に設定するようにしました。
1次元のレイヤー分割の問題点と解決策
これまでの手法は1次元データとしてdepth値の分割点を見つけようとしましたが、1次元のみだといくつか課題点がでてきました。
- depth値が同じくらいの複数の物体は、同じレイヤーになる
- depth値が広い物体は途中で分割されてしまう
- 中間レイヤーに境界線が表示される これらの課題点を解決するため、3次元クラスター分析および境界線ノイズ除去アルゴリズムを実装しました。
3次元クラスター分析
3つの課題すべてに対処するため、depth mapの座標も用いた3次元データでのクラスター分析を実装しました。座標による距離情報も用いることで、離れている物体の分割、depth値が多少変わっても物体は分割されない、境界線は周辺のクラスターにまとめられる、という3つの効果を期待しました。
分割結果をみますと、1次元ではいくつに分割しても被写体の二人は同じレイヤーになりましたが、3次元分割を用いると見事一人一人別のレイヤーに分離することができました。ただ一方で、3次元分割では背景のような広い範囲が写っている領域はパズルのピースのように分割されてしまうという欠点も見られ、有効的なケースが限られることが判明しました。
境界線のノイズ除去
続いて1次元分析で生じる境界線ノイズを除去する処理を追加しました。図7に示すように、中間となるレイヤーから境界線ノイズと思われるピクセルを抽出し、それらのピクセルを近いレイヤー(周辺で最も大きい領域のレイヤー)に移動させました。そのように補正した分割結果を使い写真をレイヤー分割することで、図5で見られた境界線ノイズを削減しました。
レイヤー分割の評価
今回のシステムではいくつもの分割手法を実装したため、各手法について「処理時間・再現性・分割結果」の3項目で性能評価を行いました。評価対象は紹介した各手法(1次元分析)と、3次元クラスター分析をk-means法に適応したものを比較しました。
処理時間
各アルゴリズムの処理時間を評価しました。処理時間は、CPUのシングルスレッドで動作させ、14回実行したうちの上位7回を平均して算出しました。 グラフは横軸が速度評価に用いたdepth mapで、縦軸が処理時間(ms)を対数表記しています。
まず一番目につく結果として、多項式回帰+が他の手法の100〜1000倍速い結果となりました。理由としては、どれだけ大きなdepth mapであってもヒストグラム化して256個のデータ(depth値の幅)にしたものを解析に用いるため、高速化が実現できています。次に早いのはk-means法で、3次元にするとデータ量は3倍に増えるものの、大幅な増加は見られませんでした。mean shiftやx-means法は探索が必要なため、k-means法の10倍ほどの時間がかかってしまっています。Fuzzy C means法は分割数を指定する手法ですが、k-means法よりも10倍ほどの時間がかかっています。
処理時間の全体の傾向としては、分割数や画像によらずサイズに比例するような傾向がみられますが、Fuzzy C means法のみ画像の内容により処理時間が大きく変わることが確認できました。
なお、elbow法についてはk-means法を指定回数繰り返して最も良い分割数を探す手法であり、処理時間≒k-means法の時間×指定回数という単純な計算となるため、グラフから除外しています。
再現性
続いて再現性の評価です。クラスター分析手法では開始時のクラスター中心点などをランダムに設定するため、同じ画像であっても最適化によるクラスタリング結果が異なる可能性があります。そのため、画像ごとに複数回実行した結果(分割数・分割depth値・最適化後のクラスターの中心点)の一致率を算出し、それらから高中低の3段階で評価しました。基本的には再現性は高いほうが良いですが、一方で適切ではない分割結果だった場合それに固定されてしまうという意味でもあるため、再現性は低くても悪いとは言い切れないと考えています。
評価の結果、Fuzzy C means法とmean shift法は平均的に90%以上の一致率であり、クラスター分析の中では再現性が高くなっていました。一方、三次元のk-means法は次元数が多いためか、特に背景などの広い範囲の分割が実行毎に変わることが多く、再現性は低い評価となりました。それ以外のクラスター分析は、画像によりますが80~90%程度の一致率であり、大きな違いは見られませんでした。なお、多項式回帰+は計算による算出のため、一致率は100%でした。
分割結果
最後に分割結果の評価になります。分割結果は、人・物体・背景が分離できているかを評価しました。本来なら理想的な分割結果を用意してその差分から判定したいところなのですが、時間的な制約もあり、今回は目視・主観による評価を行いました。
図8のように同じ画像の分割結果を見比べて判定を行いました。この画像結果ですと、k-means法とFuzzy C means法がきれいな結果となっていますが、それ以外の手法は悪い結果となっています。ただし、画像によっては逆の評価になることもありますので、総合的な判断を後述の表1に記載しました。
分割評価の結論
速度については多項式回帰+が非常に速く、次点でk-means法となりました。再現性は多項式回帰+, Fuzzy C means法, mean shift法が安定して同じ結果が出力されています。そして最も画像の分割結果がきれいなものはFuzzy C means法で、次点でk-means法となりました。これらの結論から、用途ごとのおすすめは下記になります。
- 速度重視:多項式回帰+
- 性能重視:Fuzzy C means法
- バランス(指定):k-means法
- バランス(推定):mean shift法
レイヤー分割を応用したエフェクト
ここからは、レイヤー分割を応用したエフェクトについてご説明します。まず、レイヤー分割結果を活用する最も分かりやすい用途が画像合成です。分割したレイヤーは透過画像で出力できるため、ペイントツールなどを使って分割したレイヤー間に画像を挿入したり、サイズなどを変えて他の画像に合成したりすることができます。
ただ、この画像も柵が一部途切れているなどdepth値による分割は課題点も多く、残念ながら合成となると違和感を覚えてしまうケースが少なからずありました。そこで純粋に分割した画像を使うのではなく、さらにここから加工を加えることで、違和感を軽減しつつ面白いエフェクトを実装しました。
エフェクトのための基盤機能
実装したエフェクトの紹介の前に、エフェクトを実現するにあたって必要となる機能を2つご説明します。
- Inpainting
OpenCVのinpainting機能を使って、レイヤー分割で生じた空白領域を埋めることができます。基本は近郊の画素値を使用するため、広い範囲を埋めたり分割が綺麗にできていないと不自然になってしまいますが、そのままの空白状態よりは目立ちにくくなります。
- 水彩フィルター
近郊ピクセルの中で最も色の数値が高いピクセルの色にすることで、写真を水彩画で描いたような画像に変換するフィルターを作成しました。このとき、範囲や強度を変化させることで、水彩効果の強弱を変えることができます。この水彩フィルターをかけることで、レイヤー分割やinpaintingの違和感を軽減できます。
この二つの機能と、レイヤー分割、レイヤーのリサイズなどを組み合わせることで、いくつかの動画エフェクトを作成いたしました。
水彩画効果を用いた動画エフェクト
背景水彩化動画
まず一つ目、背景が少しずつ水彩風になっていく動画です。 こちらは2分割した画像のうち、背景のレイヤーに対して水彩効果をかけ、フレームごとに水彩効果を強めていくことで実現しています。背景がボケていく画像とはまた違った雰囲気の動画になりますが、予想外の効果として波が動いているようにも見えますので、水彩効果の強度を前後させると疑似的なgif動画にできるかもしれません。
水彩画作成動画
続いて写真の風景を水彩画で描いていく風の動画です。 こちらは最初に空白領域にinpaintingをかけ水彩効果を強めに加えた遠景レイヤーを表示し、だんだんと近景レイヤーを重ね、かつ水彩効果を弱めていくことで実現しました。背景だけの絵から、少しずつ物が書き込まれていくように見えます。レイヤー分割数を増やすほど、一回の書き込み量が少なくなるので、より丁寧な動画になります。
背景Drifting
最後に、人は動いていないのに背景が進んでいるかのような不思議な感覚になる動画です。通常は動画から作成される、ドリーズームと呼ばれる演出を写真から実現しました。
図13. 背景Drifting(左:水彩効果なし、右:あり)原理としては、inpaintingで補完した背景レイヤーを中心を基準に拡大させることで実現しています。こちらは境界線がどうしても目立ちやすいのとズームにより背景のinpainting部分が見えて違和感を覚えやすいのですが、水彩効果を加えることでこれらを目立たなくすることができます。
まとめ
本グループ研修では、depth mapを用いることで写真を複数のレイヤーに分割し、またその分割結果を元に一風変わったエフェクトの開発に取り組みました。この開発では、アイディア出しから要件定義、開発、テスト、評価までの一連の経験をつむことができました。レイヤー分割自体は比較的直ぐにできましたが、やはり理想通りに分けるとなると難しく、まだまだ課題点が残っています。一方で、その精度でも違和感を覚えないように水彩フィルターを加えるという発想が出てくるなど、とても刺激になる開発経験となりました。この開発経験を今後の業務に活かしていきたいと思います。
また、アルゴリズムの改善、別のクラスターアルゴリズムを試す、マルチスレッドやGPUを使った高速化、そして新しいエフェクトの追加など、まだまだ改善の余地はありますので、業務を通じて得たスキルで少しずつ改良し、自信をもって人に勧められるシステムにできたらなと思ってます。
以上、本記事を読んでくださりありがとうございました。