Open MVG & Open MVS 1 ビルドを通すまで...

あけましておめでとうございます!今年もよろしくお願いします.
2018年の抱負から始めるべきだったのですが,昨年やり残してたアイテムの備忘録も兼ねて,新年一発目の投稿はSFMで行きます.

で,以前の投稿

daily-tech.hatenablog.com

では,Mastering OpenCVのサンプルコードを使ってSFMを実施しようとしたのですが,これだとアルゴリズムの実装がストレートすぎて,自前のカメラで撮影した写真の対応は難しそうです...何回やっても計算がいい感じに収束しませんでした.ただ,シンプルな作りになっているので,アルゴリズムの基本的な流れの理解にはとても役立つと思います.

で,自前のカメラで実用に耐えられるSFMのコードを探しました.いくつか候補はあったのですが,コードがメンテされているとのことで,下記のサイトを参考にして OpenMVG を題材に今後の作業を進めていくことにしました.

画像から3次元形状を復元!OpenMVGでSfMを試してみた - 株式会社CFlatの明後日スタイルのブログ

0. 目論見

今年のつくばチャレンジでは,SFM (Structure From Motion) とMVS (Multi View Stereo) の技術を自律走行に生かせないかなあと思っています.具体的には,
1. つくばチャレンジのコースを一眼レフカメラでいっぱい撮影して三次元マップをオフライン生成.
2. オフライン生成したマップ情報を元に,ロボットのカメラ(低解像度)で撮影した画像を合わせこみ.オンラインで自己位置推定.
という感じで,攻めたいと思っています.が,いまやっていることより難易度が上がるので,頭がついて行けばいいのですが,,,

1. コードのダウンロード

落としてきたコードは下記のものです.どちらのコードも整理されていますが,結構大きい&難しいことをやっているので,中身を理解するまでには時間が掛かりそうですが,,

OpenMVG

github.com

OpenMVS

github.com

Eigen-3.2.10

http://bitbucket.org/eigen/eigen/get/3.2.10.zip
※Eigenのバージョンは3.2.xでないとダメです.3.3.xだと,OpenMVSのメッシュ化のところでこけます.

VCGLib

github.com

Ceres

github.com

2. コードのビルド

コードのビルドは下記の要領でできました.
(フォルダはホームフォルダから始める前提で書いてます.)

2-0 必要モジュールのインストール

(ちなみに,自分はROS Kineticを入れているので,ROSを入れてない人は他にもいくらかインストールしないと行けないかもしれません.)

cd
sudo apt-get install libpng-dev libjpeg-dev
sudo apt-get install libcgal-dev libcgal-qt5-dev
sudo apt-get install meshlab
sudo apt-get -y install freeglut3-dev libglew-dev libglfw3-dev

2-1. OpenMVG のビルド

OpenMVGは割とストレートにビルド完了まで行きました.

cd
mkdir ~/workspace/reps/openmvg ~/workspace/reps/openmvg/build ~/workspace/reps/openmvg/install
git clone https://github.com/openMVG/openMVG ~/workspace/reps/openmvg/dist
cd ~/workspace/reps/openmvg/dist
git submodule update -i
cd ~/workspace/reps/openmvg/build
cmake -DCMAKE_INSTALL_PREFIX=~/workspace/reps/openmvg/install ../dist/src/
make install -j8

3. OpenMVS のビルド

3-1 Eigen のビルド
cd
hg clone https://bitbucket.org/eigen/eigen#3.2.10 workspace/reps/eigen-3.2.10/dist
mkdir workspace/reps/eigen-3.2.10/build workspace/reps/eigen-3.2.10/install
cd workspace/reps/eigen-3.2.10/build
cmake -DCMAKE_INSTALL_PREFIX=~/workspace/reps/eigen-3.2.10/install/ ../dist/
make install

ここからはちょっと正しいかどうか怪しいのですが,Eigenの3.2.x系にEigen3Config.cmakeファイルがなかったので,Eigenの3.3.4をmake install した時に生成されるshare/eigen3のフォルダをコピーしてeigen-3.2.10/install/shareに持ってきました.つまり,,,

cd
cp -r ~/workspace/reps/eigen-3.3.4/install/share/ ~/workspace/reps/eigen-3.2.10/install/

