"""Background plate: the same cameras, the same lighting, no object. In simulation this gives an EXACT object mask by image difference, which beats every height-threshold heuristic - and the height threshold is precisely what failed: CREStereo puts the belt a few mm above belt_z, so a z-crop returns a belt patch whose footprint is the crop window (measured 1700x1550x64 mm for every item, i.e. the crop, not the object). """ import json, os, sys REPO = "/home/dasha/robozon-sorter" for e in (REPO, f"{REPO}/control_test"): if e not in sys.path: sys.path.insert(0, e) for _m in [k for k in list(sys.modules) if k.startswith("cam_configs")]: del sys.modules[_m] import importlib; importlib.invalidate_caches() import asyncio import omni.usd, omni.timeline import omni.kit.viewport.utility as vp import isaacsim.core.experimental.utils.app as app_utils from pxr import UsdGeom import cam_configs as CC CFG = globals().get("cfg", CC.DEFAULT) OUT = f"{REPO}/control_test/captures/{CFG}" os.makedirs(OUT, exist_ok=True) stage = omni.usd.get_context().get_stage() tl = omni.timeline.get_timeline_interface() if tl.is_playing(): tl.stop(); await app_utils.update_app_async(steps=10) calib = CC.apply_config(stage, CFG) root = stage.GetPrimAtPath("/World/CapItems") if root.IsValid(): for c in root.GetChildren(): UsdGeom.Imageable(c).MakeInvisible() await app_utils.update_app_async(steps=25) w = vp.get_active_viewport() orig = w.camera_path bg = {} for cam_name in calib: w.camera_path = CC._cam(stage, cam_name).GetPath() await app_utils.update_app_async(steps=22) await asyncio.sleep(0) f = f"{OUT}/__background__{cam_name}.png" vp.capture_viewport_to_file(w, file_path=f) await app_utils.update_app_async(steps=12) await asyncio.sleep(0) bg[cam_name] = f w.camera_path = orig await app_utils.update_app_async(steps=10) man_path = f"{OUT}/manifest.json" man = json.load(open(man_path)) man["background"] = bg json.dump(man, open(man_path, "w"), indent=1) print(f"background plate: {len(bg)} views -> {man_path}")