summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-29 06:12:57 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-29 06:12:57 +0800
commitec49a835361fd0f6d92a41204dcc9547073b46ee (patch)
treee487c692e327484bfc813db2f65cb6a43a13b4cc /scripts
parent166fbeb4efd1c36c5c8289defdf480c89835d540 (diff)
downloadliving-village-ec49a835361fd0f6d92a41204dcc9547073b46ee.tar.gz
p64: 整改桥梁栏杆可辨(深墨栏体/亮扶手/望柱)与内景四角布局(Hermes vision 复核)
Diffstat (limited to 'scripts')
-rw-r--r--scripts/analyze-p64.py40
-rw-r--r--scripts/make-jiangnan-art.py31
2 files changed, 56 insertions, 15 deletions
diff --git a/scripts/analyze-p64.py b/scripts/analyze-p64.py
index f1b0e0c..243d7dd 100644
--- a/scripts/analyze-p64.py
+++ b/scripts/analyze-p64.py
@@ -10,8 +10,13 @@
(P62 同带基线 0.103;HUD 顶部条带 y<120 不计,避免把 UI 当内容)。
3. 桥近景:桥所在区域 (x 560..720, y 360..500) 的「木色像素」占比 >= 0.20,
证明桥面/栏杆木色进入实拍帧。
- 4. 三帧均 1280x720、非空、无 64x64 纯白块、无 24x24 纯黑块,且两两不同。
- 5. 缺字空白位:中文经 CjkGlyphAtlas 绘制,P61 已证覆盖(P61GlyphCoverageTests 绿)。
+ 4. 栏杆可辨(整改新增):以日志相机定位桥格(世界 tile x31,y29..31),取两侧栏杆条带
+ (相对桥格 x 偏移 1..6 与 26..31,纵向 3 格)。栏杆像素口径 = 亮色 (r>150,g>130,b>100)
+ 或深色 (r<80,g<80,b<80)——纯桥面木色 (≈119,77,47) 两类都不满足,故该指标直接区分
+ 「有栏杆」与「只有桥面木板」。要求左右两条带各自 rail_ratio >= 0.70。
+ 在俯瞰帧(1x 全帧)与桥近景帧上都成立。
+ 5. 三帧均 1280x720、非空、无 64x64 纯白块、无 24x24 纯黑块,且两两不同。
+ 6. 缺字空白位:中文经 CjkGlyphAtlas 绘制,P61 已证覆盖(P61GlyphCoverageTests 绿)。
Usage: python3 scripts/analyze-p64.py <record-dir> <out-txt>
Exit 0 pass / 1 fail / 2 usage.
@@ -73,6 +78,26 @@ def non_background_ratio(img, y0, y1):
return 1.0 - float(counts.max()) / float(counts.sum())
+BRIDGE_TILE_X = 31
+BRIDGE_TILE_Y0 = 29
+BRIDGE_TILE_H = 3
+RAIL_THRESHOLD = 0.70
+
+
+def rail_strip_ratios(img, camx, camy):
+ """Return (left_ratio, right_ratio) of rail-colored pixels in the two rail strips."""
+ bx = BRIDGE_TILE_X * 32 - camx
+ y0 = BRIDGE_TILE_Y0 * 32 - camy
+ y1 = y0 + BRIDGE_TILE_H * 32
+ results = []
+ for sx0 in (bx + 1, bx + 26):
+ reg = img[y0:y1, sx0 : sx0 + 5].astype(np.int16)
+ r, g, b = reg[:, :, 0], reg[:, :, 1], reg[:, :, 2]
+ rail = ((r > 150) & (g > 130) & (b > 100)) | ((r < 80) & (g < 80) & (b < 80))
+ results.append(float(rail.mean()) if rail.size else 0.0)
+ return results[0], results[1]
+
+
def main():
if len(sys.argv) != 3:
print(__doc__)
@@ -151,6 +176,17 @@ def main():
lines.append(f"bridge region wood-pixel ratio (x {x0}..{x1}, y {y0}..{y1}) = {wood}/{total} = {wood/total:.4f}")
if wood / total < 0.20:
failures.append(f"bridge wood ratio {wood/total:.4f} < 0.20")
+ for name in ("p64-overview", "p64-bridge"):
+ if name not in stats or name not in shots:
+ continue
+ camx = int(float(shots[name].group(5)))
+ camy = int(float(shots[name].group(6)))
+ left, right = rail_strip_ratios(stats[name], camx, camy)
+ lines.append(f"rail strips [{name}] cam=({camx},{camy}) left={left:.3f} right={right:.3f} (threshold {RAIL_THRESHOLD})")
+ if left < RAIL_THRESHOLD:
+ failures.append(f"{name} left rail ratio {left:.3f} < {RAIL_THRESHOLD}")
+ if right < RAIL_THRESHOLD:
+ failures.append(f"{name} right rail ratio {right:.3f} < {RAIL_THRESHOLD}")
lines.append("")
for name, shot in sorted(shots.items()):
diff --git a/scripts/make-jiangnan-art.py b/scripts/make-jiangnan-art.py
index c28244f..caf0c01 100644
--- a/scripts/make-jiangnan-art.py
+++ b/scripts/make-jiangnan-art.py
@@ -192,24 +192,29 @@ def build_world_atlas():
# P64 桥:在既有栈板桥面上补可读的两侧栏杆与望柱(桥沿纵向铺 3 格,栏杆随格连续),
# 并保留桥面横铺板纹。低饱和木色,仍为 slot 5 单格、尺寸不变,不改位置/通行。
+ # P64 桥(整改):栏杆须在 1x 俯瞰下与桥面木色差 >= 2 档,故改用「深墨栏杆体 + 暖亮扶手线 +
+ # 亮色望柱」三段对比:桥面 (119,76,47) 为中间调,栏杆体远暗、扶手/望柱远亮。仍为 slot5 单格。
x0 = slot(5)
c.rect(x0, 0, 32, 32, wood)
+ # 桥面栈板(保留中间调木色)
for y in (0, 8, 16, 24):
- c.rect(x0 + 5, y, 22, 1, wood_light)
+ c.rect(x0 + 6, y, 20, 1, wood_light)
for y in (7, 15, 23, 31):
- c.rect(x0 + 5, y, 22, 1, wood_dark)
- bridge_rail = (132, 84, 52, 255)
- bridge_rail_light = (176, 122, 71, 255)
- bridge_rail_dark = (83, 52, 39, 255)
+ c.rect(x0 + 6, y, 20, 1, wood_dark)
+ bridge_rail_ink = (34, 28, 30, 255)
+ bridge_rail_light = (214, 196, 158, 255)
bridge_kerb = (150, 146, 138, 255)
- for bx in (1, 27):
- c.rect(x0 + bx, 0, 4, 32, bridge_rail)
- c.rect(x0 + bx, 0, 1, 32, bridge_rail_light)
- c.rect(x0 + bx + 3, 0, 1, 32, bridge_rail_dark)
- for by in (2, 10, 18, 26):
- c.rect(x0 + 1, by, 5, 3, bridge_rail_dark)
- c.rect(x0 + 27, by, 5, 3, bridge_rail_dark)
- for bx in (5, 26):
+ for bx in (1, 26):
+ # 通长栏杆体(深墨,宽 5px)
+ c.rect(x0 + bx, 0, 5, 32, bridge_rail_ink)
+ # 扶手亮线(沿栏杆全长,与桥面亮 2 档以上)
+ c.rect(x0 + bx + 1, 0, 1, 32, bridge_rail_light)
+ # 望柱:每格两根,暖亮柱头压住深墨栏体
+ for by in (1, 17):
+ c.rect(x0 + bx, by, 5, 5, bridge_rail_light)
+ c.rect(x0 + bx, by + 5, 5, 1, bridge_rail_ink)
+ # 桥面与栏杆交界的石缘
+ for bx in (6, 25):
c.rect(x0 + bx, 0, 1, 32, bridge_kerb)
x0 = slot(6)