2011/03/29

録画したテレビ番組のL字を除去する

大災害が発生したりすると、テレビ番組の画面の周囲にL字状の枠が追加されて被害情報などが表示されますが、録画した番組を後で視聴するときには邪魔でしかありません。
エンコード時にクロップして除去してしまえばよいのですが、CMなどでL時の有無が切り替わる部分ではフェードイン・アウトが行われるため、綺麗に除去するエンコード定義を手動で作成するのは非常に面倒です。
そこで、動画からL字の出現範囲を自動検出して、フェードイン・アウトの部分まで正確に除去するAviSynthスクリプトを生成するというNILScript用スクリプトを作成しました。

AviSynthは、動画の読み込みや加工処理を定義するスクリプト言語の処理系です。
AviSynthをインストールすると、VideoForWindows APIで拡張子「.avs」のスクリプトを動画として読み込めるようになります。
VirtualDubなどのソフトで読み込んで編集・エンコードする一般的な使い方ですが、NILScriptのVideoユニットもVFWを利用しているためAviSynthスクリプトを読み込み可能で、今回のスクリプトでも映像処理の大部分はAviSynthスクリプトで行っています。

NILScriptのVideoユニットは、このL字除去スクリプトを作成するために暫定的に実装されたものなので、限られた機能しか用意されていませんが、このスクリプトのようにAviSynthと組み合わせれば、様々な動画処理ツールを手軽に作成できるでしょう。


スクリプトと定義データ一式は以下のURLからダウンロードできます。
使用するには、別途NILScript本体とAviSynth、MPEG-2 VIDEO VFAPI Plug-Inが必要です。
スクリプトの内容や詳しい使用方法は、上記アーカイブ内のファイルを参照して下さい。

http://lukewarm.s151.xrea.com/rem.zip


L字の検出には、L字の左上辺りの映像が不変である部分のサンプル画像を用意しておき、動画の各フレーム画像との差を調べるという手法を用いています。
ほとんど全てのピクセルが一致した場合に完全なL字とみなし、それ以外はL字無しかフェードイン・アウト中のフレームとみなすことにしました。

スクリプトが実行されると、各フレームのL字の有無を示す小さな画像からなる動画を出力するAviSynthスクリプトを生成して、Videoユニットで読み込み、フレームを一定間隔で飛ばしながらL字の有無を調べます。
L字の有無が切り替わっている箇所が見つかったら、間のフレームを調べて正確な境目を探します。
ここでも、最初に範囲の中央を調べ、既に切り替わっていたら範囲の前半、切り替わっていなければ範囲の後半を再帰的に調べるという二分探索的な手法を採ることで高速化しています。
フェードイン・アウトのフレーム数は放送局ごとに一定なので、完全にL字である範囲がわかれば、フェードイン・アウトの範囲と、L字無しの範囲も確定します。
動画の末尾まで調べたら、元の動画を読み込んで各部分に対応するフィルタを適用して連結するというAviSynthスクリプトを構築して保存すれば処理完了です。

0 件のコメント:

コメントを投稿