で,このままだとcmakeに認識されるバージョン情報が違ってしまうので,下記の変更を実施しました.

Eigen3Config.cmake

Before

set (EIGEN3_FOUND 1)
set (EIGEN3_USE_FILE    "${CMAKE_CURRENT_LIST_DIR}/UseEigen3.cmake")

set (EIGEN3_DEFINITIONS  "")
set (EIGEN3_INCLUDE_DIR  "${PACKAGE_PREFIX_DIR}/include/eigen3")
set (EIGEN3_INCLUDE_DIRS "${PACKAGE_PREFIX_DIR}/include/eigen3")
set (EIGEN3_ROOT_DIR     "${PACKAGE_PREFIX_DIR}")

set (EIGEN3_VERSION_STRING "3.3.4")
set (EIGEN3_VERSION_MAJOR  "3")
set (EIGEN3_VERSION_MINOR  "3")
set (EIGEN3_VERSION_PATCH  "4")

After

set (EIGEN3_FOUND 1)
set (EIGEN3_USE_FILE    "${CMAKE_CURRENT_LIST_DIR}/UseEigen3.cmake")

set (EIGEN3_DEFINITIONS  "")
set (EIGEN3_INCLUDE_DIR  "${PACKAGE_PREFIX_DIR}/include/eigen3")
set (EIGEN3_INCLUDE_DIRS "${PACKAGE_PREFIX_DIR}/include/eigen3")
set (EIGEN3_ROOT_DIR     "${PACKAGE_PREFIX_DIR}")

set (EIGEN3_VERSION_STRING "3.2.10")
set (EIGEN3_VERSION "3.2.10")
set (EIGEN3_VERSION_MAJOR  "3")
set (EIGEN3_VERSION_MINOR  "2")
set (EIGEN3_VERSION_PATCH  "10")

set (EIGEN_FOUND ${EIGEN3_FOUND})
set (EIGEN_USE_FILE    ${EIGEN3_USE_FILE})

set (EIGEN_DEFINITIONS  ${EIGEN3_DEFINITIONS})
set (EIGEN_INCLUDE_DIR  ${EIGEN3_INCLUDE_DIR})
set (EIGEN_INCLUDE_DIRS ${EIGEN3_INCLUDE_DIRS})
set (EIGEN_ROOT_DIR     ${EIGEN3_ROOT_DIR})

set (EIGEN_VERSION_STRING ${EIGEN3_VERSION_STRING})
set (EIGEN_VERSION ${EIGEN3_VERSION})
set (EIGEN_VERSION_MAJOR  ${EIGEN3_VERSION_MAJOR})
set (EIGEN_VERSION_MINOR  ${EIGEN3_VERSION_MINOR})
set (EIGEN_VERSION_PATCH  ${EIGEN3_VERSION_PATCH})
Eigen3ConfigVersion.cmake

Before

set(PACKAGE_VERSION "3.3.4")

if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
  set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()

  if("3.3.4" MATCHES "^([0-9]+)\\.")
    set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}")
  else()
    set(CVF_VERSION_MAJOR "3.3.4")
  endif()

After

set(PACKAGE_VERSION "3.2.10")

if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
  set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()

  if("3.2.10" MATCHES "^([0-9]+)\\.")
    set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}")
  else()
    set(CVF_VERSION_MAJOR "3.2.10")
  endif()
3-2 VCG のビルド

こいつはCMake&ビルド不要です.

cd
git clone https://github.com/cnr-isti-vclab/vcglib.git ~/workspace/reps/vcg
3-3 Ceres Solver のビルド
cd
git clone https://github.com/ceres-solver/ceres-solver.git ~/workspace/reps/ceres/dist
mkdir ~/workspace/reps/ceres/build ~/workspace/reps/ceres/install
cd ~/workspace/reps/ceres/build

で,せっかくEigenをインストールしたので,Ceresが参照するEigenのバージョンも下記のように変更してあげます.
変更する箇所は,ceres/dist/CMakeLists.txt以下の下記の部分です.
Before

find_package(Eigen REQUIRED)

After

