arissassina's picture
download
raw
4.15 kB
import csv
import glob
import json
import cv2
import numpy as np
ROOT = "/root/bdmc_pipeline"
H, W = 1920, 1080
fx = fy = H / (2 * np.tan(np.radians(72.0 / 2)))
K = np.array([[fx, 0, W / 2], [0, fy, H / 2], [0, 0, 1.0]])
RADIUS_PX = 110
devmaps = np.load(f"{ROOT}/outputs/devmaps_small.npz")["dev"].astype(np.float32)
devmaps_m = (devmaps - 128.0) / 1000.0
defects = list(csv.DictReader(open(f"{ROOT}/outputs/defects.csv")))
wins = {}
for p in sorted(glob.glob(f"{ROOT}/outputs/tracks/win_*.npz")):
z = np.load(p)
wins[int(z["start"])] = {"tracks": z["tracks"], "vis": z["vis"].reshape(z["vis"].shape[0], -1)}
tri_meta = {}
for p in sorted(glob.glob(f"{ROOT}/outputs/tracks/triangulated_*.npz")):
z = np.load(p)
tri_meta[int(z["start"])] = {"xyz": z["xyz"], "Rs": z["Rs"], "ts": z["ts"],
"rmse_med": float(np.median(z["rmse"]))}
def track_support(fst, dur, cxc, cyc):
dvs = []
for s, w in wins.items():
lo, hi = max(fst, s), min(fst + dur - 1, s + w["tracks"].shape[0] - 1)
for f in range(lo, hi + 1):
tr = w["tracks"][f - s]
v = w["vis"][f - s].astype(bool)
xi = np.clip(tr[:, 0].round().astype(int), 0, W - 1)
yi = np.clip(tr[:, 1].round().astype(int), 0, H - 1)
dist = np.hypot(xi - cxc, yi - cyc)
near = v & (dist < RADIUS_PX)
if near.sum() == 0:
continue
dvs.append(devmaps_m[f - 1][yi[near] // 4, xi[near] // 4])
if not dvs:
return None
dv = np.concatenate(dvs)
return {"n_obs": int(len(dv)),
"support_frac_lt3cm": round(float((dv < -0.03).mean()), 3),
"median_dev_cm": round(float(np.median(dv)) * 100, 2),
"p25_dev_cm": round(float(np.percentile(dv, 25)) * 100, 2)}
rows_out = []
for r in defects:
c = str(r["centroid_px"]).replace("[", "").replace("]", "").replace(",", " ").split()
cxc, cyc = float(c[0]), float(c[1])
fst, dur = int(r["first_frame"]), int(r["duration_frames"])
rec = dict(r)
ts = track_support(fst, dur, cxc, cyc)
if ts is None or ts["n_obs"] < 5:
rec.update({"track_n_obs": ts["n_obs"] if ts else 0, "track_median_dev_cm": None,
"track_support_frac": None, "confidence": "no_coverage"})
else:
med, sf = ts["median_dev_cm"], ts["support_frac_lt3cm"]
conf = ("agree" if (med <= -3.0 and sf >= 0.4)
else "partial" if med <= -1.5 else "disagree")
rec.update({**ts, "track_support_frac": sf, "track_median_dev_cm": med,
"confidence": conf})
rows_out.append(rec)
cols = ["first_frame", "t_sec", "duration_frames", "duration_s", "peak_dev_cm", "area_px",
"centroid_px", "n_obs", "median_dev_cm", "p25_dev_cm", "support_frac_lt3cm",
"confidence"]
with open(f"{ROOT}/outputs/defects_fused.csv", "w", newline="") as fh:
wr = csv.DictWriter(fh, fieldnames=cols)
wr.writeheader()
wr.writerows([{k: r.get(k) for k in cols} for r in rows_out])
tri_files = glob.glob(f"{ROOT}/outputs/tracks/triangulated_*.npz")
if tri_files:
med_rmse = float(np.median(np.concatenate([np.load(p)["rmse"] for p in tri_files])))
else:
med_rmse = 0.0
report = {
"n_defects": len(rows_out),
"confidence_counts": {c: sum(1 for r in rows_out if r.get("confidence") == c)
for c in ["agree", "partial", "disagree", "no_coverage"]},
"method": "per-defect: gather all CoTracker3 observations passing through defect region during its confirmed lifetime; compare their depth-residual samples against the flag",
"median_triangulated_rmse_px": round(med_rmse, 2),
"sigma_proxy_triangulated_cm_at_5m": round(float(med_rmse * 5.0 / fx * 100), 2),
"depth_tile_sigma_cm": json.load(open(f"{ROOT}/outputs/phase3_summary.json"))["tile_sigma_median_cm"],
"note": "no GPS/IMU: egomotion estimated visually (Kabsch on depth-anchored correspondences)",
}
json.dump(report, open(f"{ROOT}/outputs/phase6_report.json", "w"), indent=1)
print(json.dumps(report, indent=1))
print("Phase 6 fusion complete", flush=True)

Xet Storage Details

Size:
4.15 kB
·
Xet hash:
aa5b0fbc5be06b449e33f315c3cf04a330f59d8f3bc350ab80da6703323bda10

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.