映像を半自動結合するプログラム

phashを使った類似フレーム(後続フレーム)の抽出は予想外に大変でした。いつものことですが、やる前は簡単に感じるのはどうしてなのでしょう。

どうにか大量のフィルム断片(ショット)から半自動で元のショット順に並べ替えるプログラムを作成しました。
各ショットの最初と最後のフレームは大抵壊れているので、すべてのフレームからphashの値を生成しました。次に、ここからは人(自分)の作業との組み合わせになりますが、ランダムに並んでいる先頭のショットから開始して、後続のショットを見つけることを繰り返します。後続のショットが見つからなければ、次の未処理のショットから後続のショットを探し始めます。単純にこの繰り返しです。

対象ショットに対する後続ショットを見つけるために、まず、対象ショットの最後のフレーム(接続元フレーム)を表示します。そのフレームが壊れている場合は、一つ前のフレームを表示することもできます。その表示されている接続元フレームに類似するフレームを全フレームからphashで類似する順に接続先候補フレームとして表示します。なお、接続先はショットの先頭フレームでなければならないですが、先頭のフレームが壊れている可能性があるのでショット中での前半に位置するフレームの場合のみ接続先候補フレームとして表示します。ここで接続元フレームと接続先候補フレームについて接続して良いかどうかを人が判断します。接続した場合には接続先ショットについてさらにその後続のショットを探すということを繰り返します。実は、やってみると、この接続するかしないかの判断がかなり難しいです。

まず、phashの類似順がかなりひどいので、多くの場合、phashの差分が最も小さいフレームであっても後続のフレームとはならないです。ですから、人の判断がとても重要なのです。しかし、人が判断するにしても単純に連続しているフレームかどうかの判断すら結構難しいです。最初は1フレームで映像がどのぐらい変化するのかが分からなかったので、似たようなフレームを間違って接続してしまうことが頻繁にありました。
動きがない映像だと、いくら注意深く見ても間違えてしまいます。
間違えるとどうなるかというと、映像が無限ループになったり、二重に接続されたりしてしまいます。

この間違いを防ぐために、まず、既に接続されているショットに接続しようとする場合には、既に存在するショット間の接続関係が間違っている場合もあるので、既存の接続と新たな接続とのどちらを利用するかを選択できるようにしました。もちろん判断するためにそれらのフレームを表示します。
さらに、接続時に既に接続されているショットをたどり、接続することでループになるかどうかをチェックする機能を追加しました。接続するとループになる場合にも、上記、同様どちらを利用するかを選択できるようにしました。さらに、どちらも接続しない方が良い場合も実際にはあるので、どちらも切断という選択もできるようになっています。
最終的に、このようなやり方に落ち着きましたが、ここまで来るのすら試行錯誤の連続でした。

実はこれでも、なかなか、うまくいきません。フィルムの劣化以前にphashが検知する類似性は予想外に貧弱でした。と、書きつつ、かなり壊れた画像でも正しく類似していると判断できる場合もあり、かなり挙動が不思議です。ただ、総じて正しい後続フレームが見つけられない場合が多く、その分、人の判断回数が増えるという感じになっています。