ぷろぐ((>ω<))

ぷろぐらみんぐ関係のメモ

Direct Sparse Odometry (DSO) を Win10, VS2017 でビルド

環境

スタート地点

本家Gitは下記だがLinux/Mac前提。
GitHub - JakobEngel/dso: Direct Sparse Odometry
これをWindows向けに移植したforkがあったので、これを使う。
GitHub - AndreV2890/dso: Direct Sparse Odometry

しかし手元の環境ではすんなりビルドができなかった。
どうも、上記Win版DSOは下記の環境でのビルドを想定しているようである。

thirdpartyの準備

まず、thirdpartyはx86を前提として準備されている。自分で全部やりなおすのが面倒だったので、同じくx86で行くことにする。

READMEによると、cmakeしたときに依存ライブラリのパスをそれぞれ設定すればOKと書いてあるが、一部はそのままではうまくいかなかった。

  • READMEの通りやれば、うまくいったもの
    • Eigen
    • SuiteSparse
    • CHOLMOD
    • OpenCV

以下ではうまくいかなかったものについて記す

Boost, Pangolin, OpenCVへのlink (CMakeLists.txt)

cmakeのfind_packageではうまく見つからないので、

set (Boost_FOUND ON)
set (Pangolin_FOUND ON)
set (OpenCV_FOUND ON)

ということにして、includeやlibのパスをinclude_directories,() link_directories()で手動設定。

ちなみにこの3つがないと、dsoのコアライブラリまではビルドできるが、それを使ったアプリ(dso_dataset)がビルドされない。

更にちなみに、BoostはVisualStudio 2015 (vc14, v140)でビルドされているが、v140からそれ以降と互換性があるらしく今回VisualtStudio2017 (vc15, v141)だが再ビルド不要らしい。
VisualStudio2017でDSOをビルドするなら、v141のライブラリじゃないとダメだった。そのため、Boost1.66を別途x86でビルドしてリンク。

Pangolinのビルド

Releaseモード

普通にビルド。ただし、私はOpenNI2を入れていた関係でそれ関係のビルドもONになってしまい、それがリンクエラーを誘発してしばらく詰まっていた。今回OpenNI2は使わないので、CMakeの段階でOFFにする(自動的に設定されたパスを削除してConfigureする)ことで対処。

Debugモード(DSOをDebugモードで動かしたい場合は必須)

DSO.slnとライブラリの種類を合わせないと、最後のDSOビルドでpangolin.lib関連で大量のリンクエラーが発生する。

/MDとか/MTとかmsvcrt.libとかlibc.libとかlibcmt.libとか - snipsnipsnip

Pangolinプロジェクトを右クリックして[構成プロパティ]→[C/C++]→[コード生成]→[ランタイムライブラリ]を /MTd から /MDd に変更。

OpenCVのDebugモードビルド(DSOをDebugモードで動かしたい場合は必須)

thirdparty/opencvにはRelease版しか入っていない。OpenCVはDebug時はDebug用、Release時はRelease用をちゃんとリンクしないとエラーになるので、x86のDebugを自分で別途ビルド。
(配布されているPrebuiltなOpenCVはx64でしかビルドされていないので自分でビルドするしかない)

libzipのビルド

TUMのデータセットは入力画像をzipで固めているのだが、そのzipのまま画像を読み取れるようにするためにはlibzipが必要。そしてlibzipのビルドにはzlibが必要。

ということで何も考えずにWindowsでビルドできるよう環境がそろった下記を持ってきた。

GitHub - kiyolee/zlib-win-build: zlib Windows build with Visual Studio.
GitHub - kiyolee/libzip-win-build: libzip Windows build with Visual Studio.

> cd {somewhere}\
> git clone https://github.com/kiyolee/zlib-win-build.git
> git clone https://github.com/kiyolee/libzip-win-build.git

上記gitのREADMEにも書いてあるが、zlib→libzipの順序でビルドする必要がある。その際、libzipのVSソリューション内のzlibへのincludeやlibのパスは自分の環境に合わせなおす必要があることに注意。

後から気づいたが、Pangolinをビルドするとthirdparty/Pangolin/build/external/にzlibがビルドされているので、これを使ってthirdparty/libzip-1.1.1.tar.gzを解凍&ビルドすればよかったかも。

