32 gauge.py
✅ 已验证 · 代码 code/gauge.py · ./paint trace 结束时自动打印
它回答什么
「这张成品像不像人画的」。标尺从真人画作上量出来(work/example ref/ 的两张 2508px 插画),门槛以源图为锚。
用法
python3 code/gauge.py <成品.png> # 用默认参考画算标尺
python3 code/gauge.py <成品.png> ref1.jpg ref2.jpg
python3 code/gauge.py --ref work/example\ ref/*.jpg # 只打标尺
ART_SRC=xxx.png python3 code/gauge.py <成品.png> # 换源图锚点
输出:
== 成品 final.png (量之前归一到 2508px 宽) ==
源图 41.6 色数 2900 阶梯 6.19 <- 源图锚点
梯度 p99 36.9 OK 源图的 89% (门槛 85%)
8级量化色数 1840 OK 源图的 63% (门槛 55%)
8px 阶梯能量 0.78 OK 要低于源图 6.19 (放大过就会高)
── 参考画区间(仅供参照, 不是门槛): p99 59.4–74.6 色数 2504–2557 阶梯 0.97–1.03
低频 likeness 33.57 dB
全图最暗像素 (0, 0, 0)
作画日志 落笔 80669 笔 · 写像素 2 次 OK
三个画面指标
在 1:1 特写(800×600)上量:
| 指标 | 量法 | 抓什么 |
|---|---|---|
| 梯度 p99 | 亮度梯度模的 99 分位 | 边利不利 |
| 8 级量化色数 | RGB 各除 8 取整后的唯一色数 | 层次是明确的几档还是连续糊 |
| 8px 阶梯能量 | 抽行做二阶差分,FFT 后 8px 周期附近的能量 ÷ 中位 | 1x 像素格放大 8 倍留下的指纹 |
三条设计决定
归一到 2508px 再量。 梯度 p99 随分辨率变(同一张 8K 成品 @8192 → 33.2,@2508 → 42.2,@1024 → 56.2)。load() 读进来先 resize 到 NORM_W=2508。
门槛以源图为锚。 参考画 p99 59.4–74.6,源图自己 41.6。门槛写成源图的百分比(p99 ≥ 85%,色数 ≥ 55%,阶梯 < 源图)。参考画区间只打印。
特写窗口自动选。 pick_crops() 按高频能量取 3 块互不重叠的 800×600,跳过能量低于最高的 5% 的空白块。中位数作为该指标的值。
一个 bug
pick_crops() 的不重叠判断曾经写成 and:「y 差够远 且 x 差够远」才算不重叠,于是正右方那块也被当成重叠排除,候选被砍到只剩边角,最后捡到纯黑背景块(均亮 11.4 / p99 0.8),判据读出 14.5 而实际画面是 43.5。改成 or + 空白块过滤后才对。
其它两项
- 低频 likeness:两边降到 256 宽再算 PSNR。临摹只该在这个尺度上像。
- 作画日志:读同目录
strokes.jsonl,数落笔与写像素(第 25 章)。
换参考画
换一套 --ref 重跑就是新标尺,不用手改判据。参考画应该是满构图的(本书的两张是)——有大片空白背景的参考画会让 pick_crops 的自动取景失去意义。