2つ入力した映像の輝度、コントラスト、構造などを軸にピクセル単位の比較だけではなく周囲のピクセルとの相関をみて比較してオリジナルにどれだけ忠実であるか SSIM の値を計算する。主な用途はエンコード前後を比較してどれだけ劣化したのか、特定のフレームを抽出してエンコードを見直したりする。比較する動画は同じ解像度とfps、ピクセルフォーマットである必要がある。libx264 エンコードでリアルタイムで計測する場合はオプションの-tune ssim -ssim 1を使う。
ファイルの入力順が逆だったのを訂正した。2021年8月11日
1入力がオリジナルの動画、2入力がSSIMを計算する動画ではなく、1入力がSSIMを計算する動画で、2入力がオリジナルの動画でlibvmaf
フィルタと同じ順番。
- 文字を描写する drawtext
- 新しい映像の品質評価 libvmaf
- 2つの映像の画質評価をする psnr
- 新しい映像の動きの評価 vmafmotion
- 比較する動画の解像度に合わせる scale2ref
- メタデータを映像化する drawgraph, adrawgraph
- 映像フィルタを当てる前後のデータを見える化する
- メタデータをコンソールに表示する metadata, ametadata
- Windows の ffmpeg で生放送する方法 : エンコードのログ出力の方法
基本コマンド
最終結果だけを表示。1入力がSSIMを計算する動画で、2入力が元の動画。
ffmpeg -i enc.mp4 -i orig.mp4 -filter_complex ssim -an -f null -
1入力と2入力の解像度が異なるときはscale2ref
フィルタで解像度指定しなくても揃えられる。
ffmpeg -i enc.mp4 -i orig.mp4 -filter_complex scale2ref,ssim -an -f null -
ログファイルを出力する。
ffmpeg -i enc.mp4 -i orig.mp4 -filter_complex scale2ref,ssim=f=ssim.txt -an -f null -
metadata
フィルタでフレーム単位でコンソールに表示する方法。ここではunsharp
フィルタの Y の ssim を表示している。
ffplay -i input -vf split[a][b];[b]unsharp[B];[a][B]ssim,metadata=print:key=lavfi.ssim.Y
drawtext
フィルタで映像に焼き付けて再生する。
ffplay -f lavfi -i movie=enc.mp4[a];movie=orig.mp4[b];[a][b]ssim,drawtext=fontfile=C\\://Windows/Fonts/arial.ttf:fontsize=20:fontcolor=white:box=1:boxcolor=black@0.4:text='"SSIM="%{metadata\:lavfi.ssim.ALL}'
lavfi.ssim.X形式でXに代入できるのは、Y, U, V, R, G, B, All, dBで小文字でも可能。
ffprobeで調べる。
ffprobe -f lavfi -i movie=enc.mp4[0];movie=orig.mp4[1];[0][1]ssim -show_entries packet=pts_time -show_entries packet_tags=lavfi.ssim.Y,lavfi.ssim.All -of csv=p=0 > ssim_y_all.csv
コンテナフォーマットが異なる、例えばMP4とMKVなどを比較する。
ffmpeg -i enc.mp4 -i orig.mkv -filter_complex "[0:v]settb=1/AVTB,setpts=PTS-STARTPTS[0v];[1:v]settb=1/AVTB,setpts=PTS-STARTPTS[1v];[0v][1v]scale2ref,ssim" -an -f null -
framesync の設定にも対応している。
2ファイル入力するフィルタの挙動設定 framesync
動画の短い時間の方で終了するにはeof_action=1:shortest=1:repeatlast=0を追加する。
ffmpeg -i enc.mp4 -i orig.mkv -filter_complex "[0:v]settb=1/AVTB,setpts=PTS-STARTPTS[0v];[1:v]settb=1/AVTB,setpts=PTS-STARTPTS[1v];[0v][1v]scale2ref,ssim=eof_action=1:shortest=1:repeatlast=0" -an -f null -
ffmpeg 5.1以降はts_sync_mode対応したのでsettb=1/AVTB,setpts=PTS-STARTPTS
が不要になった。
ffmpeg -i 調べたい動画 -i 元の動画 -filter_complex "scale2ref=flags=bicubic,ssim=eof_action=1:shortest=1:repeatlast=0:ts_sync_mode=1" -an -f null -
公式ドキュメント:
FFmpeg Filters Documentation : ssim
FFmpeg Filters Documentation : psnr
オプション
stats_file, f[string]
ログファイルの出力名。小数点以下は6桁まで書き込む。–で標準出力する。
ログファイルの見方
- n
フレーム番号 - Y, U, V, R, G, B
コンポーネント別の SSIM。1 に近いほど忠実 - All
全体の平均 SSIM。各チャンネル平均 - dB
全体の平均 SSIM(dB)。大きいほど高画質
扱えるメタデータ。
lavfi.ssim.Y lavfi.ssim.U lavfi.ssim.V lavfi.ssim.R lavfi.ssim.G lavfi.ssim.B lavfi.ssim.All lavfi.ssim.dB
評価方法
似た指標に PSNR もあるが主観的な画質の比較なら SSIM のほうがよい。
ssim
フィルタ、psnr
フィルタを併用しログをテキストで出力する。
ffmpeg -i enc.mp4 -i orig.mp4 -filter_complex "ssim=f=ssim.txt;[0:v][1:v]psnr=f=psnr.txt" -an -f null -
TB、PTSも揃えてssim
フィルタ、psnr
フィルタを併用する。
ffmpeg -i enc.mp4 -i orig.mp4 -filter_complex "[0:v]settb=1/AVTB,setpts=PTS-STARTPTS,split[0va][0vb];[1:v]settb=1/AVTB,setpts=PTS-STARTPTS[1v];[0va][1v]scale2ref[0va][1v];[1va]split[1va][1vb];[0va][1va]ssim=eof_action=1:shortest=1:repeatlast=0;[0vb][1vb]psnr=eof_action=1:shortest=1:repeatlast=0" -an -f null -
http://www.jiima.or.jp/pdf/5_JIIMA_guideline.pdf より
PSNR | SSIM | 主観評価 |
40~∞[dB] | 0.98以上 | 元の画像と圧縮画像の区別がつかない |
30~40[dB] | 0.90~0.98 | 拡大すれば劣化がわかるレベル |
30以下[dB] | 0.90以下 | 明らかに劣化がわかる |
x264におけるSSIMの目安
http://www.wikihouse.com/htumenc/index.php?SSIM より
SSIM値 | qp設定値(例) | |
0.98 以上 | 20 | オリジナルと区別がつかない。 |
0.95 | 30 | 見るに耐えない。(*または辛うじて、そこそこ見られる*) |
0.9 | 40 | 非常に醜い。 |
0.8 | 51 | これ以上は圧縮できない |
0.7 以下 | – | 素材に大量のノイズを加え、さらにそのノイズを量子化工程で消し去るほどqpを高くしない限り、達成困難。 |