Predator's Vision

画像処理、3D点群処理、DeepLearning等の備忘録

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

Android Studio でデバッグ実行してもブレークポイントで止まらない場合の対処

タイトルの件でちょっとハマったのでメモ。
Android Studioデバッグ実行してもブレークポイントで止まらない場合、考えられる理由は私の知っている範囲では次の3つ。まだまだ事例は他にもあるかもしれないですが。
私がハマったのは3番目の奴です。

1. AsyncTask等で別スレッドで動いている場合

そのスレッドでデバッグできるようにするために追加すべきコードがあります。
「AsyncTask ブレークポイント」等で検索すればたくさん出てきます。

www.ecoop.net

2. Gradle の設定で debuggable が false になっている

android studio ブレークポイント 止まらない」で検索すると下記サイトがヒットします。
d.hatena.ne.jp

3. Gradle の設定で minifyEnabledが true になっている

私はこれでした。debuggableが true でも minifyEnabled が false じゃないとブレークポイントでは止まらないのですね…

以上!

OpenCVを使いたいときのcmakeの書き方

次のように書けばよい。かなりシンプル。link_directoriesの指定は不要。
なぜならば、${OpenCV_LIBS}でライブラリへの絶対パスが指定されるため

OpenCVが見つかった場合のみプロジェクトを作成したければif(DEFINED ${OpenCV_VERSION})でadd_executableやtarget_link_librariesを囲めばよい

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)

project(opencv_project)

find_package(OpenCV 2.4 REQUIRED)

include_directories(${OpenCV_INCLUDE_DIRS})

add_executable (project1 hoge.cpp)
target_link_libraries (project1 ${OpenCV_LIBS})

一発でわかる Iterative Closest Point のコンセプト図解

2つの点群を重ね合わせる手法にICP (Iterative Closest Point) というものがあります。
1992年に発表されてから、現在に至るまであらゆる派生手法が提案されています。

ベーシックなICPの仕組みは一言で言うと「近傍点との距離の最小化を繰り返す」です。これを動画で示すと次の通りです。ちょっとずつ2つの点群の間が縮まって、最後的にぴったり合わせられるわけです。

ICPの注意点として、「初期位置合わせが必要」ということが挙げられます。言い換えると「2つの点群はある程度近い位置に配置されていないといけない」ということです。もし、初期位置合わせがされていなければ、下記の動画のように変な結果に終わってしまいます。(オレンジの破線が正しい点の対応関係を表す)

適切な初期位置合わせ+ICPで例えば次の画像のように2つの3D点群をピタッと合わせられます。

  • 点群1

f:id:presan:20160518011521p:plain

  • 点群2

f:id:presan:20160518011525p:plain

  • ICP結果

f:id:presan:20160518011528p:plain

Visual Studio 2013 でソリューションを開こうとするとビジーになる場合の対処

Visual Studio 2013 でソリューションを開こうとするとビジーになる場合が前からちょくちょくあったが、
今日は全く開けなくなった。何回再起動したり.suoファイルを削除したりしても治らない。


そこでちょっと調べて見つけた解決方法。私はこれで治った。

簡単に言うと「ツール」→「オプション」→「ソース管理」でプラグイン「なし」にする

OpenCV3では視差画像が作れない?

OpenCVで視差画像を作ろうと思って調べたところ下記のサイトを発見。ちなみに2008年の情報。
Momma's Wiki: OpenCV/距離計測 - ステレオマッチング(二眼カメラ)による距離計測 ※CvCalibFilte...

これに従って、最新であるOpenCV3を使って試してみたら、cvFindStereoCorrespondence関数が未定義といって怒られる。
ちなみに、OpenCV2.4.11を使ったらできた。

OpenCV3では視差画像は作れないか、別の何かに置き換わったのかもしれない。
暇なときにOpenCV3の視差画像関連の機能を探したいと思います。

PTAMをVS2013でWebカメラ使用版に改造してビルド

PTAMビルド手順はいろんなサイトに載ってますが、100%その通りにやればビルドできたというわけではないので、そのメモ。

上記サイトの情報に加えて必要だったこと

事前準備

PTAMコンパイル

  • 「Build/Win32の中のPTAM.sln、PTAM.vcproj、CameraCalibrator.vcproj、VideoSource_Win32_CMU1394.cc を PTAM フォルダ直下へコピー。」とあるが:
    • PTAM.vcxproj、CameraCalibrator.vcxprojの2ファイルも必要
    • VideoSource_Win32_CMU1394.ccは不要
  • 2つのプロジェクト(CameraCalibrator、PTAM)それぞれのDebug、Releaseの使用libファイルからcmu1394.lib的なのを削除
  • max, min関数が見つからないと怒られるので、ATANCamera.ccに「#include <algorithm>」を追加