# 多视角三维重建项目素材 (MVS / NeRF / 3D Gaussian Splatting)

本目录是用本机 Blender 4.5 (Cycles + OptiX GPU) 生成的**合成多视角重建数据集**，可作为课程项目「引入 MVS / NeRF / 3D 高斯方法，重建场景的密集点云表示」的标准输入与真值(ground truth)。

- 场景：一张带棋盘格桌面的静物（砖块立方体、噪声球、棋盘圆柱、波浪圆锥、噪声环面、石纹猴子、沃罗诺伊二十面体等），全部使用程序化纹理，保证表面有足够的特征纹理供特征匹配与外观建模。
- 相机：72 个环绕视角（3 个仰角环 × 每环 24 个方位角），完整覆盖场景，适合 NeRF / 3DGS 训练与 MVS 密集重建。

---

## 1. 目录结构

```
mvs_project/
├── generate_dataset.py        # 数据生成脚本(可用 Blender 重新运行/改参数)
├── README.md                  # 本说明
├── metadata.json              # 数据集参数汇总
├── scene.blend                # 场景源文件(Blender 打开可复现/改场景)
├── images/                    # 72 张多视角 RGB 图 frame_0000.png ... frame_0071.png
├── poses/
│   └── transforms.json        # 相机内参+外参 (OpenCV/COLMAP 约定)
├── sparse/                    # COLMAP 文本格式(可直接喂给 MVS/3DGS 工具)
│   ├── cameras.txt            # PINHOLE 内参
│   ├── images.txt             # 每帧位姿(四元数+平移)
│   └── points3D.txt           # 稀疏点占位(空, 真值见 gt/)
└── gt/
    ├── dense_pointcloud.ply   # 真值稠密点云(30万点, 含法线与颜色)
    └── mesh.ply               # 真值三角网格(世界坐标, 顶点索引)
```

---

## 2. 数据说明

| 项目 | 值 |
|---|---|
| 图像分辨率 | 800 × 800 (方形像素) |
| 视角数 | 72 (3 环 × 24 方位) |
| 焦距 | fx = fy = 888.889 px，cx = cy = 400 px |
| 水平/垂直视场角 | 约 48.46° (0.8457 rad)，方形图像下两者相等 |
| 镜头/传感器 | 40mm，sensor_fit = HORIZONTAL |
| 环绕半径 / 目标点 | 6.2 米，(0, 0, 0.55) |
| 真值点云 | 300,000 点 (x,y,z,nx,ny,nz,r,g,b) |

### 坐标约定（重要）

本数据集统一采用 **OpenCV / COLMAP 约定**：

- 相机坐标系：**x 向右，y 向下，z 向前（指向场景）**。
- 像素坐标系：原点在左上角，(u,v) = (fx·X/Z + cx, fy·Y/Z + cy)。
- 世界坐标系：Blender 世界（z 向上）。
- `transforms.json` 中每帧的 `transform_matrix` 是 **camera-to-world (c2w)** 的 4×4 矩阵。
- `sparse/images.txt` 中存的是 **world-to-camera** 旋转（四元数 qw,qx,qy,qz）+ 平移 t，即 `X_cam = R·X_world + t`，相机光心 `C = -Rᵀ·t`。

> 脚本内置了「重投影自检」：用 Blender 自身的 `world_to_camera_view` 逐点对照，本数据集最大重投影误差 ≈ 0.001 px，位姿与内参数学上自洽。

---

## 3. 三种方法怎么用

### 3.1 MVS（多视角立体视觉，COLMAP 流程）

MVS 的核心就是「先用 SFM 估计位姿、再密集重建」，`images/` 即输入：

```bash
# 安装 COLMAP 后:
colmap feature_extractor  --database_path db.db --image_path images
colmap exhaustive_matcher --database_path db.db
colmap mapper --database_path db.db --image_path images --output_path sparse0
# 可选: 用本目录提供的 sparse/ 作为位姿参考/校验
colmap image_undistorter --image_path images --input_path sparse0 --output_path dense --output_type COLMAP
colmap patch_match_stereo --workspace_path dense --workspace_format COLMAP
colmap stereo_fusion --workspace_path dense --workspace_format COLMAP --output_path dense/fused.ply
```

最终把 `fused.ply` 与 `gt/dense_pointcloud.ply` 对比（CloudCompare / 自行算 Chamfer 距离、精度/召回）。

### 3.2 NeRF（nerfstudio / instant-ngp / 原版 NeRF）

`poses/transforms.json` 可直接喂给 **nerfstudio**（Blender 数据解析器）或 **instant-ngp**：

```bash
# nerfstudio
ns-train nerfacto --data mvs_project

# instant-ngp (需把 transforms.json 放在 images 同级目录)
python scripts/run.py --scene mvs_project
```

> ⚠️ **原版 2020 NeRF 代码（bmild/nerf、google-research/nerf）使用的是 OpenGL 约定（x 右、y 上、z 后）。** 若你用这些旧代码，读入 c2w 后做一次翻转即可：
>
> ```python
> c2w[:, 1:3] *= -1   # 对旋转部分的 y、z 列以及平移的 y、z 分量整体取反
> ```

nerfstudio / instant-ngp 默认走 OpenCV 约定，无需额外转换。

### 3.3 3D Gaussian Splatting

3DGS 原生走 COLMAP/OpenCV 约定，直接读 `sparse/`（或运行 COLMAP 得到更完整的稀疏点初始化）：

```bash
# gaussian-splatting 仓库内
python convert.py -s mvs_project          # 读 images/ 生成相机与初始点
python train.py -s mvs_project -m output/xxx
python render.py -m output/xxx
```

也可以用 `poses/transforms.json`（OpenCV c2w + fl_x/fl_y/cx/cy）自行构造 3DGS 的 `Cameras` 数据结构。

---

## 4. 重新生成 / 自定义场景

```bash
# 完整 72 视角, 800px, 128 采样, 30万点
blender.exe --background --factory-startup --python generate_dataset.py -- --outdir <输出目录>

# 快速冒烟测试(3 视角, 400px, 5000点)
blender.exe --background --factory-startup --python generate_dataset.py -- --smoke --outdir <输出目录>

# 自定义参数
blender.exe ... -- --res 1024 --samples 256 --rings 4 --azim 30 --points 500000 --outdir <输出目录>
```

参数：`--res`(分辨率) `--samples`(Cycles采样) `--rings`(仰角环数) `--azim`(每环方位角) `--points`(真值点数) `--outdir`(输出目录) `--smoke`(快速测试)。

改场景：编辑 `generate_dataset.py` 里的 `setup_scene()` 增删物体/材质，或在 Blender 里打开 `scene.blend` 修改后重渲。

---

## 5. 评估建议

- **几何精度**：对重建点云与 `gt/dense_pointcloud.ply` 做双向 Chamfer Distance、Precision/Recall/F1（用 CloudCompare 的 C2C 距离，或 `pytorch3d`/`open3d`）。
- **外观**：NeRF/3DGS 可额外对比渲染视差(PSNR/SSIM/LPIPS)，用 `gt/mesh.ply` 或 `images/` 中预留的测试视角。
- 相机位姿已给出，也可故意**丢弃位姿**只喂 `images/` 给 MVS(COLMAP)，验证「从图像恢复位姿 + 密集重建」的完整链路。
