画像をドット絵風の低画質に変換するTwitter Bot「低画質」を作った – razokulover publogで話題になったのを ffmpeg のフィルタでドット絵風の低画質に変換する。
関連記事
ぼやけた画像からドット絵を抽出する – Posts – Seaside Laboratory
ffmpeg での出力例
けものフレンズプロジェクト|公式サイトよりサーバルちゃんを引用。
現在のページ:FRIENDS | けものフレンズプロジェクト
- 画像を1×1ピクセルより大きいサイズで分割する
- 分割した各領域の色の平均値を算出する
- 算出した色をkmeans法でクラスタリングし、色数を減らす
- 各分割した領域をクラスタリングされた色で塗りつぶす
これを ffmpeg のフィルタで行う、
scale, zscale
フィルタで解像度を8の倍数にしてモザイク化できない映像の解像度を丸めるfrei0r
フィルタのpixeliz0rで分割して平均化しモザイクのようにするpalettegen
フィルタで減色する色を決めるpaletteuse
フィルタでpalettegen
で決めた色に減色する- アルファチャンネルがあれば
lut2
フィルタでアルファチャンネルをコピーする
ここで問題になるのが外部ライブラリに依存するfrei0r
フィルタで、Windows環境ならfrei0r
フィルタが使えるffmpegとfrei0rのライブラリを各自で作らなければならない。frei0rライブラリが使えないときはm-ab-s/media-autobuild_suiteを使い自分で用意するか、scale
フィルタなどでneighborフラグを立てて解像度を戻すとそれらしくなる。現在はpixelize
フィルタが追加されたのでfrei0r
フィルタを使わなくても良い。
使うフィルタの解説
- リサイズする scale
- Zライブラリを使ったリサイズフィルタ zscale
- ffmpeg で使える frei0r フィルタの使い方
- LUTを手軽に入れ替えられるlut2、tlut2、swapuv
- ffmpeg で 256色を最適化する palettegen, paletteuse
目次
コマンド例
使う色を決めるパレットを作るコマンドと、そのパレットを使って減色する2つのコマンドに分けられる。最初のコマンドは基本的には後述する色数の指定だけ変える。
画像の場合のコマンド例
ffmpeg -i input -vf scale="trunc(iw/8)*8:trunc(ih/8)*8:flags=neighbor,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:flags=neighbor,frei0r=pixeliz0r",paletteuse=0 paletteuse.png
1行コマンド
ffmpeg -i input -lavfi scale="trunc(iw/8)*8:trunc(ih/8)*8:flags=neighbor,frei0r=pixeliz0r",split[a],palettegen=24:stats_mode=0[pal],[a][pal]paletteuse=0 output.gif
アルファチャンネルのある画像の場合のコマンド例
ffmpeg -i input -vf scale="trunc(iw/8)*8:trunc(ih/8)*8:flags=neighbor,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:flags=neighbor,frei0r=pixeliz0r",split[a],paletteuse=0,[a]lut2=y:y:y:x paletteuse.png
1行コマンド
ffmpeg -i input -lavfi scale="trunc(iw/8)*8:trunc(ih/8)*8:flags=neighbor,frei0r=pixeliz0r",split=3[a][b],palettegen=24:stats_mode=0[pal],[a][pal]paletteuse=0,[b]lut2=y:y:y:x output.png
動画の場合のコマンド例
ffmpeg -i input -lavfi scale="trunc(iw/8)*8:trunc(ih/8)*8:flags=neighbor,frei0r=pixeliz0r",split[a],palettegen=24:stats_mode=single[pal],[a][pal]paletteuse=new=1 -an out.gif
動画のすべてのフレームをドット絵風にしない場合はあらかじめ時間指定してカットするか、-ss 入力時間 -i 入力ファイル -vf(filter_complex) フィルタ -t 出力時間を併用する。ここでは開始5秒から5秒間出力する。
ffmpeg -ss 5 -i input -lavfi scale="trunc(iw/8)*8:trunc(ih/8)*8:flags=neighbor,frei0r=pixeliz0r",split[a],palettegen=24:stats_mode=single[pal],[a][pal]paletteuse=new=1 -t 5 -an out.gif
詳細な設定方法
リサイズ
本映像に8の倍数に丸めるのなら上のコマンドのままでよいが、任意の横、または縦の解像度にしたい場合は設定を変える。ただし設定値の片方はあらかじめ8の倍数にすること。
横幅を 1280 にして縦幅を元映像のアスペクト比をなるべく維持しつつ8の倍数に。
"scale=1280:trunc((ih*ow/iw)/8)*8:flags=neighbor"
縦幅を 960 にして横幅を元映像のアスペクト比をなるべく維持しつつ8の倍数に。
"scale=trunc((iw*oh/ih)/8)*8:960:flags=neighbor"
ドットの荒さを変える
シンプルなアイコンなら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
ffmpeg -i input -i palettegen.mkv -filter_complex scale="trunc(iw/8)*8:trunc(ih/8)*8:flags=neighbor,frei0r=pixeliz0r",paletteuse=0 -an paletteuse.gif
アニメPNG
ffmpeg -i input -i palettegen.mkv -filter_complex scale="trunc(iw/8)*8:trunc(ih/8)*8:flags=neighbor,frei0r=pixeliz0r",paletteuse=0 -an -f apng paletteuse.png
WEBM(VP9)
VP9(libvpx-vp9)のエンコード設定について
ffmpeg -i input -i palettegen.mkv -filter_complex scale="trunc(iw/8)*8:trunc(ih/8)*8:flags=neighbor,frei0r=pixeliz0r",paletteuse=0 -acodec opus -vcodec libvpx-vp9 -crf 30 -b:v 0 -qmin 20 -qmax 40 -pix_fmt yuv420p paletteuse.webm
MP4(AVC)
ffmpeg -i input -i palettegen.mkv -filter_complex scale="trunc(iw/8)*8:trunc(ih/8)*8:flags=neighbor,frei0r=pixeliz0r",paletteuse=0 -acodec copy -vcodec libx264 -pix_fmt yuv420p paletteuse.mp4