blur-slam-bpn-code / scripts /build_tum_points3d.py
zhaoshiwen's picture
Initial upload: BPN deblur pipeline code (scripts, triangle-splatting, BAGS, EVSSM forks)
c75b162 verified
Raw
History Blame Contribute Delete
3.06 kB
#!/usr/bin/env python3
"""Generate points3D.txt from TUM depth frames using scipy for pose conversion."""
import os, numpy as np
from PIL import Image
from pathlib import Path
from scipy.spatial.transform import Rotation
BASE = "/home/szha0669/storage/blur_slam_exp"
TUM_DIR = f"{BASE}/data/TUM_RGBD/rgbd_dataset_freiburg1_desk"
OUT = f"{BASE}/data/tum_fr1desk/scene/sparse/0/points3D.txt"
FX, FY, CX, CY = 517.3, 516.5, 318.6, 255.3
DEPTH_SCALE = 5000.0
def read_timestamps(path):
data = {}
with open(path) as f:
for line in f:
if line.startswith('#'): continue
parts = line.strip().split()
if len(parts) >= 2:
try:
data[float(parts[0])] = parts[1:]
except ValueError:
pass
return data
def nearest_ts(query, ts_sorted, max_dt=0.05):
idx = np.searchsorted(ts_sorted, query)
best = None
for i in [idx-1, idx]:
if 0 <= i < len(ts_sorted):
dt = abs(ts_sorted[i] - query)
if dt < max_dt and (best is None or dt < best[0]):
best = (dt, ts_sorted[i])
return best[1] if best else None
rgb_data = read_timestamps(f"{TUM_DIR}/rgb.txt")
depth_data = read_timestamps(f"{TUM_DIR}/depth.txt")
gt_data = read_timestamps(f"{TUM_DIR}/groundtruth.txt")
depth_ts = sorted(depth_data.keys())
gt_ts = sorted(gt_data.keys())
rgb_ts = sorted(rgb_data.keys())
# Sample every 30th frame
sampled = rgb_ts[::30]
print(f"Sampling {len(sampled)} frames")
all_pts, all_colors = [], []
for rgb_t in sampled:
d_t = nearest_ts(rgb_t, depth_ts)
g_t = nearest_ts(rgb_t, gt_ts)
if d_t is None or g_t is None: continue
tx, ty, tz, qx, qy, qz, qw = map(float, gt_data[g_t])
R_c2w = Rotation.from_quat([qx, qy, qz, qw]).as_matrix()
t_c2w = np.array([tx, ty, tz])
depth_path = f"{TUM_DIR}/{depth_data[d_t][0]}"
rgb_path = f"{TUM_DIR}/{rgb_data[rgb_t][0]}"
depth_img = np.array(Image.open(depth_path)).astype(np.float32) / DEPTH_SCALE
rgb_img = np.array(Image.open(rgb_path))
H_d, W_d = depth_img.shape
ys, xs = np.meshgrid(np.arange(0, H_d, 8), np.arange(0, W_d, 8), indexing='ij')
ys, xs = ys.ravel(), xs.ravel()
zs = depth_img[ys, xs]
valid = (zs > 0.2) & (zs < 4.0)
ys, xs, zs = ys[valid], xs[valid], zs[valid]
xc = (xs - CX) / FX * zs
yc = (ys - CY) / FY * zs
pts_cam = np.stack([xc, yc, zs], axis=1)
pts_world = (R_c2w @ pts_cam.T).T + t_c2w
colors = rgb_img[ys, xs]
all_pts.append(pts_world)
all_colors.append(colors)
all_pts = np.concatenate(all_pts, axis=0)
all_colors = np.concatenate(all_colors, axis=0)
print(f"Total: {len(all_pts)} points")
with open(OUT, 'w') as f:
f.write("# 3D point list: POINT3D_ID X Y Z R G B ERROR TRACK[]\n")
for i, (pt, col) in enumerate(zip(all_pts, all_colors)):
f.write(f"{i+1} {pt[0]:.6f} {pt[1]:.6f} {pt[2]:.6f} "
f"{int(col[0])} {int(col[1])} {int(col[2])} 0.5\n")
print(f"Written: {OUT}")