知覚ラダー(PSNR+SSIM+VMAF統合)でQ値決定を再現性のある運用へ
従来の Quality Ladder は PSNRのみ/SSIMのみ といった単指標依存で“違和感” を取りこぼすことがあります。多指標を統合し 再現性あるQ決定 に拡張します。
- Zスコア化で指標を無次元化
- 重み付き線形合成で統合スコア
- Elbow + 増分閾値で最適Q
1. 単指標の限界
PSNR は平均二乗誤差由来で 局所構造/彩度ずれ に鈍感、SSIM は色差と高周波ノイズを見逃し、VMAF は精度が高い一方で計算コストが高い。単指標最適化は “現場での違和感” を捕捉しきれません。
統合ラダーは指標を 無次元正規化→重み付き合成→効率勾配解析 し 再現性ある Q 選定 を可能にします。
2. データセット設計
偏りを防ぐため画像カテゴリを層別 (texture / portrait / lineart / UI / lowlight / gradient)。seed 固定で比較揺らぎを抑えます。
{"version":3,"strata":{"texture":12,"portrait":8,"lineart":6,"ui":10,"lowlight":4,"gradient":4},"seed":20250907}
seed 変更時は CI で “データセット差分” をログ化し品質推移との混同を防止。
3. 正規化
各指標スケールを Z スコアに揃え欠損は 0 (平均) で補完し安定性重視。
// 指標をZスコア化
function z(values:number[], v:number){
const m = mean(values);
const s = std(values);
return (v - m) / (s || 1);
}
function safeZ(vals:number[], v:number|undefined){return v==null?0:z(vals,v);}
4. 重み付け & 合成
初期重み (0.3 / 0.3 / 0.4 / -0.2)。主観 AB ラベルを教師に L2 正則回帰で再学習可能。
// 統合スコア wPSNR + wSSIM + wVMAF - wBytes
for (const p of ladder){
p.score = 0.3*z(psnrs,p.psnr) + 0.3*z(ssims,p.ssim) + 0.4*z(vmafs,p.vmaf) - 0.2*z(bytes,p.bytes);
}
// 重み再学習 (概念)
const w = ridgeRegression(Zmatrix, subjectiveWins);
5. ラダー JSON スキーマ
{"image":"hero.png","enc":"avif","qset":[{"q":18,"psnr":37.1,"ssim":0.985,"vmaf":94.8,"bytes":18234,"score":1.92}],"best":18,"seed":20250907}
score 勾配 (Δscore/Δbytes) がしきい値を割った最初の Q を best とする。
6. 最適Q探索
Elbow 判定 + 効率 (Δscore ÷ Δbytes) 閾値併用で過学習的高Q選択を抑制。
// スコア最大の踊り場手前 (elbow) を探索
const sorted = ladder.slice().sort((a,b)=>a.q-b.q);
let best = sorted[0];
for (let i=1;i<sorted.length;i++){
if (sorted[i].score > best.score + 0.15) best = sorted[i];
}
for (let i=1;i<sorted.length;i++){const g=sorted[i].score-sorted[i-1].score;const c=sorted[i-1].bytes-sorted[i].bytes; if(g/(c||1)<0.0005){best=sorted[i];break;}}
7. CI 逸脱検知
PR と base のラダーを比較し score 差 / best Q 差 / 指標 Z 差 を閾値評価。
# CI: ラダーJSONの統合スコア逸脱検知
node scripts/ladder.js --image hero.png --vmaf --out head.json
node scripts/ladder.js --image hero.png --vmaf --ref origin/main --out base.json
node scripts/ladder-merge-score.js base.json head.json --delta-th 0.4
if (Math.abs(head.best-base.best)>2 && head.score<base.score-0.25) fail();
VMAF は代表 20% サンプルのみ、残りは線形近似。
8. 運用ガバナンス
- seed 変更は commit diff で明示ログ
- 重み更新は weights.jsonl に追記 (再現性)
- Q 変更は 帯域節約推定と共に PR description に出力
9. FAQ
- 重みドリフト? → 直近3回移動平均適用
- VMAF 遅い? → AVX2 / フレーム間 skip / 並列
- 低解像度? → MS-SSIM 追加で補強
10. まとめ
統合ラダーは “指標→意思決定” の翻訳層。Adaptive Q / Chroma 最適化や Tiling 戦略など他改善の評価基盤になります。