画像をドット絵風の低画質に変換するTwitter Bot「低画質」を作った – razokulover publog で話題になったのを ffmpeg のフィルタでドット絵風の低画質に変換する。
ffmpeg での出力例
けものフレンズプロジェクト|公式サイト よりサーバルちゃんを引用
アルゴリズムについては上のブログにあるように
- 画像を1×1ピクセルより大きいサイズで分割する
- 分割した各領域の色の平均値を算出する
- 算出した色をkmeans法でクラスタリングし、色数を減らす
- 各分割した領域をクラスタリングされた色で塗りつぶす
これを ffmpeg のフィルタで行う
scale, zscale
フィルタで解像度を8の倍数にしてモザイク化できない映像の解像度を丸めるfrei0r
フィルタの pixeliz0r で分割して平均化しモザイクのようにするpalettegen
フィルタで減色する色を決めるpaletteuse
フィルタでpalettegen
で決めた色に減色する- アルファチャンネルがある場合は
lut2
フィルタでアルファチャンネルをコピーする
ここで問題になるのが外部ライブラリに依存する frei0r
フィルタで、Windows 環境なら Zeranoe ffmpeg と DLL を使えば手軽に試せるが、それ以外の場合は、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 -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