File size: 3,425 Bytes
c75b162
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
"""Generate sparse depth supervision PNGs from a COLMAP sparse model, by
projecting each image's observed 3D points (points3D.txt, via the 2D-3D
correspondences already stored in images.txt) onto its own pixel grid using
that image's COLMAP pose. Output format matches what BAGS/TriSplat's
load_gt_depth_cache expects: <source_path>/depth/<image_name>.png, uint16,
depth_units * 1000 (same convention as ScanNet sensor depth -> meters via
/1000, but here "units" = whatever scale the COLMAP reconstruction itself
is in, which is the SAME scale the renderer's surf_depth/depth will be in
since it's trained on these same poses)."""
import os, sys, numpy as np, cv2

REPO_TRI = "/srv2/szha0669/blur_slam_exp/repos/triangle-splatting"
sys.path.insert(0, REPO_TRI)
from scene.colmap_loader import read_extrinsics_text, qvec2rotmat

SPARSE = "/home/szha0669/storage/blur_slam_exp/data/i2slam_trigsplat/tum_fr2_xyz_abl1/sparse/0"
OUT_DIR = "/home/szha0669/storage/blur_slam_exp/data/i2slam_trigsplat/tum_fr2_xyz_abl1/depth"
W, H = 640, 480
MAX_DEPTH = 65.0  # uint16/1000 storage cap; drop (not clamp) farther points as
                  # likely-noisy long-tail COLMAP triangulations (p95~64.5, p99~140)


def read_points3D_xyz(path):
    pts = {}
    with open(path) as f:
        for line in f:
            line = line.strip()
            if not line or line.startswith("#"):
                continue
            elems = line.split()
            pid = int(elems[0])
            pts[pid] = np.array(list(map(float, elems[1:4])))
    return pts


def main():
    os.makedirs(OUT_DIR, exist_ok=True)
    images = read_extrinsics_text(os.path.join(SPARSE, "images.txt"))
    points3D = read_points3D_xyz(os.path.join(SPARSE, "points3D.txt"))

    all_depths = []
    n_pts_per_img = []
    n_dropped = 0
    n_total = 0
    for img in images.values():
        R = qvec2rotmat(img.qvec)
        t = img.tvec
        depth_map = np.zeros((H, W), dtype=np.float32)
        n = 0
        for (x, y), pid in zip(img.xys, img.point3D_ids):
            if pid == -1 or pid not in points3D:
                continue
            xyz_cam = R @ points3D[pid] + t
            d = xyz_cam[2]
            if d <= 0:
                continue
            n_total += 1
            if d > MAX_DEPTH:
                n_dropped += 1
                continue
            px, py = int(round(x)), int(round(y))
            if 0 <= px < W and 0 <= py < H:
                if depth_map[py, px] == 0 or d < depth_map[py, px]:
                    depth_map[py, px] = d
                n += 1
                all_depths.append(d)
        n_pts_per_img.append(n)

        raw = np.clip(depth_map * 1000.0, 0, 65535).astype(np.uint16)
        out_path = os.path.join(OUT_DIR, img.name)  # name already e.g. "000000.png"
        cv2.imwrite(out_path, raw)

    all_depths = np.array(all_depths)
    print(f"images: {len(images)}, depth maps written to {OUT_DIR}")
    print(f"points/image: min={min(n_pts_per_img)} max={max(n_pts_per_img)} "
          f"mean={np.mean(n_pts_per_img):.1f}")
    print(f"depth value range: min={all_depths.min():.4f} max={all_depths.max():.4f} "
          f"mean={all_depths.mean():.4f}  (units = COLMAP pose-scale, same as "
          f"renderer's surf_depth/depth output)")
    print(f"dropped (depth > {MAX_DEPTH}): {n_dropped}/{n_total} "
          f"({100 * n_dropped / n_total:.2f}%)")


if __name__ == "__main__":
    main()