- 必须是有序序列(Sequence is Mandatory)
不支持无序数据集(如 Zip-NeRF 风格或许多 DeepBlending 场景)。
要求图像按顺序捕获,且连续帧之间必须有足够的重叠(理想情况下超过 2/3 的内容)。 - 严格的运动要求(Translation is Key)
连续帧之间必须确保足够的平移(Translation),以进行准确的三角测量。
必须避免只有旋转而没有平移的情况。 - 缺乏闭环校正(No Loop Closure)
当轨迹重新访问重建区域时,不进行漂移补偿。
这会导致姿态误差累积,可能引起错位。 - 相机模型和分辨率限制
要求图像遵循针孔投影模型,主点居中(无鱼眼/畸变)。
它只优化焦距。
匹配器在 1-2MP 范围内表现最佳。
MP(Megapixel,百万像素): 1MP 等于一百万像素。
匹配器(Matcher): 指的是该方法中用于在连续图像之间寻找对应特征点,从而估计相机姿态(Pose)和场景深度(三角测量)的算法部分。
建议
缓慢、顺序移动: 在场景周围缓慢行走并按顺序拍照。
保持基线: 在转身时,要侧移一步(“taking a step sideways”)以保持足够的平移基线。
户外比室内容易: 户外场景效果很好,因为运动自然;室内场景由于空间限制更容易出错。
解决方案:使用相机标定和预处理
(On-the-fly NVS)仅优化焦距,它不具备优化畸变参数的能力。如果输入图像带有明显的未校正畸变,模型的姿态估计和 3D 重建的精度会受到严重影响。
在 NeRF/3DGS 领域处理这个问题有成熟的标准流程:通过相机标定和预处理来消除畸变。
需要的是一个将物理相机模型(带畸变)转换成数学上的理想针孔模型(无畸变)的步骤,这通常通过以下方法实现:
1. 相机标定(Calibration)
这是获取畸变参数的基础步骤。
- 方法: 最常用的是基于张正友标定法(Zhang's method)的棋盘格或圆点板标定。
- 工具: 您可以使用 OpenCV 中集成的标定工具,通过拍摄不同角度的标定板图像来计算出相机的内参(焦距 \(f_x, f_y\)、主点 \(c_x, c_y\))和畸变参数(径向畸变 \(k_1, k_2, k_3\)、切向畸变 \(p_1, p_2\))。
2. 图像校正(Undistortion)
在获得畸变参数后,您需要用这些参数对所有输入图像进行预处理。
- 过程: 校正工具会根据计算出的畸变参数,对原始图像的每个像素进行反向几何变换,将图像上弯曲的直线恢复成直线。
- 结果: 校正后的图像会更接近理想的针孔模型,可以直接作为
on-the-fly-nvs
的输入。
3. 常用软件和工具
- 学术/开发工具:
- OpenCV: 提供完整的标定和畸变校正功能,常用于 NeRF/3DGS 工作流的前处理。
- COLMAP: 如果您先用 COLMAP 处理了整个数据集,它会输出一个包含经过畸变校正的内参文件。虽然这个
on-the-fly-nvs
方法不是 COLMAP 的替代品,但您可以使用 COLMAP 提供的内参和校正后的图像。
- 商业/图形工具(如果不需要最高精度):
- DxO ViewPoint / Nikon NX Studio 等: 这些专业图像编辑软件具备自动校正功能,可以通过查找镜头的预设光学模块来消除桶形和枕形畸变,并将图像裁剪以保持视野。
总结:
即使实际相机存在畸变,您也不需要更换相机。关键在于进行相机标定,并在将数据输入到on-the-fly-nvs
方法之前,使用标定结果对所有图像进行畸变校正预处理,以满足该方法对“无鱼眼/畸变”针孔模型的严格要求。
您提出的要求是正确的。为了更好地解决“无畸变”的问题,我们可以将相机标定和校正的步骤具体化,提供一个基于 OpenCV/Python 的实用流程。这是 NeRF 和 3DGS 领域最常用的方法。
由于on-the-fly-nvs
强调的是效率和即时性,它的预处理要求必须被严格满足。
- DxO ViewPoint / Nikon NX Studio 等: 这些专业图像编辑软件具备自动校正功能,可以通过查找镜头的预设光学模块来消除桶形和枕形畸变,并将图像裁剪以保持视野。
相机畸变校正的具体流程(基于 OpenCV)
这个过程分为三个阶段:数据采集、参数标定和图像校正。
阶段一:数据采集(准备标定板图片)
您需要准备一个棋盘格或圆点阵列的标定板。
- 打印标定板: 确保标定板是平整的,没有弯曲或褶皱。
- 拍摄图片: 使用您要用于
on-the-fly-nvs
的同一相机和设置(焦距、分辨率等)拍摄标定板。- 数量: 拍摄 15 到 25 张图片。
- 角度: 必须在不同角度、距离和位置拍摄。
- 包括相机正对标定板的图片。
- 包括相机倾斜(例如 45 度)拍摄的图片。
- 包括标定板位于画面边缘和角落的图片,以捕捉边缘的畸变。
- 对焦: 确保每张图片都清晰对焦。
阶段二:参数标定(计算畸变参数)
这一步使用 Python 和 OpenCV 来计算相机的内参矩阵 \(K\) 和 畸变系数 \(D\)。
所需工具: Python, OpenCV (cv2
), NumPy
核心步骤:
- 定义标定板参数: 告诉程序您的标定板有多少行、多少列角点,以及每个方格的实际尺寸(单位可以是任意的,但要保持一致)。
- 查找角点: OpenCV 函数
cv2.findChessboardCorners()
会尝试在每张图片中自动定位棋盘格的角点。 - 精确化角点: 使用
cv2.cornerSubPix()
进一步提高角点位置的精度。 - 计算参数: 使用
cv2.calibrateCamera()
函数,输入所有图片中检测到的 2D 图像点(imgpoints
)及其对应的 3D 物理点(objpoints
)。- 输出: 该函数会返回以下关键参数:
- 相机内参矩阵 \(K\): 包含 \(f_x, f_y, c_x, c_y\)。
- 畸变系数 \(D\): \([k_1, k_2, p_1, p_2, k_3]\)。
- 重投影误差: 这是一个衡量标定精度的指标,通常小于 0.5 像素表示结果可靠。
- 输出: 该函数会返回以下关键参数:
阶段三:图像校正(Undistortion)
在获得了内参 \(K\) 和畸变系数 \(D\) 后,您可以对用于 NVS 重建的所有原始图像进行校正。
- 计算映射表: 使用
cv2.getOptimalNewCameraMatrix()
和cv2.initUndistortRectifyMap()
计算一个映射表(Map)。这个映射表告诉程序如何将原始图像中的像素,重新映射到校正后的图像中,从而获得最佳的视野和裁剪。 - 应用校正: 使用
cv2.remap()
函数,将映射表应用到每一张原始输入图片上。 - 保存结果: 将校正后的图片保存到磁盘上的新文件夹(例如
source_path/images_undistorted/
)。这些无畸变的图片才是您应该输入给on-the-fly-nvs
模型进行训练的。
总结要点
- 数据优先: 确保您用于训练 NVS 的所有图像都是经过畸变校正的。
- 分辨率调整: 在校正后,如果原始图像分辨率很高(例如大于 4MP),您可能还需要将这些校正后的图像下采样到 1-2MP 范围内(例如 1080p),以满足模型对分辨率的要求。
- COLMAP 的作用: 如果您不想自己写标定代码,可以先将数据输入 COLMAP。COLMAP 强大的 SFM 流程会进行标定,并能输出校正后的内参,通常还会提供一个批处理脚本来导出无畸变的图像供 NeRF/3DGS 使用。
采取一些技巧来简化拍摄过程并提高成功率
1 使用视频拍摄,然后提取帧:
操作: 将相机设置为视频模式,缓慢且连续地移动和旋转,覆盖所有需要的角度和位置(包括边缘、近处、远处)。
优点: 比单张拍照更容易确保连续性,并且可以事后从视频中提取出 15-25 张最符合要求的帧作为输入图片。
2 固定标定板,移动相机:
将标定板固定在一个垂直的平面(如墙面或画架)上。
您需要做的仅仅是拿着相机,在标定板周围缓慢移动,并调整相机角度(倾斜)和距离(近远)。
3 专注于画面的四个角:
在拍摄时,故意将标定板放在画面的左上角、左下角、右下角和右上角,确保这四个区域都有标定板数据。
技巧: 您不需要让标定板充满整个画面,只需让它的一部分清晰地落在您想捕捉的边缘区域即可。
4 实时反馈工具 (如果有):
如果您使用的是 OpenCV 标定代码,一些实现会提供一个实时窗口。
这个窗口会在您移动相机时实时显示它是否找到了足够的角点。这能帮助您快速判断当前拍摄角度是否有效。