2016年8月5日金曜日

PCLとかC++で作ったコードをPythonから使いたい!


概要
完全分散処理のフレームワークとしてSparkがある.このSparkが対応している言語として
  • Java
  • Python
  • Scala
が挙げられる.そう,C++には対応していないのである.
例えばPythonで記述し,PCLを使いたい!
といった場合,一応PythonにもPCLがありpcdファイルを読み込んだりちょっとした処理ならできる.
しかし

PCL_visualizerが使えないΣ(|||▽||| )


↑こんなことがしたいのに,PythonPCLでは使えません.
3Dvisualizerといえば,かろうじてpyplotぐらいに思う.

どうにかしてVisualizeしたい!
と思い,行き着いたのがPython用のC++ラッパーを作ること.
ラッパーを作ればPythonからC++のPCLを使えるのではないかと奮闘した記録です.

※ちなみに,ラッパーを作るとはライブラリを作るようなイメージで,C++で作った関数等をPython用のライブラリとして生成できます.

環境
Ubuntu 14.04
Python 2.7
PCL 1.7

方法
ラッパーの作り方はいくつかあるらしいが,今回はboost::pythonを用いる.
↓ソースコード
#include <string>
#include <iostream>
#include <boost/python.hpp>

using namespace std;

std::string hello (std::string s){
  cout << "hello" << endl;
  return "Hello, " + s;
}

int plus_(int n){
  return n + n;
}

const char* yeah(){
  return "yeah!";
}

BOOST_PYTHON_MODULE (test)
{
  boost::python::def( "hello", hello );
  boost::python::def( "plus", plus_ );
  boost::python::def( "yeah", yeah );
}
これをtest.cppとして保存する.

コンパイル
このコードをコンパイルする方法は3つある.
  • 端末による操作
  • CMake
  • Makefile
多くのサイトでは,端末にコマンドを打ってコンパイルする方法がよく見受けられる.
今回は,上2つの方法を紹介する.

コマンドによる方法


pythonのバージョンやディレクトリが異なる場合は適宜-Iのところを修正する.

CMake


これを,CMakeLists.txtとしてtest.cppと同じディレクトリに保存する.



上記の2つの方法により,test.soというファイルが生成される.
このファイルがpythonが読み込めるライブラリとして機能する.

使い方
シェルを用いた簡単な使い方をご紹介
test.soと同じディレクトリで

これで動作の確認ができたので,あとはこのディレクトリにパスを通せばpythonのコードからも使えるようになる.

本題のPCL
では,これらをもとにpythonからpcl visualizerを使ってみる.

cube.pcd

コンパイル
ここでは,CMakeを使うことにする.なぜなら,コマンドによるPCLのリンクの仕方とかよくわからないから←
それに,CMakeのほうがファイルやライブラリを追加したいときにCMakeLists,txtをちょっと書き加えるだけだから.



表示できました.

今後の展望
次は,Eclipseで使えるようにパスを通したり,Eclipse上でラッパーを生成できたらいいなと.

トラブルシューティング


  1. よくこんなエラーが出ることがある.
    このエラーの原因はいろいろあって,特定することが難しいが,一例を示す.
    • pythonのパスがおかしい
    • BOOST_PYTHON_MODULE()のカッコ内の文字とcppファイルの名前が一致していない.
      例えば,BOOST_PYTHON_MODULE(test)とtest.cppのように一致している必要があるっぽい
    • Boostライブラリの競合によるエラー
      CMakeLists.txtに記述する際,find_packageにBoost,PythonLibs,PCLと指定しているが,PCLもBoostライブラリを持っており,通常のBoostライブラリを上書きしてしまうために起こるエラーらしい.参考
      よって,find_packageする順番を変えることで解決できる.

  2. 生成されたsoファイルの接頭にlibが付いている場合
    例えば,test.soを作ったつもりが,libtest.soというファイルが生成されることがある.
    このままimportすると

    というエラーが出る.こういう時は,生成されたlibtest.soのファイル名を変更してtest.soにすればうまくimportできる.
    しかし,いちいちファイル名を変更するはめんどくさいので,CMakeLists.txtに

    を加えることでlibのついていないsoファイルを生成できる.

  3. PCLのパスの問題

    ほかのPCLのヘッダは通ったのに,pcl_visualizer.hだけがないと言われました.
    cmakeした時のログを見てみると,

    どうやらapt-getで入れたpclではなく,anaconda2に入っているpclを参照しているようです.
    そして,anaconda2のpclはvisualizerが入ってないんですね.
    ということでapt-getで入れたlibpclを参照するようにCMakeLists.txtを変更します.

    これで,/usr/includeにあるpclを参照してくれるようになり,無事コンパイルが通ります.


















0 件のコメント :

コメントを投稿