動画のフレーム間の差分をiOS/macOSでどう判定するか

以前、動画からスライドを自動生成するiOS/macOSアプリをつくった。

数時間で自分用に雑につくったものなので非常に荒削りなのだが、毎年WWDCのキャッチアップには必ず使っている。

で、課題として残っていたのが、

類似画像の除去

の部分だった。

こちらが全自動で生成したスライドのサンプルだが、

たとえばp.7〜p.9は同じページが連続してしまっている。

こういうのを自動で除去したい、というのが上に挙げた「類似画像の除去」の課題。

同じ画像であればスキップする

というのが当然思いつく解決法で、2つの画像が同じかどうかは以下で判定できる。

func ==(lhs: UIImage, rhs: UIImage) -> Bool {
    lhs === rhs || lhs.pngData() == rhs.pngData()
}

ピクセルデータが全く同じであれば、これがtrueになる。

これだけでいくつかの「同じページの連続」は除去できた。

しかし、実際はかなり多くのケースで、この方法はうまくいかない

たとえば以下のようなケース:

画像A
画像B

まったく同じ画像を2枚貼っているようだが、ピクセルデータ的には差分がある

実際に差分をとった画像を出力してみると、こんな感じ:

うっすらと差分がある。(これは制作者がこのフレーム間に意図的に差分を設けたわけでなく、おそらく動画エンコーディングによって発生する差分だと思う)

これをどう除去するか。

2つの画像の類似度を判定する / 差分を計算する

当然こういう話になるが、iOS/macOSでこれをシンプルに実装するにはどういう方法がいいだろうか。

Visionフレームワークにこういう類似度を計算するAPIがあるが、これはまったく違う画像の類似性を計算するものなので、今回の課題とは用途がまったく違う。

Core Imageを利用して次のような方法を取ることにした。

ここから先は

4,322字
文章やサンプルコードは多少荒削りかもしれませんが、ブログや書籍にはまだ書いていないことを日々大量に載せています。たったの400円で、すぐに購読解除してもその月は過去記事もさかのぼって読めるので、少しでも気になる内容がある方にはオトクかと思います。

技術的なメモやサンプルコード、思いついたアイデア、考えたこと、お金の話等々、頭をよぎった諸々を気軽に垂れ流しています。

最後まで読んでいただきありがとうございます!もし参考になる部分があれば、スキを押していただけると励みになります。 Twitterもフォローしていただけたら嬉しいです。 https://twitter.com/shu223/