Spaces:
Sleeping
Sleeping
| """R1-3 — metric scale certification on an exact synthetic scene (CI-safe: | |
| no torch, analytic depth). | |
| Scene: pinhole camera (f = image width), height 1.5 m, pitch 25 deg, looking | |
| at an infinite ground plane. Depth is computed analytically, the homography is | |
| built exactly from four ground points with a known plane-unit scale, so the | |
| true metersPerUnit is known in closed form. | |
| Checks (real implementation extracted from app.py): | |
| 1. recovery: estimate_meters_per_unit returns the true scale within 2% | |
| 2. rejection: a sheared homography (the synthetic-VP failure mode) returns | |
| None instead of a confidently-wrong scale | |
| 3. relative depth (normalised [0,1]) returns None (metric-only feature) | |
| """ | |
| import cv2 | |
| import numpy as np | |
| # --- real implementation from app.py ---------------------------------------- | |
| src = open("app.py").read() | |
| ns = {"np": np, "cv2": cv2, "depth_model_is_metric": lambda name=None: True} | |
| start = src.index("def estimate_meters_per_unit") | |
| end = src.index("\n# ---", start) | |
| exec(compile(src[start:end], "app.py", "exec"), ns) | |
| estimate_meters_per_unit = ns["estimate_meters_per_unit"] | |
| W, H = 800, 600 | |
| F = float(W) | |
| CAM_H = 1.5 | |
| PITCH = np.deg2rad(25.0) | |
| UNITS_PER_M = 200.0 # plane-unit scale baked into the homography | |
| TRUE_MPU = 1.0 / UNITS_PER_M | |
| def scene(): | |
| cx, cy = W / 2.0, H / 2.0 | |
| u, v = np.meshgrid(np.arange(W, dtype=np.float64), np.arange(H, dtype=np.float64)) | |
| # ground plane: 1/Z = (sin(t) + cos(t) * (v - cy)/f) / h (v grows downward) | |
| inv_z = (np.sin(PITCH) + np.cos(PITCH) * (v - cy) / F) / CAM_H | |
| mask = inv_z > 1.0 / 30.0 # floor visible, within 30 m | |
| z = np.where(mask, 1.0 / np.maximum(inv_z, 1e-9), 0.0) | |
| # camera-frame 3D, then world ground coordinates. Camera pitched DOWN by | |
| # PITCH, world y up, image v down: world_y = -cos*y_c - sin*z (must be | |
| # exactly -CAM_H on the ground — asserted), forward = cos*z - sin*y_c. | |
| x_c = z * (u - cx) / F | |
| y_c = z * (v - cy) / F | |
| world_y = -np.cos(PITCH) * y_c - np.sin(PITCH) * z | |
| assert np.allclose(world_y[mask], -CAM_H, atol=1e-9), "sim geometry inconsistent" | |
| x_w = x_c | |
| fwd_w = np.cos(PITCH) * z - np.sin(PITCH) * y_c | |
| return mask.astype(np.uint8), z.astype(np.float32), x_w, fwd_w | |
| def exact_homography(mask, x_w, fwd_w): | |
| ys, xs = np.nonzero(mask) | |
| # four well-spread ground points | |
| picks = [] | |
| for fy, fx in [(0.95, 0.2), (0.95, 0.8), (0.55, 0.3), (0.55, 0.7)]: | |
| yy = int(np.percentile(ys, fy * 100)) | |
| row = xs[ys == yy] | |
| xx = int(np.percentile(row, fx * 100)) | |
| picks.append((xx, yy)) | |
| src_pts = np.float32(picks) | |
| dst_pts = np.float32( | |
| [[x_w[y, x] * UNITS_PER_M, fwd_w[y, x] * UNITS_PER_M] for x, y in picks] | |
| ) | |
| return cv2.getPerspectiveTransform(src_pts, dst_pts) | |
| def main(): | |
| ok = True | |
| mask, z, x_w, fwd_w = scene() | |
| Hm = exact_homography(mask, x_w, fwd_w) | |
| mpu = estimate_meters_per_unit(z, mask, Hm.flatten().tolist(), W, H) | |
| if mpu is None: | |
| print(" [FAIL] recovery: returned None on exact scene") | |
| ok = False | |
| else: | |
| err = abs(mpu - TRUE_MPU) / TRUE_MPU | |
| good = err <= 0.02 | |
| print(f" [{'PASS' if good else 'FAIL'}] recovery: mpu={mpu:.6f} " | |
| f"(true {TRUE_MPU:.6f}, err {err * 100:.2f}%)") | |
| ok &= good | |
| # synthetic-VP failure mode: progressive horizontal shear of plane coords | |
| S = np.array([[1.0, 0.35, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]) | |
| H_bad = S @ Hm | |
| mpu_bad = estimate_meters_per_unit(z, mask, H_bad.flatten().tolist(), W, H) | |
| print(f" [{'PASS' if mpu_bad is None else 'FAIL'}] rejection: sheared homography -> {mpu_bad}") | |
| ok &= mpu_bad is None | |
| rel = (z - z[mask > 0].min()) / (z[mask > 0].max() - z[mask > 0].min()) | |
| ns["depth_model_is_metric"] = lambda name=None: False | |
| mpu_rel = estimate_meters_per_unit(rel.astype(np.float32), mask, Hm.flatten().tolist(), W, H) | |
| print(f" [{'PASS' if mpu_rel is None else 'FAIL'}] relative depth -> {mpu_rel}") | |
| ok &= mpu_rel is None | |
| print("\n" + ("ALL R1-3 SIM CHECKS PASSED" if ok else "R1-3 SIM CHECKS FAILED")) | |
| return 0 if ok else 1 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |