yensaki’s blog

必要なものは締め切り

動画ファイルからいい感じに重複しない画像を取り出す

画像

画像は日常で使えたり使えなかったりして便利。 togetter.com

いろんなの使えたい

でも手元に画像はない

動画ファイルならあるんだけど。

じゃあ動画から画像を取り出せばいいのでは?

ffmpeg -i imovie.mp4 -ss 1 -vframes 1 -f image2 out.jpg

取り出したい画像を見つけて何回も繰り返すのは少しツラミ :smile:

動画から静止画を連続で

ffmpeg-r オプションを使えば連番で静止画を作成できる。

qiita.com

でも動画から一定間隔で取り出すと同じ画像、類似した画像もたくさんできる

これもまたツラミ :smile: 無駄が多くなっちゃう

なるべくユニークっぽく取り出してもらえない?

周辺探したところ、それができるものは見つからなかった。
ということでうまくできる方法を考える。
似てる画像がたくさんあるからツラミだとすればそれらを検知して消してくれればいいのでは?

イデア 1. 動画から一定間隔で静止画を取り出す 2. 静止画同士で類似画像度を判定して似てるやつらは消す

作った

github.com

名前が意外とハマって気に入った。
瞬間をいいとこ取り。

使用技術:

手順

  1. 動画ファイルから静止画を抽出
  2. 静止画をリサイズ
  3. 各画像から特徴を切り出してハッシュ値を算出(Perceptual Hash)
  4. それぞれを比較して類似画像を検出して削除

Perceptual Hash

Python の Imagehash を利用。
python便利…

一旦は phash を使用
画像間の類似度はハミング距離。

PyCall

その Python Imagehash は便利なんだけど
どうしても Ruby で全体を書きたい。

最初は Open3python を実行した。
でももっとちゃんとやりたくなったのでもう少し考える。
Ruby から Python function を実行できる PyCall があるのでそれを使いたい。
ちゃんと乗っておくと後々楽そうなので。

GitHub - mrkn/pycall.rb: Calling Python functions from the Ruby language

というわけで最終的には全部 Ruby ファイルで完結できた。
ハミング距離の計算もRuby で。

こんな感じ

24分程度のmp4を渡すと30分ぐらいで画像集ができた。
2/3ぐらいは 切り出しと convert の時間だった。
imagehash の算出/ハミング距離の計算/ファイル削除はせいぜい10分程度。

f:id:yensaki:20181202174726p:plain

3 Pictures/s で静止画を取っていたので24分は4300枚。 ハミング距離20までを類似として扱うと3500枚ほど削除できる。

まとめ

Ruby のライブラリで 動画から類似画像を(なるべく)除いた画像を切り出せるようになりました。
消しすぎ・残しすぎがまだいくらかあるのでもう一歩調整できる。
Python と PyCall に感謝。