2つ入力した映像の輝度、コントラスト、構造などを軸にピクセル単位の比較だけではなく周囲のピクセルとの相関をみて比較してオリジナルにどれだけ忠実であるか SSIM の値を計算する。主な用途はエンコード前後を比較してどれだけ劣化したのか、特定のフレームを抽出してエンコードを見直したりする。比較する動画は同じ解像度とfps、ピクセルフォーマットである必要がある。libx264 エンコードでリアルタイムで計測する場合はオプションの-tune ssim -ssim 1を使う。

ファイルの入力順が逆だったのを訂正した。2021年8月11日
1入力がオリジナルの動画、2入力がSSIMを計算する動画ではなく、1入力がSSIMを計算する動画で、2入力がオリジナルの動画でlibvmafフィルタと同じ順番。

基本コマンド

最終結果だけを表示。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を高くしない限り、達成困難。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)