当前位置:   article > 正文

关于我想在windows上编译colmap这件事_colmap boost

colmap boost

关于我想在windows上编译colmap这件事

前几天尝试在windows上编译colmap,途中遇到了很多的问题,在这里记录以下,方便以后参考,以下内容仅供参考,如有错误欢迎指正,也欢迎大家有问题在评论区讨论。

环境

windows10 专业版20H2
cuda 10.0
VS2015
QT 5.9.3
cmake 3.18.5
另外可能需要git、7z等软件

编译流程

大体的编译流程如下,先手动编译Boost(也可以现在编译好的),之后编译CGAL,最后编译colmap,其中编译colmap才是遇到坑最多的地方

编译Boost

1.去官网下载一个Boost版本,最好不要太新,不然可能出问题(直觉),这里我用的是1.66.0版本
2. 解压后执行booststrap.bat脚本,之后会生成b2.exe和bjam.exe两个可执行文件,在编译时只用到了b2.exe
3. 在这篇文章的帮助下可以对Boost的编译有更进一步的了解,这里本人在执行时使用的参数如下

b2.exe install --toolset=msvc-14.0 --prefix="E:\3DAbout\ThirdParty\boost_1_66_0\msvc-140_64" link=static runtime-link=shared threading=multi architecture=x86 address-model=64 debug release
  • 1

因为本人使用的时VS2015因此对应的toolset是msvc-14.0,其它版本的对应关系可以参考这篇文章,这里prefix指定存放编译后文件的目录
4.经过漫长的等待就可以看到在prefix指定的目录下生成了include和lib库
至此Boost编译完成,为了后面表述方便用<boost_path> 指代prefix所指定的目录

编译CGAL

1.去官网下载一个CGAL安装文件,这里实际上下载的是源码,安装完成后还是需要自己使用cmake进行编译,编译完成后将编译好的文件复制一份保留之后将cgal卸载即可,这里下载4.14.3版本
2.之后使用cmake进行编译,configure时最好用64为哦,后面只需要指定Boost_DIR和Boost_INCLUDE_DIR,前者是<boost_path>,后者是<boost_path>\include\boost-1_66,之后configure,generate
3.在build文件夹下找到CGAL.sln,打开编译生成对应的版本即可(Release版本必须有哦)

编译colmap

1.从github上下载colmap,这里下载的是3.5版本(同样不是最新版)
2.这里咱们使用scripts目录下的build.py脚本进行编译安装,但是你直接使用的话会存在网络连接错误等问题,emmm,具体原因有一个是eigen那个库好像删了?然后其它的话也是下载的巨慢,因此采用的方法是咱们自己把库下载下来,扔进去就好了,可以去刚才的那个网盘下载。
3.在colmap根目录下创建一个build文件夹(这里可以自定义,后面在编译时能找到就好),将刚才网盘里的“colmap编译需要的第三方库.zip”中所有的库在build目录下解压,解压时最好选“在当前目录解压”哦,之后将所有的文件夹重命名如下
第三方库名称
图中的colmap目录可以先不管
4.之后修改scripts\build.py文件,大体的意思就是将所有需要下载以及重命名的地方注释掉,直接用咱们自己下载的库,我在网盘里提供的库与colmap3.5所需要的库相对应,如果你装其它版本的colmap就下载它所指定的版本,去官网或者github上下载就好了,没啥难的,说明下build_cmake_project函数会在第三方库下面创建__build__目录用于保存编译后的结果,需要调用cmake,因此你需要确保path里加了cmake。下面提供我对整个脚本的更改(只列出了更改过的函数)

def build_eigen(args):
    path = os.path.join(args.build_path, "eigen")
    # if os.path.exists(path):
        # return

    # url = "https://bitbucket.org/eigen/eigen/get/3.3.4.zip"
    # archive_path = os.path.join(args.download_path, "eigen-3.3.4.zip")
    # download_zipfile(url, archive_path, args.build_path,
                     # "e337acc279874bc6a56da4d973a723fb")
    # shutil.move(glob.glob(os.path.join(args.build_path, "eigen-*"))[0], path)

    build_cmake_project(args, os.path.join(path, "__build__"))


