手振れ動画を定点カメラっぽく補正した話 OpenCV

手持ちのカメラで動画を撮影すると固定しているつもりでもある程度手振れを起こします。   こんな感じで…

手持ちのカメラで動画を撮影すると固定しているつもりでもある程度手振れを起こします。

 

こんな感じですね。スマートフォンのカメラで撮影すると大体このようになります。
それが出来ると何がどうなるの?という話は置いておいて、これを定点カメラで撮影したような動画にしたい!というのが今回のテーマ。

 

ビデオスタビライザー

手振れ補正と言えばビデオスタビライザーというのがあるんですが

◯手振れ動画

◯Youtubeのビデオスタビライザーを適用したもの

今回やりたいのはこれじゃ無かった。
「手持ちカメラで定点で撮影しているつもりの動画」を「定点カメラで撮影したような動画」にすることが目的。

文章にすると難しいです。このページ下の方の結果動画を見てもらった方がイメージはしやすいと思います。

Try And Error

「とりあえず画像処理と言えばこれ!」なOpenCVのリファレンスを見つつビデオスタビライズしてみたのですが、結果は上記Youtubeのようなヌルヌルっと動く動画。

オプティカルフローからカメラ全体の動きを想定してごにょごにょする、というのも試してみたのですが、手振れといっても単純な縦横移動だけでなく回転とか要素の欠損も出てきてなかなか難しい。

それっぽいものが出来ても微妙なズレが気になります。

 

何かないかなーと思いつつOpenCVのサンプルとドキュメントを見ていたところ、findTransformECCという関数を発見しました。

http://docs.opencv.org/trunk/modules/video/doc/motion_analysis_and_object_tracking.html

Opencv3で追加された(る?)んですかね。この関数が正に私がやりたかったことを実装してくれているのでした。

画像を処理する関数ですが、画像でできる=1フレームずつ処理すれば動画でできるなので、ひとまずの実装として問題はないです。

パラメータも精度と補正のアルゴリズムくらいで割とわかりやすい。

結果

まあ、細かい話は置いておいて出来上がりの動画です。

 

ポスターの角を注視するとわかりやすいと思いますが、動画内の背景は最初から最後までほとんど動いていません。

そもそも「手振れを起こしている」「撮影されている範囲は一定」なので補正するにあたって欠損(黒い部分)が出るのは覚悟の上。

気になる場合はトリミングしてやったり、別途補完してやる必要があります。

備考

iOS上でも動作しますのでスマートフォンで撮影した動画をアプリでごにょごにょするのに使えるかもしれません。多分Android上でも動くんじゃないかと。

ただ、処理時間(CPU)をかなり使うので、リアルタイムに処理するのは現状難しいっぽいです。ゆがみが大きくなるとその時間は顕著になります。

また、ゆがみが大きすぎる(補正できない?)場合は

The algorithm stopped before its convergence. The correlation is going to be minimized. Images may be uncorrelated or non-overlapped in function findTransformECC

と出てAbortします。ある程度のフィルタリング/エラーハンドリングは必要ですね。

 

今更ながらもうちょっと良いやり方があるんじゃないかと思いつつ今日はここまで。