文章

探索TheiaSfM:0-介绍与安装

1 TheiaSfM简介

TheiaSfM是由 Chris Sweeney 开发的一款专注于结构从运动(Structure from Motion,简称 SfM)任务的计算机视觉库。它以可靠性、易用性和扩展性为核心特点,实现了包括多视图几何、位姿求解、特征提取与匹配、三维重建等关键算法。TheiaSfM 的代码风格清晰,外部依赖性低,这使得它在处理大规模 SfM 任务时表现出了优异的性能。项目的源代码已在 Github 上开源,并且提供了详尽的API文档1

2 TheiaSfM 安装

与其他一些知名的三维重建库如 OpenMVG 和 Colmap 相比,TheiaSfM 的文档和资料相对较少2。TheiaSfM 的实际依赖库不多,其中 glog、gflags 和 cereal 已经包含在项目内部,外部依赖仅有 OpenImageIO、Eigen 和 Ceres。Eigen 库只需引入头文件即可,Ceres 库的编译也相对简单。较为复杂的是 OpenImageIO 库的编译,因为它的版本众多,而网上的博客确定能够与 TheiaSfM 兼容的 OpenImageIO 版本是 1.7.173。此外,OpenImageIO 的依赖 OpenEXR 在 Windows 环境下的编译也相当具有挑战性。

2.1 方法一:使用 vcpkg 安装

你可以通过 vcpkg 直接安装 TheiaSfM 库:

1
vcpkg install theia:[triplet]

展开

其中,[triplet] 根据你的编译器和库类型而定,例如 x64-windows-dynamicx64-mingw-static

2.2 方法二:从源码编译

如果你希望从源码进行调试,可以考虑先安装 TheiaSfM 的依赖,然后从源码编译。在实际编译过程中,你会发现 TheiaSfM 的外部依赖并不算多,如果使用源码自带的库和 CMakeLists 文件,编译过程会相对轻松。

对于各个依赖库,常规编译即可。较为复杂的是 SuiteSparse,在 Windows 下 FindBlas 经常报错,这时你需要在 SuiteSparse 的 CMakeLists 文件中手动指定相应的库目录:

1
2
set(BLAS_LIBRARIES YOUR_BLAS_DIR)
set(LAPACK_LIBRARIES YOUR_LAPACK_DIR)

展开

此外,SuiteSparse 库还需要 gmp 和 mpfr 库,建议使用 vcpkg 进行安装,安装 mpfr 时会自动安装 gmp:

1
vcpkg install mpfr

展开

配置好源码环境中的依赖项后,你可以按照常规方式进行编译和运行。

  • OpenImageIO命名空间:oiio::->OIIO::
  • getline函数在Windows平台没有实现
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
// Choose implementation of getline according to platform
#ifdef _WIN32
    #define PLATFORM_WINDOWS
#elif __linux__ || __APPLE__
    #define PLATFORM_POSIX
#else
    #error "Unknown platform"
#endif

#ifdef PLATFORM_WINDOWS
    #include <malloc.h>
    ssize_t getline(char **lineptr, size_t *n, FILE *stream) {
        char *bufptr = NULL;
        size_t size = 0;
        int c;

        if (lineptr == NULL || n == NULL) return -1;

        bufptr = *lineptr;
        size = *n;

        c = fgetc(stream);
        while (c != EOF && c != '\n') {
            if (bufptr - *lineptr < size - 1) {
                *bufptr++ = c;
            }
            c = fgetc(stream);
        }

        *bufptr = '\0';
        if (bufptr - *lineptr >= size - 1) {
            size_t new_size = size * 2;
            char *new_bufptr = (char *)realloc(*lineptr, new_size);

            if (new_bufptr == NULL) return -1;

            *lineptr = new_bufptr;
            *n = new_size;
            bufptr = *lineptr + size;
            while (c != EOF && c != '\n') {
                if (bufptr - *lineptr < *n - 1) {
                    *bufptr++ = c;
                }
                c = fgetc(stream);
            }
            *bufptr = '\0';
        }

        return bufptr - *lineptr;
    }
#else
    #include <stdio.h>
#endif

展开

参考

  1. Theia文档. www.theia-sfm.org ↩︎

  2. 库安装:TheiaSfM. https://zhuanlan.zhihu.com/p/54112018 ↩︎

  3. theia-sfm配置文档. https://zhuanlan.zhihu.com/p/38880542 ↩︎

本文由作者按照 CC BY NC SA 4.0 进行授权