def build_freeimage(args):
    path = os.path.join(args.build_path, "freeimage")
    # if os.path.exists(path):
        # return

    if PLATFORM_IS_WINDOWS:
        # url = "https://kent.dl.sourceforge.net/project/freeimage/" \
              # "Binary%20Distribution/3.17.0/FreeImage3170Win32Win64.zip"
        # archive_path = os.path.join(args.download_path, "freeimage-3.17.0.zip")
        # download_zipfile(url, archive_path, args.build_path,
                         # "a7e6f2f261e72260ec5b91c2a0f4bde3")
        # shutil.move(os.path.join(args.build_path, "FreeImage"), path)
        copy_file_if_not_exists(
            os.path.join(path, "Dist/x64/FreeImage.h"),
            os.path.join(args.install_path, "include/FreeImage.h"))
        copy_file_if_not_exists(
            os.path.join(path, "Dist/x64/FreeImage.lib"),
            os.path.join(args.install_path, "lib/FreeImage.lib"))
        copy_file_if_not_exists(
            os.path.join(path, "Dist/x64/FreeImage.dll"),
            os.path.join(args.install_path, "lib/FreeImage.dll"))
    else:
        # url = "https://kent.dl.sourceforge.net/project/freeimage/" \
              # "Source%20Distribution/3.17.0/FreeImage3170.zip"
        # archive_path = os.path.join(args.download_path, "freeimage-3.17.0.zip")
        # download_zipfile(url, archive_path, args.build_path,
                         # "459e15f0ec75d6efa3c7bd63277ead86")
        # shutil.move(os.path.join(args.build_path, "FreeImage"), path)

        if PLATFORM_IS_MAC:
            with fileinput.FileInput(os.path.join(path, "Makefile.gnu"),
                                     inplace=True, backup=".bak") as fid:
                for line in fid:
                    if "cp *.so Dist/" in line:
                        continue
                    if "FreeImage: $(STATICLIB) $(SHAREDLIB)" in line:
                        line = "FreeImage: $(STATICLIB)"
                    print(line, end="")
        elif PLATFORM_IS_LINUX:
            with fileinput.FileInput(
                    os.path.join(path, "Source/LibWebP/src/dsp/"
                                 "dsp.upsampling_mips_dsp_r2.c"),
                    inplace=True, backup=".bak") as fid:
                for i, line in enumerate(fid):
                    if i >= 36 and i <= 44:
                        line = line.replace("%[\"", "%[\" ")
                        line = line.replace("\"],", " \"],")
                    print(line, end="")
            with fileinput.FileInput(
                    os.path.join(path, "Source/LibWebP/src/dsp/"
                                 "dsp.yuv_mips_dsp_r2.c"),
                    inplace=True, backup=".bak") as fid:
                for i, line in enumerate(fid):
                    if i >= 56 and i <= 58:
                        line = line.replace("\"#", "\"# ")
                        line = line.replace("\"(%", " \"(%")
                    print(line, end="")

        subprocess.call(["make", "-f", "Makefile.gnu",
                         "-j{}".format(multiprocessing.cpu_count())], cwd=path)

        copy_file_if_not_exists(
            os.path.join(path, "Source/FreeImage.h"),
            os.path.join(args.install_path, "include/FreeImage.h"))
        copy_file_if_not_exists(
            os.path.join(path, "libfreeimage.a"),
            os.path.join(args.install_path, "lib/libfreeimage.a"))


