Contents

开源3d重建系统

概览

COLMAP 学术界更流行

OpenSfM 更适合GIS领域

OpenMVG + OpenMVS

mvs-texturing

三维重建流程

/posts/%E5%BC%80%E6%BA%90%E4%B8%89%E7%BB%B4%E9%87%8D%E5%BB%BA%E6%A1%86%E6%9E%B6%E4%BB%8B%E7%BB%8D/image.png

开源三维重建系统比较

/posts/%E5%BC%80%E6%BA%90%E4%B8%89%E7%BB%B4%E9%87%8D%E5%BB%BA%E6%A1%86%E6%9E%B6%E4%BB%8B%E7%BB%8D/image%201.png
绿色表示支持,红色表示不支持

COLMAP install

https://github.com/colmap/colmap

https://colmap.github.io/install.html

https://repology.org/project/colmap/versions

pipline

https://blog.csdn.net/m0_56836274/article/details/139245630

docker方式安装

https://hub.docker.com/r/colmap/colmap

FAQ

1、Dense stereo reconstruction requires CUDA, which is not available on your system.

稠密重建必须安装配置cuda

2、No good initial image pair found.

The error “No good initial image pair found” in COLMAP typically occurs during the feature matching or structure-from-motion (SfM) pipeline, specifically when COLMAP is unable to find a good pair of images to start the matching process.

Here are some common causes and solutions for this error:

1. Insufficient Overlap Between Images

  • Cause: If the images do not have enough overlap (i.e., common features), COLMAP may struggle to find a good initial image pair.
  • Solution:
    • Ensure that your images have significant overlap and that the camera movement between shots isn’t too large.
    • Try to include images with obvious common features.

2. Low-Quality or Poorly Captured Images

  • Cause: Images with poor resolution, blurriness, or noise may not have enough features to match.
  • Solution:
    • Use higher-quality images with clear details and fewer blurry areas.
    • Ensure images have distinct features that are easy to detect.

3. Incorrect Camera Parameters

  • Cause: Incorrect camera intrinsic parameters (focal length, principal point, etc.) can affect the feature matching process.
  • Solution:
    • If you have camera calibration data, make sure to input the correct intrinsic parameters in COLMAP.
    • If unsure, you can use the Automatic Calibration option in COLMAP to let it estimate the parameters.

4. Inadequate Feature Extraction or Matching

  • Cause: The feature extraction and matching process may not be set up optimally, leading to no good matches between images.
  • Solution:
    • Increase the number of features extracted by adjusting the parameters in Feature Extraction (e.g., increase the number of keypoints, use different detectors like SIFT or ORB).
    • Use More Robust Matching by adjusting matching parameters or enabling Exhaustive Matching.

5. Misconfigured Camera Model

  • Cause: The selected camera model may not suit your dataset, especially if you’re using a non-standard or specific camera type.
  • Solution:
    • Check if you’re using the correct camera model in COLMAP. If you are using a non-standard camera, try defining the camera model manually or adjust the model settings.

6. Image Quality Control

  • Solution: You can try running the image set through a tool that automatically detects problematic images. If certain images are out of focus, poorly exposed, or lack sufficient texture, COLMAP might fail to create a good initial match. Removing or fixing these images could help.

7. Try Manual Initialization

  • Solution: If automatic initialization fails, you can try manual initialization. In COLMAP, you can manually select two images to initialize the SfM pipeline. This can sometimes bypass the issue when automatic matching is not successful.

8. Image Scale or Alignment Issues

  • Cause: Images might have been resized or improperly aligned (e.g., if they come from different sources with different camera settings or scales).
  • Solution: Make sure all images are aligned correctly, and if they were resized or downsampled, consider working with the original images.

Next Steps:

  • Start by reviewing the dataset and checking for any obvious issues with the images (e.g., overlap, quality).
  • Try adjusting the parameters for feature extraction and matching in COLMAP.
  • If the issue persists, consider using manual initialization to give COLMAP a better starting point.

colmap稀疏点云格式

📌 COLMAP 稀疏点云的目录结构及文件格式

COLMAP 生成的 稀疏重建(Sparse Reconstruction) 结果通常保存在 sparse/ 目录下,其结构如下:

