スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Super4PCS

PCLで検索してたらSuper4PCSというRegistrationライブラリが良いという噂を見つけたので試してみたのですが、これがまあ大変苦労しました。

こちらのサイトを参考に、まずはGitHubからソースコードをダウンロードします。Super4PCSをビルドするにはEigenANNOpenCVCFITSIOBoostといったライブラリが必要となります。既にEigen v3.2.4、OpenCV v2.4.8、Boost v1.57を持ってたので、新たに必要なのはANNとCFITSIO。


ANNはv1.1.2のソースコードをダウンロードするとVisual Studioのソリューションファイルも含まれているので、Visual Studio 2013用にアップグレードしてビルドします。

CFITSIOはv3.370のソースコードと一緒にupdated CMakeLists.txtを忘れずにダウンロードします。最初updated...に気付かず、ZIPに含まれていたCMakeLists.txtでビルドできなくてかなりの時間を無駄にしてしました。


そしてSuper4PCSのビルド。僕は各ライブラリをビルドした成果物をライブラリ毎にinclude、vc12/bin、vc12/lib、vc12/bin.x64、vc12/lib.x64といったサブフォルダにコピーして使っているのですが、Super4PCSのCMakeはライブラリのソースコード(に含まれているCMakeのconfigファイル)を探しに行ったりするので、ちょっと注意が必要です。

CMakeで作成したVisual Studio 2013用のソリューションファイルでビルドすると大量のコンパイルエラーが発生しました。Super4PCSのサイトをよく見たらVisual Studioではビルドできないというバグが報告されていました。でもまだ諦めない。

特に目に付いたのは「constexpr」というキーワード前後で発生しているエラー。僕は今まで知らなかったのですが、constexprはC++11で導入された機能なのだそうで、VisualStudio 2013では未対応Visual Studio 2013 Update 5 (2013.5) CTP 3(今はVisual Studio 2013 Update5 RCに差し替えられてます)を当ててみましたが何も変わらず。Visual Studio 2015 CTP 6(今はVisual Studio 2015 RCに差し替えられてます)をインストールして、2013用のソリューション/プロジェクトファイルを2015用にアップグレードしたら何故かプロジェクトのプロパティに「C++」や「リンカー」などの項目が表示されず、コンパイルできるかどうかの確認すらできませんでした。
20150505a