def build_glew(args):
    path = os.path.join(args.build_path, "glew")
    # if os.path.exists(path):
        # return

    # url = "https://kent.dl.sourceforge.net/project/glew/" \
          # "glew/2.1.0/glew-2.1.0.zip"
    # archive_path = os.path.join(args.download_path, "glew-2.1.0.zip")
    # download_zipfile(url, archive_path, args.build_path,
                     # "dff2939fd404d054c1036cc0409d19f1")
    # shutil.move(os.path.join(args.build_path, "glew-2.1.0"), path)

    build_cmake_project(args, os.path.join(path, "build/cmake/__build__"))

    if PLATFORM_IS_WINDOWS:
        shutil.move(os.path.join(args.install_path, "bin/glew32.dll"),
                    os.path.join(args.install_path, "lib/glew32.dll"))
        os.remove(os.path.join(args.install_path, "bin/glewinfo.exe"))
        os.remove(os.path.join(args.install_path, "bin/visualinfo.exe"))


def build_gflags(args):
    path = os.path.join(args.build_path, "gflags")
    # if os.path.exists(path):
        # return

    # url = "https://github.com/gflags/gflags/archive/v2.2.1.zip"
    # archive_path = os.path.join(args.download_path, "gflags-2.2.1.zip")
    # download_zipfile(url, archive_path, args.build_path,
                     # "2d988ef0b50939fb50ada965dafce96b")
    # shutil.move(os.path.join(args.build_path, "gflags-2.2.1"), path)
    os.remove(os.path.join(path, "BUILD"))

    build_cmake_project(args, os.path.join(path, "__build__"))


def build_glog(args):
    path = os.path.join(args.build_path, "glog")
    # if os.path.exists(path):
        # return

    # url = "https://github.com/google/glog/archive/v0.3.5.zip"
    # archive_path = os.path.join(args.download_path, "glog-0.3.5.zip")
    # download_zipfile(url, archive_path, args.build_path,
                     # "454766d0124951091c95bad33dafeacd")
    # shutil.move(os.path.join(args.build_path, "glog-0.3.5"), path)

    build_cmake_project(args, os.path.join(path, "__build__"))


def build_suite_sparse(args):
    if not args.with_suite_sparse:
        return

    path = os.path.join(args.build_path, "suite-sparse")
    # if os.path.exists(path):
        # return

    # url = "https://codeload.github.com/jlblancoc/" \
          # "suitesparse-metis-for-windows/zip/" \
          # "7bc503bfa2c4f1be9176147d36daf9e18340780a"
    # archive_path = os.path.join(args.download_path, "suite-sparse.zip")
    # download_zipfile(url, archive_path, args.build_path,
                     # "e7c27075e8e0afc9d2cf188630090946")
    # shutil.move(os.path.join(args.build_path,
                             # "suitesparse-metis-for-windows-"
                             # "7bc503bfa2c4f1be9176147d36daf9e18340780a"), path)

    build_cmake_project(args, os.path.join(path, "__build__"))

    if PLATFORM_IS_WINDOWS:
        lapack_blas_path = os.path.join(args.install_path,
                                        "lib64/lapack_blas_windows/*.dll")
        for library_path in glob.glob(lapack_blas_path):
            copy_file_if_not_exists(
                library_path, os.path.join(args.install_path, "lib",
                                           os.path.basename(library_path)))