set(Eigen3_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../eigen-3.2.10/install/share/eigen3/cmake")
find_package(Eigen3 REQUIRED CONFIG PATHS ${Eigen3_DIR} NO_DEFAULT_PATH)

そしてビルドします.

cmake -DCMAKE_INSTALL_PREFIX=~/workspace/reps/ceres/install/ -DMINIGLOG=ON -DBUILD_TESTING=OFF -DBUILD_EXAMPLES=ON ../dist/
make install -j8
3-4 OpenMVSのビルド

ここまでくれば,ようやくOpenMVSのビルドです.

cd
git clone https://github.com/cdcseacave/openMVS ~/workspace/reps/openmvs/dist
mkdir ~/workspace/reps/openmvs/build ~/workspace/reps/openmvs/install

で,同じくCMakeLists.txtを変更してやる必要があります.
一つ目のCMakeLists.txtは~/workspace/reps/openmvs/dist/CMakeLists.txtです.変更内容はCeresの時と同じで,自分のローカルでビルドしたEigenとOpenCVを使うように設定します.

openmvs/dist/CMakeLists.txt

Before

FIND_PACKAGE(Eigen ${SYSTEM_PACKAGE_REQUIRED})
if(EIGEN_FOUND)
       INCLUDE_DIRECTORIES(${EIGEN_INCLUDE_DIRS})
        ADD_DEFINITIONS(${EIGEN_DEFINITIONS} -D_USE_EIGEN)
        SET(_USE_EIGEN TRUE)
 endif()
 
FIND_PACKAGE(OpenCV ${SYSTEM_PACKAGE_REQUIRED})

After

SET(Eigen3_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../eigen-3.2.10/install/share/eigen3/cmake")
FIND_PACKAGE(Eigen3 ${SYSTEM_PACKAGE_REQUIRED} CONFIG PATHS Eigen3_DIR NO_DEFAULT_PATH)
if(EIGEN3_FOUND)
       INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIRS})
        ADD_DEFINITIONS(${EIGEN_DEFINITIONS} -D_USE_EIGEN)
        SET(_USE_EIGEN TRUE)
 endif()
 
SET(OpenCV_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../opencv-3.1.0/install/share/OpenCV")
FIND_PACKAGE(OpenCV ${SYSTEM_PACKAGE_REQUIRED} CONFIG PATHS ${OpenCV_DIR} NO_DEFAULT_PATH)

二つ目ののCMakeLists.txtは~/workspace/reps/openmvs/dist/libs/MVS/CMakeLists.txtです.gitからダウンロードした VCG と Ceres のパス設定をします.

dist/libs/MVS/CMakeLists.txt

VCG,Ceresのパス設定.
Before

FIND_PACKAGE(VCG ${SYSTEM_PACKAGE_REQUIRED})
if(VCG_FOUND)
       include_directories(${VCG_INCLUDE_DIRS})
       add_definitions(${VCG_DEFINITIONS})
endif()
 
FIND_PACKAGE(CERES ${SYSTEM_PACKAGE_REQUIRED})
 if(CERES_FOUND)
        include_directories(${CERES_INCLUDE_DIRS})
        add_definitions(${CERES_DEFINITIONS})

After

SET(VCG_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/../../../../vcg/")
include_directories(${VCG_INCLUDE_DIRS})
add_definitions(${VCG_DEFINITIONS})
 
SET(CERES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../ceres/install/lib/cmake/Ceres")
FIND_PACKAGE(Ceres ${SYSTEM_PACKAGE_REQUIRED} CONFIG PATHS ${CERES_DIR} NO_DEFAULT_PATH)
 if(CERES_FOUND)
        include_directories(${CERES_INCLUDE_DIRS})
        add_definitions(${CERES_DEFINITIONS})

あと,Ceres-Solverのリンクディレクトリ周りも少し修正が必要でした.
Before

TARGET_LINK_LIBRARIES(MVS Common Math IO ${CERES_LIBS} ${CGAL_LIBS} ${CUDA_CUDA_LIBRARY})

After

LINK_DIRECTORIES("${CERES_DIR}/../../")
TARGET_LINK_LIBRARIES(MVS Common Math IO ceres ${CGAL_LIBS} ${CUDA_CUDA_LIBRARY})

で,ビルドが通ります.

cd
cd ~/workspace/reps/openmvs/build
cmake -DCMAKE_INSTALL_PREFIX=~/workspace/reps/openmvs/install ../dist/
make install -j8

ふーーーー.記事にまとめようとすると,時間かかりますね...次は実際に自分の一眼レフでとった写真を復元します.