ffmpeg でドット絵風の低画質に変換する


画像をドット絵風の低画質に変換するTwitter Bot「低画質」を作った – razokulover publog で話題になったのを ffmpeg のフィルタでドット絵風の低画質に変換する。

ffmpeg での出力例
けものフレンズプロジェクト|公式サイト よりサーバルちゃんを引用

けもフレ図鑑のサーバルちゃん、左がオリジナル、右が pixeliz0r 0.8倍の16色

アルゴリズムについては上のブログにあるように

  1. 画像を1×1ピクセルより大きいサイズで分割する
  2. 分割した各領域の色の平均値を算出する
  3. 算出した色をkmeans法でクラスタリングし、色数を減らす
  4. 各分割した領域をクラスタリングされた色で塗りつぶす

これを ffmpeg のフィルタで行う

  • scale, zscale フィルタで解像度を8の倍数にしてモザイク化できない映像の解像度を丸める
  • frei0r フィルタの pixeliz0r で分割して平均化しモザイクのようにする
  • palettegen フィルタで減色する色を決める
  • paletteuse フィルタで palettegen で決めた色に減色する
  • アルファチャンネルがある場合は lut2 フィルタでアルファチャンネルをコピーする

ここで問題になるのが外部ライブラリに依存する frei0r フィルタで、Windows 環境なら Zeranoe ffmpegDLL を使えば手軽に試せるが、それ以外の場合は、frei0r フィルタが使える ffmpeg と frei0r のライブラリを各自で作らなければならない。

使うフィルタの解説

コマンド例

使う色を決めるパレットを作るコマンドと、そのパレットを使って減色する2つのコマンドに分けられる。最初のコマンドは基本的には後述する色数の指定だけ変える。

画像の場合のコマンド例

ffmpeg -i input -vf scale="trunc(iw/8)*8:trunc(ih/8)*8,frei0r=pixeliz0r",palettegen=24:stats_mode=0 palettegen.png
ffmpeg -i input -i palettegen.png -filter_complex scale="trunc(iw/8)*8:trunc(ih/8)*8,frei0r=pixeliz0r",paletteuse=0 paletteuse.png

アルファチャンネルのある画像の場合のコマンド例

ffmpeg -i input -vf scale="trunc(iw/8)*8:trunc(ih/8)*8,frei0r=pixeliz0r",palettegen=24:stats_mode=0 palettegen.png
ffmpeg -i input -i palettegen.png -filter_complex scale="trunc(iw/8)*8:trunc(ih/8)*8,frei0r",split[a],paletteuse=0,[a]lut2=y:y:y:x paletteuse.png

動画の場合のコマンド例

ffmpeg -i input -vf scale="trunc(iw/8)*8:trunc(ih/8)*8,frei0r=pixeliz0r",palettegen=24:stats_mode=2 -vcodec ffv1 -an palettegen.mkv
ffmpeg -i input -i palettegen.mkv -filter_complex scale="trunc(iw/8)*8:trunc(ih/8)*8,frei0r=pixeliz0r",paletteuse=0 -an paletteuse.gif

動画のすべてのフレームをドット絵風にしない場合はあらかじめ時間指定してカットするか、-ss 入力時間 -i 入力ファイル -vf(filter_complex) フィルタ -t 出力時間 を併用する。ここでは開始5秒から5秒間出力する。
ffmpeg -ss 5 -i input -vf scale="trunc(iw/8)*8:trunc(ih/8)*8,frei0r=pixeliz0r",palettegen=24:stats_mode=2 -t 5 -vcodec ffv1 -an palettegen.mkv
ffmpeg -ss 5 -i input -i palettegen.mkv -filter_complex scale="trunc(iw/8)*8:trunc(ih/8)*8,frei0r=pixeliz0r",paletteuse=0 -t 5 -an paletteuse.gif

詳細な設定方法

リサイズ

本映像に8の倍数に丸めるのなら上のコマンドのままでよいが、任意の横、または縦の解像度にしたい場合は設定を変える。ただし設定値の片方はあらかじめ8の倍数にすること。

横幅を 1280 にして縦幅を元映像のアスペクト比をなるべく維持しつつ8の倍数に"scale=1280:trunc((ih*ow/iw)/8)*8"
縦幅を 960 にして横幅を元映像のアスペクト比をなるべく維持しつつ8の倍数に"scale=trunc((iw*oh/ih)/8)*8:960"

ドットの荒さを変える

シンプルなアイコンなら pixeliz0r の既定値、または少し上げてもよい。逆に複雑な場合は少し下げるとよい。既定値から上げるとモザイクが大きく、下げると小さくなる。
既定値(どちらも同じ):frei0r=pixeliz0r、”frei0r=pixeliz0r:0.0194444|0.0243056″

既定値からの倍率の目安

10 0.194444 0.243056
9 0.1749996 0.2187504
8 0.1555552 0.1944448
7 0.1361108 0.1701392
6 0.1166664 0.1458336
5 0.097222 0.121528
4 0.0777776 0.0972224
3 0.0583332 0.0729168
2 0.0388888 0.0486112
1 0.0194444 0.0243056
0.9 0.01749996 0.02187504
0.8 0.01555552 0.01944448
0.7 0.01361108 0.01701392
0.6 0.01166664 0.01458336
0.5 0.0097222 0.0121528

色の数を変える

palettegen フィルタの最初の引数、コマンド例では 24 の値を変える。

出力形式を変える

出力フォーマットは GIF、アニメGIF、PNG、アニメPNG、WEBM(VP9)、MP4(AVC) のどれでも使える。

GIF、アニメGIF の場合

paletteuse の出力拡張子を paletteuse.gif に変える。
ffmpeg -i input -i palettegen.mkv -filter_complex scale="trunc(iw/8)*8:trunc(ih/8)*8,frei0r=pixeliz0r",paletteuse=0 -an paletteuse.gif

アニメPNG の場合

paletteuse の出力拡張子を paletteuse.apng に変える。
ffmpeg -i input -i palettegen.mkv -filter_complex scale="trunc(iw/8)*8:trunc(ih/8)*8,frei0r=pixeliz0r",paletteuse=0 -an paletteuse.apng

WEBM(VP9) の場合

-acodec opus(または libopus) -vcodec libvpx-vp9 -pix_fmt yuv420p paletteuse.webm に変える。
ffmpeg -i input -i palettegen.mkv -filter_complex scale="trunc(iw/8)*8:trunc(ih/8)*8,frei0r=pixeliz0r",paletteuse=0 -acodec opus -vcodec libvpx-vp9 -pix_fmt yuv420p paletteuse.webm

MP4(AVC) の場合

-acodec copy(aac ではない場合は aac) -vcodec libx264 -pix_fmt yuv420p paletteuse.mp4 に変える。
ffmpeg -i input -i palettegen.mkv -filter_complex scale="trunc(iw/8)*8:trunc(ih/8)*8,frei0r=pixeliz0r",paletteuse=0 -acodec copy -vcodec libx264 -pix_fmt yuv420p paletteuse.mp4

関連記事
ffmpeg で Twitter に投稿できる PNG に変換する

コメントを残す

メールアドレスが公開されることはありません。