def build_ceres_solver(args):
    path = os.path.join(args.build_path, "ceres-solver")
    # if os.path.exists(path):
        # return

    # url = "https://github.com/ceres-solver/ceres-solver/archive/1.14.0.zip"
    # archive_path = os.path.join(args.download_path, "ceres-solver-1.14.0.zip")
    # download_zipfile(url, archive_path, args.build_path,
                     # "26b255b7a9f330bbc1def3b839724a2a")
    # shutil.move(os.path.join(args.build_path, "ceres-solver-1.14.0"), path)

    extra_config_args = [
        "-DBUILD_TESTING=OFF",
        "-DBUILD_EXAMPLES=OFF",
    ]

    if args.with_suite_sparse:
        extra_config_args.extend([
            "-DLAPACK=ON",
            "-DSUITESPARSE=ON",
        ])
        if PLATFORM_IS_WINDOWS:
            extra_config_args.extend([
                "-DLAPACK_LIBRARIES={}".format(
                    os.path.join(args.install_path,
                                 "lib64/lapack_blas_windows/liblapack.lib")),
                "-DBLAS_LIBRARIES={}".format(
                    os.path.join(args.install_path,
                                 "lib64/lapack_blas_windows/libblas.lib")),
            ])

    if PLATFORM_IS_WINDOWS:
        extra_config_args.append("-DCMAKE_CXX_FLAGS=/DGOOGLE_GLOG_DLL_DECL=")

    build_cmake_project(args, os.path.join(path, "__build__"),
                        extra_config_args=extra_config_args)
  • 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
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198

5.改完上面几个函数后,还有个地方需要更改,就是build_post_process函数,这个函数会复制一些库到__install__目录下,其中对于cgal相关库那一部分的复制需要与你实际安装的版本对应,我的修改如下

def build_post_process(args):
		...
        if args.cgal_path:
            gmp_lib_path = os.path.join(
                args.cgal_path, "../auxiliary/gmp/lib/libgmp-10.dll")
            if os.path.exists(gmp_lib_path):
                copy_file_if_not_exists(
                    gmp_lib_path,
                    os.path.join(args.install_path, "lib/libgmp-10.dll"))
            copy_file_if_not_exists(
                os.path.join(args.cgal_path,
                             "bin/Release/CGAL-vc140-mt-4.14.3.dll"),
                os.path.join(args.install_path, "lib/CGAL-vc140-mt-4.14.3.dll"))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

这个地方不改也行,报错的时候把对应的库手动复制过去也行“bin/Release/CGAL-vc140-mt-4.14.3.dll” 和 “lib/CGAL-vc140-mt-4.14.3.dll”类似文件可以在cgal的build目录下找到的
这里补充说明下,eigen库在编译时可能需要用到boost库,但是cmake过程中没有办法让你手动选择,因此可能需要你提前修改eigen的makefile,找到eigen\CMakeLists.txt,在一个比较靠前的位置set一下Boost_INCLUDE_DIR,如下

set(Boost_INCLUDE_DIR "E:/3DAbout/ThirdParty/boost_1_66_0/msvc-140_64/include/boost-1_66")
  • 1

6.在colmap根目录下打开cmd,使用build.py脚本进行编译即可

python scripts/python/build.py --build_path E:/3DAbout/colmap/build --colmap_path E:/3DAbout/colmap --boost_path "E:/3DAbout/ThirdParty/boost_1_66_0/msvc-140_64" --qt_path "C:/Qt/Qt5.9.3/5.9.3/msvc2015_64" --cuda_path "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v10.0" --cgal_path "E:/3DAbout/ThirdParty/CGAL-4.14.3/build"
  • 1

这里建议在colmap根目录下创建一个bat脚本,直接执行bat脚本即可
7.等待…
经过漫长的等待,应该是会编译成功的,不成功,可能需要你具体地去查查哪里有问题了,不过一般按照我这流程下来是没问题的。脚本跑完之后会在build目录下生成__install__目录,里面会有COLMAP.bat,执行即可,至此编译成功。
8.如果你有反复需要编译的需求,可以将build.py中那些第三方库编译函数中的目录检测功能重新打开,防止后面在编译的时候又会编译一遍第三方库,就是这句

    if os.path.exists(path):
        return
  • 1
  • 2

总结:编译完成后发现,其实也没什么难的,windows下的编译问题多发生在那个build.py,哪里发生问题了就去看看build.py那一部分所对应的功能是啥,然后看看能不能曲线解决下,加油,希望你能编译出一个能用的colmap,欢迎大家有问题在评论区讨论。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号