Visual Studio 2013がC++11に対応してないのなら、その部分だけソースを書き換えればいいのではないかと思い、厳密には間違っているんだろうけどコンパイルを通すためにconstexprをconstに置き換えてみましたが、それでもまだまだ意味不明なエラーが発生しました。以下のように対処しましたが、一旦ビルドが通った後に元に戻してもエラーが再現しなかったり、32bitと64bitで振る舞いが違ったりして、正直よくわかりません。

  • matching.ccのextractFilesAndTrFromStandfordConfFile関数内のfilesystem::path(confFilePath).parent_path().native()でnative()ではなくstring()を使う。プロジェクトの文字セットが「マルチバイト文字セットを使用する」に設定されているため。

  • Windowsには存在しないunistd.hをインクルードしないようにする。

  • Windowsには存在しないsys/time.hをこちらを参考に作成する。僕はこのファイルにstruct timezone(メンバー変数はint型)の定義を追加しました。

  • normalHealSet.hに#include <vector>を追加。

  • normalset.hに#incldue <array>と#include <sys/time.h>を追加。

  • 4pcs.ccに#define _USE_MATH_DEFINES、#include <math.h>、#include <sys/time.h>を追加。

  • super4pcs.ccに#include <utility>と#include <algorithm>を追加。

  • bbox.hに#undef minと#undef maxを追加。

  • normalHealSet.cppのIndexedNormalHealSet::getNeighbors()関数内のfor(typename ChealMap::const_iterator it =...でC2899: typename cannot be used outside a template declarationが発生するので、typenameをコメントアウト。

  • super4pcs.ccのMatchSuper4PCSImpl::MeanDistance()、Verify()関数内のtypename Super4PCS::KdTree::Index resId =...でtypenameをコメントアウト。

  • pairCreationFunctor.hのstruct PairCreationFunctor内でtypedef Eigen::Matrix<Scalar, 3, 1> Point;と定義されているのに、テンプレート引数でPairCreationFunctor::Pointが指定されているとC2923: PairCreationFunctor<_Scalar>::Point is not a valid template type argument for parameter 'Point'が発生するので、PairCreationFunctor::Pointの代わりにEigen::Matrix<Scalar, 3, 1>を指定した。

  • 4pcs.ccのvector<pair<Point3D, Point3D>>の「>>」を念のため「> >」と間にスペースを入れた。

  • いくつかのファイルで文法的に間違ってなさそうなのにエラーが消えない場合、「Unicode(UTF-8シグネチャ付き) - コードページ65001」の代わりに「日本語(シフトJIS) - コードページ932」で保存し直したらコンパイルが通るようになりました。

  • intersectionNode.hのNdNode::split関数の最後にあるイテレーターを使った配列内要素の削除のとこでvector iterators incompatibleが発生するので、イテレーターではなくインデックス(添字)で配列にアクセスするように変更した。

  • super4pcs.ccのbool MatchSuper4PCSImpl::TryOneBase()のtransform_ = transform;付近でアクセス違反が発生するので#define EIGEN_DONT_VECTORIZEを定義してEigenのvectorizationを無効にしました


これでビルドが通ってSuper4PCS.exeが動くようになりましたが、データやパラメータ(引数で与えるdelta)にもよるんだろうけど、物凄く遅い。これはコンパイル時に式を定数に変換するconstexprを使ってないせいかもしれない。でもC++11に対応しているVisual Studio 2015でビルドできないしどうしたものかと思っていたら、Visual C++ Compiler November 2013 CTPを使えば、Visual Studio 2013で完璧ではないもののC++11の機能が使えるようになることが判明したので試してみることにしました。

インストール後、Super4PCSの全てのプロジェクトのプロパティのプラットフォームツールセットをVisual Studio 2013 (v120)からVisual C++ Compiler Nov 2013 CTP (CTP_Nov2013)に変更し、constに変更したソースコードをconstexprに戻してビルドしたら、C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xmemory0の593行でC2280: 'std::pair::pair(const std::pair &)' : attempting to reference a deleted functionが発生しました。deleted functionというのもC++11に関係しているようで、メリットがよくわかりませんが、クラスのメンバー関数の宣言にvoid func() = delete;のように記述することができるようです。ソースコードをみても明示的に関数をdeletedとは指定していないので、Point3DクラスにPoint3D& operator =(const Point3D& p)を追加してみたり、Point3D(Point3D&& other)を追加してみたりしましたが状況は改善せず。&&演算子ってのも何者なんでしょう。参照の参照?と思ったらムーブコンストラクタというそうです。なんだかC++11には知らない機能がたくさん追加されているみたいなのでVisual Studio 2015に移行するまでに勉強しておかなきゃならなそうです。結局、コピーコンストラクタPoint3D(const Point3D& other):をPoint3D(Point3D& other):に変更したら上記エラーは消えました。

次はutils.hのtemplate<bool validate, class ndIndexT, class IndexT, class SizeT> constexpr inline IndexT UnrollIndexLoop関数でC1001: An internal error has occurred in the compiler。同じutil.hにテンプレート引数が異なるtemplate<bool validate, class ndIndexT, class IndexT, class SizeT> constexpr inline IndexT UnrollIndexLoopという関数があるのにそちらは問題がないようです。これは2日くらいかかってようやくnormalHealSet.h内の関数inline int indexCoordinates( const Index3D& coord) const { return Utils::UnrollIndexLoop( coord, 2, _egSize ); }でUnrollIndexLoopに渡しているcoordをIndex3Dでキャストすればエラーが発生しないことがわかりました。このconst絡みのコンパイルエラーってVisual Studio側のバグなんでしょうね。

これでconstexprを使ってビルドした状態で動くようになりましたが、ちっとも速くなったようには感じなかったので、以下の設定で、32bitではなく64bitのReleaseでビルドしました。
最適化実行速度の最大化(/O2)
インライン関数の展開拡張可能な関数すべて(/Ob2)
組み込み関数を使用するはい(/Oi)
速度またはサイズを優先実行速度を優先(/Ot)
プログラム全体の最適化はい(/GL)
関数レベルでリンクするはい(/Gy)
拡張命令セットを有効にするストリーミングSIMD拡張機能2(/arch:SSE2)
ランタイム型情報を有効にするはい(/GR)
コンパイル言語の選択C++コードとしてコンパイル(/TP)



生成されたSuper4PCS.exeで19200頂点を含む2つのplyファイルのregistrationをしてみます。
20150505b20150505c


この2つの点群は以下のようにずれています。
20150505d


これをSuper4PCSでdelta=0.01でregistrationするとこの通り。
20150505e


このデータは先日PCLのICPで試してダメだったものなので、噂どおりSuper4PCSは優秀ということです。しかし遅い。ちゃんと時間を計った訳じゃないけど、完了まで2時間くらいはかかったと思います。このままじゃ実用的じゃないので、特徴点の抽出と対応付けなど、真面目にやる必要がありそうです。あー疲れた。
スポンサーサイト

コメントの投稿

非公開コメント

プロフィール

JVR(自腹)

Author:JVR(自腹)

メールフォーム

名前:
メール:
件名:
本文:

カレンダー
10 | 2017/11 | 12
- - - 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 - -
最新記事
最新コメント
最新トラックバック
カテゴリ
月別アーカイブ
検索フォーム
RSSリンクの表示
QRコード
QR
リンク
ブロとも申請フォーム

この人とブロともになる

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。