File size: 3,257 Bytes
cca6827
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/usr/bin/env python3
"""Unit test: eval_final.masked_view == eval_heldout.heldout_view (the path that produced
the held-out NV numbers / viz_pairs artifact) on FB150 + Omni views, and the far-clip
fix only changes renders of cameras farther than 10 units.
Usage: python test_equiv_heldout.py MESH_DIR_FB150 [OBJ ...]   (server-local paths)"""
import sys, json
from pathlib import Path
import numpy as np

HERE = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(HERE))
import eval_final as EF                                   # noqa: E402  (package, far-fixed renderer)
sys.path.insert(0, str(HERE / "heldout"))
import eval_heldout as EH                                 # noqa: E402  (original module)
import importlib.util                                     # noqa: E402
# 'render' is already bound to the package (far-fixed) module -> load the ORIGINAL renderer explicitly
_spec = importlib.util.spec_from_file_location("render_orig", "/home/nvidia/jonghoon/mv-mesh/metrics/appeval/render.py")
R_ORIG = importlib.util.module_from_spec(_spec); _spec.loader.exec_module(R_ORIG)
assert R_ORIG.render_input_view.__defaults__[1] == 20.0 and EF.R.render_input_view.__defaults__[1] is None
EH.R = R_ORIG                                             # heldout_view now uses the original far=20 renderer

mesh_dir = Path(sys.argv[1]); objs = sys.argv[2:]
ctx = EF.R.get_ctx()
rep = []
for ds in ("fb150", "omni300"):
    idx = json.load(open(EH.DS[ds]["index"]))
    for obj in (objs if ds == "fb150" else ["asparagus_001", "bowl_001"]):
        mp = mesh_dir / f"{obj}.glb" if ds == "fb150" else EH.DS[ds]["exp"] / "renders" / f"{obj}_canon.glb"
        mesh = EF.EA.load_mesh(mp)
        g_new, g_old = EF.R.prepare_mesh(mesh), EH.R.prepare_mesh(mesh)
        for rec in idx[obj][:3] + [dict(tag="front", cam=-1, root=str(EH.DS[ds]["exp"]))]:
            m_old, p_old, r_old = EH.heldout_view(g_old, rec, obj, ctx)
            m_new, p_new, r_new = EF.masked_view(g_new, Path(rec["root"]), obj, rec["tag"], ctx)
            d = max(abs(m_old[k] - m_new[k]) for k in EF.MKEYS)
            rep.append(dict(ds=ds, obj=obj, tag=rec["tag"], cam_dist=round(m_new["cam_dist"], 2),
                            max_metric_diff=d, pix_equal=bool(np.array_equal(p_old, p_new, equal_nan=True)),
                            max_pix_diff=float(np.nanmax(np.abs(p_old - p_new))),
                            lpips_old=m_old["lpips"], lpips_new=m_new["lpips"]))
            print(rep[-1], flush=True)
near = [r for r in rep if r["cam_dist"] < 10]
# pass: identical metrics (<=1e-6; rasteriser/texture sampling is not bit-deterministic across two
# MeshGL instances of large UV-textured meshes, max pixel diff is reported)
ok = all(r["max_metric_diff"] <= 1e-6 for r in near)
print(f"EQUIV (cams < 10 units: {len(near)} views, bit-identical renders {sum(r['pix_equal'] for r in near)}, "
      f"max metric diff {max(r['max_metric_diff'] for r in near):.2e}, max pix diff {max(r['max_pix_diff'] for r in near):.2e}): "
      f"{'PASS' if ok else 'FAIL'}")
far = [r for r in rep if r["cam_dist"] >= 10]
print(f"far cams (>=10 units, far-clip fix may change render): {len(far)} views, "
      f"changed {sum(not r['pix_equal'] for r in far)}")
sys.exit(0 if ok else 1)