COLMAP_PROJECT/
│── images/             # 输入图像
│── sparse/             # 稀疏点云数据
│   ├── 0/              # 第一组稀疏重建(可有多个)
│   │   ├── cameras.bin       # 相机内参信息
│   │   ├── images.bin        # 图像的位姿 (R, T) 及 3D-2D 观测关系
│   │   ├── points3D.bin      # 3D点云数据
│   ├── txt/            # 可选:转换后的文本格式(cameras.txt, images.txt, points3D.txt)
│   ├── pointcloud.ply  # 可选:PLY 格式点云(用于可视化)
│── database.db         # COLMAP 数据库(存储特征点、匹配关系等)
│── dense/              # 稠密重建(MVS)
│── ...

0/ 目录表示第一个重建模型,如果你进行了多次 Incremental Reconstruction,可能会有 1/, 2/ 等多个重建模型。


📂 1. 稀疏点云的二进制文件格式(默认)

默认情况下,COLMAP 使用二进制格式存储数据:

文件名作用
cameras.bin相机的内参(焦距、主点、畸变系数等)
images.bin相机的外参(位姿 R, T)和 3D-2D 对应关系
points3D.bin稀疏 3D 点云(包含颜色、重投影误差等)

如何转换为文本格式(可读)

可以使用 colmap model_converter 转换:

1
colmap model_converter --input_path sparse/0 --output_path sparse/txt --output_type TXT

这样会生成:

  • cameras.txt
  • images.txt
  • points3D.txt

📄 2. 解析 COLMAP 生成的 txt 文件

(1) cameras.txt

存储相机的内参,每行格式如下:

<camera_id> <model> <width> <height> <params>

示例:

1 PINHOLE 1920 1080 1500.0 960.0 540.0
  • PINHOLE 表示相机模型(可以是 SIMPLE_PINHOLEOPENCV 等)。
  • 1500.0 是焦距 fx
  • 960.0 540.0 是主点坐标 (cx, cy)

(2) images.txt

存储 相机外参(位姿 R, T) 及 3D-2D 观测关系,每个相机两行:

<image_id> <qw> <qx> <qy> <qz> <tx> <ty> <tz> <camera_id> <image_name>
<point2D_x1> <point2D_y1> <point3D_id1> <point2D_x2> <point2D_y2> <point3D_id2> ...

示例:

1 0.998 -0.002 0.055 -0.015 0.2 0.1 1.5 1 img_001.jpg
50.5 30.2 10  120.3 60.7 11  ...
  • qw, qx, qy, qz 是四元数(旋转矩阵)。
  • tx, ty, tz 是平移向量。
  • point2D_x, point2D_y 是该图像上的特征点像素坐标。
  • point3D_id 是点云中对应的 3D 点 ID(如果 1,表示未匹配到 3D 点)。

(3) points3D.txt

存储 3D 点坐标、颜色、重投影误差及观测信息

<point3D_id> <X> <Y> <Z> <R> <G> <B> <error> <track>

示例:

10 1.23 2.34 3.45 255 0 0 0.5  1 23  2 15  3 7
  • 10:点 ID
  • 1.23 2.34 3.45:3D 世界坐标
  • 255 0 0:RGB 颜色
  • 0.5:重投影误差
  • 1 23 2 15 3 7:该点被 image_id=1 的第 23 个关键点观测到,image_id=215 号关键点观测到,依此类推。

📂 3. PLY 格式(可视化用)

如果你想用 MeshLabOpen3D 可视化点云,可以导出 .ply

1
colmap model_converter --input_path sparse/0 --output_path sparse/pointcloud.ply --output_type PLY

该文件包含:

  • 3D 坐标 (x, y, z)
  • 颜色 (r, g, b)

使用 Open3D 读取并可视化:

1
2
3
4
import open3d as o3d

pcd = o3d.io.read_point_cloud("sparse/pointcloud.ply")
o3d.visualization.draw_geometries([pcd])

💡 总结

文件名作用可读性
cameras.bin / cameras.txt存储相机的内参📜 易读(TXT)
images.bin / images.txt存储相机位姿(R, T)及 3D-2D 观测关系📜 复杂但可读
points3D.bin / points3D.txt存储 3D 点云及颜色、重投影误差等📜 重要
pointcloud.plyPLY 格式的点云文件(可视化)📌 方便可视化