DSOビルド

ようやくメインのビルド。これもそのままではビルドできない。

zipオフライン映像を入力するよう改造1

Win版forkではWebカメラで動かすように改造されているようなので、本家のmain_dso_pangolin.cppから該当箇所を逆移植。

実際の改造コードの掲載はここでは省略する。やることは次の通り:

  • main関数内のcv::VideoCapture関係の記述を削除
  • main関数冒頭でparseArgumentするようにし、sourceなどのハードコード指定を削除
  • 画像読み込みのwhile文を削除し、本家からfor文を移植

zipオフライン映像を入力するよう改造2

src\util\DatasetReader.hの中のgetdir関数がPOSIX仕様なので、下記を参考に書き換え。
ディレクトリ内のファイルリストを得る

#ifdef _MSC_VER
#include <io.h>
#else
#include <dirent.h>
#endif

inline int getdir(std::string dir, std::vector<std::string> &files)
{
#ifdef _MSC_VER
	struct _finddata_t fdata;
	intptr_t fh = _findfirst(dir.c_str(), &fdata);
	if (-1 == fh)
	{
		return -1;
	}

	do {
		std::string name = std::string(fdata.name);
		if (name != "." && name != "..")
			files.push_back(name);
	} while (0 == _findnext(fh, &fdata));

	_findclose(fh);
#else
    // (省略)
#endif
    std::sort(files.begin(), files.end());

    if(dir.at( dir.length() - 1 ) != '/') dir = dir+"/";
	for(unsigned int i=0;i<files.size();i++)
	{
		if(files[i].at(0) != '/')
			files[i] = dir + files[i];
	}

    return files.size();
}

usleep削除

main_dso_pangolin.cpp内にusleep()が使われているがWindowsでは使えない。
WinAPIのQueryPerformanceCounter()に代替するのが正しいのだろうが、面倒なのでひとまず単純にコメントアウト。問題が生じたら後で上の修正をすることとする…

リンクするライブラリを追加

リンクするライブラリはmain_dso_pangolin.cppの冒頭で #pragma comment で指定されている。下記のように編集。

//#include <GL/freeglut.h>

#pragma comment(lib, "glew.lib")
#pragma comment(lib, "libpng16.lib")
#pragma comment(lib, "jpeg.lib")
#pragma comment(lib, "libzip.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "opengl32.lib")

// Boost
#ifdef _DEBUG
#pragma comment(lib, "libboost_thread-vc141-mt-gd-x32-1_66.lib")
#pragma comment(lib, "libboost_system-vc141-mt-gd-x32-1_66.lib")
#pragma comment(lib, "libboost_date_time-vc141-mt-gd-x32-1_66.lib")
#pragma comment(lib, "libboost_chrono-vc141-mt-gd-x32-1_66.lib")
#else
#pragma comment(lib, "libboost_thread-vc141-mt-s-x32-1_66.lib")
#pragma comment(lib, "libboost_system-vc141-mt-s-x32-1_66.lib")
#pragma comment(lib, "libboost_date_time-vc141-mt-s-x32-1_66.lib")
#pragma comment(lib, "libboost_chrono-vc141-mt-s-x32-1_66.lib")
#endif

// OpenCV
#ifdef _DEBUG
#pragma comment(lib,"opencv_core341d.lib")
#pragma comment(lib,"opencv_highgui341d.lib")
#pragma comment(lib,"opencv_imgproc341d.lib")
#pragma comment(lib,"opencv_imgcodecs341d.lib")
#pragma comment(lib,"opencv_videoio341d.lib")
#else
#pragma comment(lib,"opencv_core341.lib")
#pragma comment(lib,"opencv_highgui341.lib")
#pragma comment(lib,"opencv_imgproc341.lib")
#pragma comment(lib,"opencv_imgcodecs341.lib")
#pragma comment(lib,"opencv_videoio341.lib")
#endif

thirdparty/Pangolin/glewがあったので、要らんやろと思いfreeglutのincludeも消したが、thirdparty/freeglutがあったことに後から気づいた。

いざビルド&実行

ビルドできた。
その後、libpng16.dll, libzip.dll, opencv_*.dllが見つかるようにパスを通すと実行できた。

f:id:presan:20190428213238p:plain
Direct Sparse Odometry on Windows10