COLMAP 数据解析
在这篇文章中,我们将重点解析 COLMAP 的输出数据,并用 Python 和 PyTorch 将它们转化为模型可以理解的张量(Tensors)。
数据集
我们首先下载 Mip-NeRF 360 数据集。当我们解压完数据集(例如经典的盆栽 bonsai 场景),会看到一个层级分明的目录结构。
图像数据 (Images)
首先是大量的图像文件。数据集中不仅包含接近 4K 的原始高分辨率图像,还贴心地提供了下采样(Downscaled)版本:缩小 2 倍 (images_2)、缩小 4 倍 (images_4)、缩小 8 倍 (images_8)。
COLMAP 输出文件
COLMAP 算法运行后,会输出三个核心的二进制(.bin)文件,它们是 3D 重建的灵魂:
- cameras.bin:记录相机的内参(焦距、中心点等)。
- images.bin:记录每张照片对应的相机外参(位置和姿态)。
- points3d.bin:稀疏的 3D 点云数据。
为了方便在 Python 中操作,我们会用脚本将这些 .bin 文件先转换为 .txt 文本格式,最后再打包成 NumPy 的 .npy 格式(如 cameras.npy、points3d.npy)。
代码实现
接下来,我们将进入代码环节。用 Python 读取这些 .npy 文件并为渲染做准备。
加载 3D 点云
点云文件(points3d.npy)中存储了场景中每一个离散点的信息。每一行代表一个点,包含 6 个关键值:前三个是空间坐标
- # 1. Load point cloud
- pc_path = "datasets/out_colmap/bonsai/point_cloud.npy"
- print(f"Loading point cloud from {pc_path}...")
- pc_data = np.load(pc_path) # shape: (N, 6)
- # Extract XYZ and RGB
- xyz = pc_data[:, :3] # shape: (N, 3)
- rgb = pc_data[:, 3:6] # shape: (N, 3)
- # Convert to PyTorch tensors
- PC = torch.from_numpy(xyz).float()
- PCColor = torch.from_numpy(rgb).float() / 255.0 # Normalize to [0, 1]
加载相机参数
这里的相机采用的是针孔相机模型 (Pinhole Camera Model)。对于光学中心点
- # 2. Load camera metadata
- meta_path = "datasets/out_colmap/bonsai/cam_meta.npy"
- print(f"Loading camera metadata from {meta_path}...")
- cam_meta = np.load(meta_path, allow_pickle=True).item()
- print("Camera metadata:", cam_meta)
- height = cam_meta['height']
- width = cam_meta['width']
- fx = cam_meta['fx']
- fy = cam_meta['fy']
- cx = width / 2
- cy = height / 2
如果我们现在将准备好的 xyz 和 rgb 喂给光栅化器去绘图,会发现图像上什么也没有。
此时屏幕毫无画面,并非点云数据丢失了,而是因为相机没有看向点云。目前我们仅仅加载了相机的内参(焦距、图像尺寸),但还没有配置相机的外参(位置和朝向)。我们将在下一篇文章中进行实现。