修: 对齐修好了配对,判决却用旧配对的帧占比(0912 洞见 假拒绝)
洞见在 crf 24 上被判 'mean 0.9974 但 20/1199 帧低于 0.85' → 拒。实测: 0.9974/0.9936 是对齐后的数字,
而 20 帧是直配的旧计数 —— 两个数字来自不同配对。三向对照测试(本地,同一 60 s 窗口):
健康对 min 0.9940 mean 0.9971 0 坏帧 → 走快路径(无对齐搜索),通过 ✓
错位对 'alignment repaired the pairing: 20 frame(s) below 0.85 before, 0 after'
min 0.9940 mean 0.9972 1199 帧 0 坏帧 → 通过 ✓ ← 与洞见判决书 20/1199 逐项吻合
真缺陷对 mean 0.9612 151 帧(10.07%) → 仍被拒 ✓(没变橡皮章)
改动:
- 触发条件补上帧占比: 原来只看 min<0.985 / mean<0.995,帧占比超标不触发搜索;
- _paired_ssim / _perframe_best 现在返回 below 计数,并同样剔除近平坦帧(之前对齐后的数字
含黑场帧,会让对齐看起来比直配还差);
- 采用对齐结果时同步更新 stats['below'](判决用的就是它),并打印 'X frames below before, Y after'。
This commit is contained in:
+48
-12
@@ -742,7 +742,12 @@ def ssim_vs_source(src_local, out_local, info, workdir, tag, dur=SSIM_WINDOW):
|
||||
# 2. coarse, STEP 10 over +-100 - unchanged, for a file that has drifted by tens of frames;
|
||||
# 3. per-frame best match over +-ALIGN_PERFRAME, for a window whose displacement varies.
|
||||
used_off = 0 # the alignment the VMAF observation below is measured at
|
||||
if n and (lo is None or lo < SSIM_TARGET or mean is None or mean < SSIM_MEAN_MIN):
|
||||
# Trigger on the FRAME-SHARE as well, not just min/mean: a window can pair wrongly for a stretch
|
||||
# of frames while its min stays above SSIM_TARGET, and then the share is the only symptom. That
|
||||
# was 0912 洞见 (20 of 1199 frames below 0.85 - refused on the share, never searched).
|
||||
direct_below = bad
|
||||
if n and (lo is None or lo < SSIM_TARGET or mean is None or mean < SSIM_MEAN_MIN
|
||||
or bad > MAX_BAD_SHARE * n):
|
||||
best = None
|
||||
nf = min(n, 1200)
|
||||
pid = os.getpid() # two lanes share the stage dir: a fixed tag let them overwrite
|
||||
@@ -751,9 +756,10 @@ def ssim_vs_source(src_local, out_local, info, workdir, tag, dur=SSIM_WINDOW):
|
||||
for off in offs:
|
||||
if off == 0:
|
||||
continue
|
||||
mn, mm, k = _paired_ssim(ref, out, off, nf, workdir, "%d%s%d" % (pid, stage, abs(off)))
|
||||
mn, mm, k, bl = _paired_ssim(ref, out, off, nf, workdir,
|
||||
"%d%s%d" % (pid, stage, abs(off)), flat)
|
||||
if mn is not None and (best is None or mn > best[0]):
|
||||
best = (mn, mm, k, off, stage)
|
||||
best = (mn, mm, k, off, stage, bl)
|
||||
if best and best[0] >= 0.90 and best[1] >= 0.98:
|
||||
break # the fine stage already explains it; don't pay for the rest
|
||||
if best and best[0] >= 0.90 and best[1] >= 0.98:
|
||||
@@ -767,12 +773,24 @@ def ssim_vs_source(src_local, out_local, info, workdir, tag, dur=SSIM_WINDOW):
|
||||
% (best[3], best[4]))
|
||||
lo, mean, n = best[0], best[1], best[2]
|
||||
used_off = best[3]
|
||||
# The share MUST come from the same pairing as the min/mean that were just adopted.
|
||||
# Leaving the direct count in place refused an encode whose pictures had already been
|
||||
# verified at the aligned offset (0912 洞见: min 0.9936 mean 0.9974 after realignment,
|
||||
# refused by "20 of 1199 frames below 0.85" from the WRONG pairing).
|
||||
if best[5] is not None:
|
||||
stats["below"] = best[5]
|
||||
log(" alignment repaired the pairing: %d frame(s) below %.2f before, %s after"
|
||||
% (direct_below, BAD_FRAME_SSIM, stats.get("below")))
|
||||
else:
|
||||
per = _perframe_best(ref, out, nf, workdir, "%d" % pid)
|
||||
per = _perframe_best(ref, out, nf, workdir, "%d" % pid, flat)
|
||||
if per and per[1] >= 0.90 and per[2] >= 0.98:
|
||||
stats["align_note"] = ("per-frame best match (+-%d frames) - displacement varies "
|
||||
"inside the window" % ALIGN_PERFRAME)
|
||||
lo, mean, n = per[1], per[2], per[0]
|
||||
if per[3] is not None:
|
||||
stats["below"] = per[3]
|
||||
log(" per-frame realignment: %d frame(s) below %.2f before, %s after"
|
||||
% (direct_below, BAD_FRAME_SSIM, stats.get("below")))
|
||||
else:
|
||||
log(" no alignment explains the mismatch (best constant offset %s,"
|
||||
" per-frame best-match %s) - keeping the direct-pairing verdict"
|
||||
@@ -901,18 +919,34 @@ def vmaf_of_pair(ref_raw, out_raw, off, nf, workdir, tag):
|
||||
pass
|
||||
|
||||
|
||||
def _paired_ssim(ref_raw, out_raw, off, nf, workdir, tag):
|
||||
"""(min, mean, frames) for one constant offset - see `_ssim_series` for the sign convention."""
|
||||
def _paired_ssim(ref_raw, out_raw, off, nf, workdir, tag, flat=()):
|
||||
"""(min, mean, frames, below) for one constant offset - see `_ssim_series` for the sign.
|
||||
|
||||
`flat` holds the indices of near-flat source frames; they are dropped here exactly as the direct
|
||||
pairing drops them, so the alignment is judged on the same frame set as the verdict that follows
|
||||
(without this a black fade dragged the aligned mean below the direct one and the search looked
|
||||
useless on files that were merely dark).
|
||||
`below` is what the frame-share test actually consumes - returning only min/mean meant a repaired
|
||||
alignment still got refused by the share count taken from the WRONG pairing.
|
||||
"""
|
||||
vals = _ssim_series(ref_raw, out_raw, off, nf, workdir, tag)
|
||||
return (min(vals), sum(vals) / len(vals), len(vals)) if vals else (None, None, 0)
|
||||
base = max(0, off)
|
||||
keep = [v for i, v in enumerate(vals) if (base + i) not in flat]
|
||||
if not keep:
|
||||
return (None, None, 0, 0)
|
||||
return (min(keep), sum(keep) / len(keep), len(keep),
|
||||
sum(1 for v in keep if v < BAD_FRAME_SSIM))
|
||||
|
||||
|
||||
def _perframe_best(ref_raw, out_raw, nf, workdir, tag):
|
||||
"""(frames, min, mean) where each frame scores against the best of its +-ALIGN_PERFRAME
|
||||
neighbours.
|
||||
def _perframe_best(ref_raw, out_raw, nf, workdir, tag, flat=()):
|
||||
"""(frames, min, mean, below) where each frame scores against the best of its +-ALIGN_PERFRAME
|
||||
neighbours, over the non-flat frames only.
|
||||
|
||||
For a window whose displacement is not one constant shift. A wrong-picture defect cannot be
|
||||
rescued by this - such frames have no good neighbour - while a duplicate-frame stretch can.
|
||||
rescued by this - such frames have no good neighbour - while a duplicate-frame stretch can, and
|
||||
that is precisely the shape a false frame-share refusal has (measured 2026-10-12: 0912 洞见
|
||||
scored 20 of 1199 frames below 0.85 with a 0.9974 mean by direct pairing; shifting the encode by
|
||||
ONE frame produced 22 such frames on the same content and a correct pairing produced none).
|
||||
"""
|
||||
per = {}
|
||||
for off in range(-ALIGN_PERFRAME, ALIGN_PERFRAME + 1):
|
||||
@@ -920,12 +954,14 @@ def _perframe_best(ref_raw, out_raw, nf, workdir, tag):
|
||||
base = max(0, off)
|
||||
for i, v in enumerate(vals):
|
||||
j = base + i
|
||||
if j in flat:
|
||||
continue
|
||||
if v > per.get(j, -1.0):
|
||||
per[j] = v
|
||||
if not per:
|
||||
return None
|
||||
s = [per[k] for k in sorted(per)]
|
||||
return len(s), min(s), sum(s) / len(s)
|
||||
return len(s), min(s), sum(s) / len(s), sum(1 for v in s if v < BAD_FRAME_SSIM)
|
||||
|
||||
|
||||
def pin_to_e_cores(mask=None):
|
||||
|
||||
Reference in New Issue
Block a user