0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Vmaf と fps の細かい話

Posted at

Vmaf とは

簡単にいうと Netflix が開発したライブラリで、二つの動画を比較して片方を参照してもう片方がどの程度劣化したかをスコアとして表現するもの。

疑問

vmaf って要は動画のフレームとフレームをいっこずつ比較しているんだから、フレーム間引いても統計的には問題ないんじゃないの?って思ったので、そうなのかどうなのか調査。

ここを理解することで fps を変更した時の vmaf の使い方もわかるはず

結論

vmaf は単純に一個ずつフレームを比較するわけではない。例えば motion features とかだと前のフレームの情報も参照して feature を求めている。なのでフレームが一緒でも前のフレームとの関係によってスコアが変わる。

つまり以下のようなことが言える

  • 元の動画と fps から fps を減らした場合、元の fps に合わせて score を求めるべき
  • 元の動画からなんらかの補完手法で fps を増やした場合、それがスコアにプラスとしてに評価されることはない(と思ってる)
  • 計算速度のために frame を間引く意図で fps を下げて score を求めるとスコアは意図しないものとなる

以下、メモ

ここからは読まなくてもいい

まず Vmaf とは

まず、データセットは

  • 1080p のディスプレイに Netflix 10 秒程度の video clip を表示
  • 実際にユーザに bad, poor, fair, good, excellent の 5 段階評価してもらう
  • bad = 20 〜 excellent = 100 とスコア化してデータセットにする

そんで、そのデータセットの video clip 動画から以下のような手法で各種 features を取得して、その features から Score を予測する SVM モデルを作るという手法

Feature name Identifier Core feature? Individual Metrics
VIF vif Yes vif_scale0, vif_scale1, vif_scale2, vif_scale3
Motion2 motion Yes motion, motion2
ADM adm Yes adm2, adm_scale0, adm_scale1, adm_scale2, adm_scale3
CAMBI cambi No cambi
CIEDE2000 ciede No ciede2000
MS-SSIM float_ms_ssim No
PSNR psnr No psnr_y, psnr_cb, psnr_cr
PSNR-HVS psnr_hvs No psnr_hvs, psnr_hvs_y, psnr_hvs_cb, psnr_hvs_cr
SSIM float_ssim No

ほんで

libvmaf というライブラリになってて

(めちゃくちゃ雑にかいているので動くかは謎だけど)大体以下のようなコードを書く

// context の初期化(各動画フレームの feature のデータパイプラインのようなものを内部に持っている)
VmafContext *vmaf;
vmaf_init(&vmaf, cfg);

// model のロード
VmafCudaConfiguration cfg = { 0 };
VmafModel *model;
vmaf_model_load(&model, &cfg, "vmaf_b_v0.6.3")
vmaf_use_features_from_model(vmaf, model);


// 動画の 1 フレームごとに以下のような処理をする。
// raw data を yuv 形式で vmaf の VmafPicture 構造体に入れる(本当は ffmpeg とか gst とか使う)
VmafPicture ref_pic;
vmaf_picture_alloc(&ref_pic, VMAF_PIX_FMT_YUV420P, 8, 1920, 1080); // 1080p yuv420 の場合
memcpy(ref_pic.data[0], ref_frame.y_data, 1920 * 1080);
memcpy(ref_pic.data[1], ref_frame.y_data, 1920 * 1080 / 4); 
memcpy(ref_pic.data[2], ref_frame.y_data, 1920 * 1080 / 4); 

// raw data を yuv 形式で vmaf の VmafPicture 構造体に入れる(本当は ffmpeg とか gst とか使う)
VmafPicture dist_pic;
vmaf_picture_alloc(&dist_pic, VMAF_PIX_FMT_YUV420P, 8, 1920, 1080); // 1080p yuv420 の場合
memcpy(dist_pic.data[0], dist_frame.y_data, 1920 * 1080);
memcpy(dist_pic.data[1], dist_frame.y_data, 1920 * 1080 / 4); 
memcpy(dist_pic.data[2], dist_frame.y_data, 1920 * 1080 / 4); 

// vmaf context に frame の index と一緒に登録、 feature extract と svm prediction が行われる
vmaf_read_pictures(vmaf, &ref_pic, &dist_pic frame_index);



// 計算が全部終わるまで待つ
vmaf_read_pictures(vmaf, NULL, NULL, 0);

// 結果を得る
double vmaf_score;
vmaf_score_pooled(vmaf, model, VMAF_POOL_METHOD_MEAN, &vmaf_score, first_frame_index, last_frame_index);

printf("Score: %f", vmaf_score);

で本題

vmaf_score_pooled で取得されるスコアって単純に一個一個のフレームのスコアを平均するんだっけ?ってこと

コードを読んでみたらそういう実装になっている。

でも

ただ、経験的にフレームを間引くとスコアが大きく変わることを経験的に知っていて、それがなぜ発生するかを調べる必要が出てきた。

で、以下のあたりのコードを読んでみたところ

motion feature など VMAF_FEATURE_EXTRACTOR_TEMPORAL が設定されているものは single thread で feature extraction が順番に行われており、以下のコードのように二つ前までのフレームが参照されていることがわかった。

なるほどですね。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?