iter9-T9+T10: 卡⑮ 分辨率案甲落码+卡⑰b C 档黄金图基准——stretch aspect expand→**keep**(1920 档=等比 1.35×+左右黑边 ~96px〔16:10 设计在 16:9 窗口,非字面 1.5×——呈报落码注记如实修正〕;逻辑布局 1920/1280 逐键一致实测 7 键)+HUD框架两档条款修订(1280 基准档定值口径+1920 全局等比)+§8.2 案甲注记+06 分辨率条目收口+资产升档条目案乙裁决落文+美术资产规格两项条目移除(裁决一甲/二追认)+tools/golden_compare.py(容差口径:灰度差>16 占比 ≤2%,四屏黄金图 artwork/qa-golden-20260930 建基准自比 0.00% PASS——升档批换代须显式重制)

This commit is contained in:
DKChan committed 2026-09-30 15:59:03 +08:00
1 parent a4fdf527f1
commit 08a0d88bd4
6 files changed
+72 -19

No files matched your search

+65
View File
@@ -0,0 +1,65 @@
#!/usr/bin/env python3
r"""golden_compare.py — C 档黄金图对比(迭代 9 卡⑰b 2026-09-30;呈现层测试分级·周期重闸件)。
用法: python tools/golden_compare.py <黄金图目录> <新截图目录> [屏清单...]
默认屏清单 = shot_menu.png shot_camp.png shot_level.png shot_battle.png。
判据(容差口径,v1 冻结):
① 四屏存在且尺寸一致(与黄金图逐屏比对);
② 逐像素灰度差 >16 的像素占比 ≤2%(抗锯齿/微噪声容差带——结构级变化必超带);
③ changed 占比 >2% 即 FAIL(视觉回归信号——逐屏列差异热区提示)。
基准冻结=2026-09-30(v3.5 视觉落码+营地终稿+分辨率案甲后);资产升档批换代时显式重制基准。
退出码: 0 = 全过 / 1 = 有失败。
"""
import sys
from pathlib import Path
from PIL import Image, ImageChops
TOLERANCE = 16 # 灰度差容差(单通道)
FAIL_RATIO = 0.02 # changed 占比失败线
def compare(base: Path, curr: Path, name: str, failures: list) -> None:
pb, pc = base / name, curr / name
if not pb.exists():
failures.append("%s: 黄金图缺失(基准未建)" % name)
return
if not pc.exists():
failures.append("%s: 新截图缺失" % name)
return
a = Image.open(pb).convert("L")
b = Image.open(pc).convert("L")
if a.size != b.size:
failures.append("%s: 尺寸 %s != 基准 %s" % (name, b.size, a.size))
return
diff = ImageChops.difference(a, b)
hist = diff.histogram()
total = a.size[0] * a.size[1]
changed = sum(hist[TOLERANCE + 1:]) / total
print("[golden] %s — changed=%.2f%%(容差 ≤%.0f 差/≤%.0f%%)%s" % (
name, changed * 100, TOLERANCE, FAIL_RATIO * 100, "OK" if changed <= FAIL_RATIO else "FAIL"))
if changed > FAIL_RATIO:
failures.append("%s: changed %.2f%% > %.0f%%(视觉回归——核对热区后重制或修复)" % (name, changed * 100, FAIL_RATIO * 100))
def main() -> int:
if len(sys.argv) < 3:
print("用法: python tools/golden_compare.py <黄金图目录> <新截图目录> [屏清单...]")
return 1
base, curr = Path(sys.argv[1]), Path(sys.argv[2])
shots = sys.argv[3:] or ["shot_menu.png", "shot_camp.png", "shot_level.png", "shot_battle.png"]
failures = []
for name in shots:
compare(base, curr, name, failures)
if failures:
print("[golden] FAIL——")
for f in failures:
print(" - %s" % f)
return 1
print("[golden] PASS(%d 屏黄金图对比全过)" % len(shots))
return 0
if __name__ == "__main__":
sys.exit(main())