如果你需要解析 .bin,可以用 Python 读取:

1
2
3
4
5
6
import colmap_read_model as read_model  # 需要 colmap_read_model.py(可在 COLMAP GitHub 找到)

cameras, images, points3D = read_model.read_model("sparse/0", ext=".bin")
print("Number of cameras:", len(cameras))
print("Number of images:", len(images))
print("Number of 3D points:", len(points3D))

如果你有更具体的问题,比如如何解析 .bin 文件或者转换其他格式,可以告诉我! 🚀

4、外参表示形式

在 COLMAP 中,外参(外部参数,extrinsics)用于描述相机在三维空间中的姿态。COLMAP 使用 世界坐标系到相机坐标系的变换,并采用 四元数 + 平移向量 进行存储。


1. COLMAP 外参的存储格式

q=qw+qxi+qyj+qzk (w,x,y,z顺序)

COLMAP 的外参一般存储在 cameras.txt(相机参数)、images.txt(外参) 或 images.bin(二进制格式)文件中,格式如下:

IMAGE_ID QW QX QY QZ TX TY TZ CAMERA_ID NAME

每一行表示一张图像的外参:

  • IMAGE_ID:图像的 ID
  • QW QX QY QZ:表示 旋转(四元数),用于描述相机姿态
  • TX TY TZ:表示 平移向量(相机在世界坐标系中的位置)
  • CAMERA_ID:相机的 ID(与 cameras.txt 关联)
  • NAME:图像文件名

2. 外参的数学含义

COLMAP 采用 世界坐标系 → 相机坐标系 的变换:

Xc=R⋅Xw+TX_c = R \cdot X_w + T

其中:

  • RR 是旋转矩阵,由四元数转换得到
  • T=(TX,TY,TZ)T = (TX, TY, TZ) 是平移向量
  • XwX_w 是世界坐标系中的点
  • XcX_c 是相机坐标系中的点

如果需要相机的 位姿(世界坐标系中的位置和朝向),可以计算 相机中心 C

C=−RT⋅TC = -R^T \cdot T

其中:

  • RTR^T 是旋转矩阵的转置
  • 计算后得到的是相机在世界坐标系下的中心位置

3. 从 COLMAP 提取外参

如果想将 COLMAP 提供的 四元数+平移向量 转换为 旋转矩阵 R 和相机中心 C,可以使用 Python 代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import numpy as np
from scipy.spatial.transform import Rotation as R

# 假设外参数据
qw, qx, qy, qz = 0.707, 0.0, 0.707, 0.0  # 四元数
tx, ty, tz = 1.0, 2.0, 3.0  # 平移向量

# 1. 四元数转旋转矩阵
rot = R.from_quat([qx, qy, qz, qw]).as_matrix()  # SciPy 需要 [qx, qy, qz, qw]

# 2. 计算相机中心
t = np.array([tx, ty, tz]).reshape(3, 1)
camera_center = -rot.T @ t

print("旋转矩阵 R:\n", rot)
print("相机中心 C:\n", camera_center.flatten())

4. 解析二进制 images.bin

COLMAP 也支持 images.bin 格式,如果想解析,可以用 colmap.bin_to_txt 或者 Python:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import struct

def read_colmap_binary_images(path):
    with open(path, "rb") as f:
        num_images = struct.unpack("<Q", f.read(8))[0]
        images = {}
        for _ in range(num_images):
            data = struct.unpack("<idddddddi", f.read(64))
            image_id, qw, qx, qy, qz, tx, ty, tz, camera_id = data
            name_length = struct.unpack("<I", f.read(4))[0]
            name = f.read(name_length).decode("utf-8")
            images[image_id] = (qw, qx, qy, qz, tx, ty, tz, camera_id, name)
        return images

images = read_colmap_binary_images("images.bin")
print(images)

总结

  • COLMAP 采用四元数 + 平移向量存储外参

  • 外参表示的是世界坐标系到相机坐标系的变换

  • 四元数可以转换为旋转矩阵 R,相机中心可以通过 计算。

    C=−RTTC = -R^T

  • 可以解析 images.txtimages.bin 以获取外参

meshlab

ctrl+左键长按 拖动

ctrl+滚轮 控制点数的增减