赞
踩
前几天尝试在windows上编译colmap,途中遇到了很多的问题,在这里记录以下,方便以后参考,以下内容仅供参考,如有错误欢迎指正,也欢迎大家有问题在评论区讨论。
windows10 专业版20H2
cuda 10.0
VS2015
QT 5.9.3
cmake 3.18.5
另外可能需要git、7z等软件
大体的编译流程如下,先手动编译Boost(也可以现在编译好的),之后编译CGAL,最后编译colmap,其中编译colmap才是遇到坑最多的地方
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
因为本人使用的时VS2015因此对应的toolset是msvc-14.0,其它版本的对应关系可以参考这篇文章,这里prefix指定存放编译后文件的目录
4.经过漫长的等待就可以看到在prefix指定的目录下生成了include和lib库
至此Boost编译完成,为了后面表述方便用<boost_path> 指代prefix所指定的目录
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版本必须有哦)
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)
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"))
这个地方不改也行,报错的时候把对应的库手动复制过去也行“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")
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"
这里建议在colmap根目录下创建一个bat脚本,直接执行bat脚本即可
7.等待…
经过漫长的等待,应该是会编译成功的,不成功,可能需要你具体地去查查哪里有问题了,不过一般按照我这流程下来是没问题的。脚本跑完之后会在build目录下生成__install__目录,里面会有COLMAP.bat,执行即可,至此编译成功。
8.如果你有反复需要编译的需求,可以将build.py中那些第三方库编译函数中的目录检测功能重新打开,防止后面在编译的时候又会编译一遍第三方库,就是这句
if os.path.exists(path):
return
总结:编译完成后发现,其实也没什么难的,windows下的编译问题多发生在那个build.py,哪里发生问题了就去看看build.py那一部分所对应的功能是啥,然后看看能不能曲线解决下,加油,希望你能编译出一个能用的colmap,欢迎大家有问题在评论区讨论。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。