3次元画像処理ライブラリ「Open3D」の紹介
いつも読んでいる、「空飛ぶロボットのつくりかた」というブログで、Open3DというIntel製の3次元画像処理のライブラリが紹介されていました。
「Open3D」の公式サイトは以下です。
Open3D
個人的に、3次元画像処理には興味あって、以前Point Cloud Library(以下PCL)を使った、簡単な3次元画像処理を紹介したことがあります(以下記事参照)。
ただ、PCLには以下のような不満がありました。
- C++しか使えない(C++苦手…)
- ちょっとした修正にもいちいちビルドしないといけない
- たくさん行数書く必要がある
Open3Dがつくられたのも、上記のような不満を解消するのが目標だったようで、Open3Dを紹介する論文によると、Open3DのPCLに比べた利点は以下とのことです。
- Pythonが使える
- 少ない行数でかける(PCLの1/5とのこと)
- Jupyter Notebookでデバッグできる
そしてPCLはかなりディスられてました。よっぽど嫌な思いをしたのでしょう(PCLに親を殺されたとか)。
Open3DはROSと連携させると良さそう
Open3D、ちょっと触ってみて。確かにPythonでサクサク書けるのは便利で、プロトタイピング(試行錯誤)には使いやすそうだなと感じました。
ただ、3次元画像処理って自分としては3次元センサと組み合わせてリアルタイムで処理したいのですよね。PCLの場合は、ROS(Robot Operation System)と組み合わせることで、ROSに対応した多種多様な3次元センサと、ROSの強力な可視化機能(Rviz)やログ機能(rosbag)が使えたのが非常に便利でした。
Open3Dは、自分が調べた感じROSには対応していなさそうでした。「対応していないのだったら、自分でROSに対応させちゃえ!」ということで、「open3d_ros」というOpen3DとROSを連携させるちょっとしたツールを作ってみました。
この記事では、「open3d_ros」の使い方と、どんなことができるかを簡単に紹介いたします。
「open3d_ros」によるOpen3DとROS連携のセットアップ方法
Open3DとROSを連携させるためのセットアップ手順を説明していきます。ここからの想定は、ネイティブのLinux(Ubuntu 16.04)がインストールされたPC、もしくは仮想環境上でのLinux環境を想定しています。
Macの仮想環境(Parallels Desktop Lite)に関しては以下記事参照下さい。WindowsでもVirtual Boxなどの環境で同様にできると思います(未確認)。
仮想環境上で、Open3Dのビルドに失敗する場合は、仮想環境のメモリ設定を最大限確保し、何度かビルドをしてみて下さい。
ROSと3次元センサのセットアップ
ROSと3次元センサのセットアップに関しては、以下記事参照下さい。
3次元センサはKinectを想定していますが、もし3Dセンサを持っていなくても、ログデータ(rosbag)で試すことできますので、Kinectのセットアップをスキップして次に進んで下さい。
Open3Dインストール
Open3Dのインストールは、公式サイトのドキュメントとこちらの記事に従いました。具体的にはLinux(Ubuntu)のターミナル上で以下コマンドを実行します。
$ git clone https://github.com/IntelVCL/Open3D $ cd Open3D $ ./scripts/install-deps-ubuntu.sh $ mkdir build && cd build $ cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python ../src $ make -j
参考までに、以下コマンド実行すれば、ネイティブのMacにインストールすることもできました。ネイティブのMacにROSを入れるのは至難の技ですが…
$ git clone https://github.com/IntelVCL/Open3D $ cd Open3D $ ./scripts/install-deps-osx.sh $ mkdir build && cd build $ cmake ../src $ make -j
これで py3d が Open3d/build/lib/
以下に生成されるのですが、このままだと py3d をimport するのに Open3d/build/lib/
に移動したり、パスを指定しないといけないので不便です。
以下で Pythonのパスが通っているディレクトリが分かるので、 py3dをコピーしてやり、簡単にインポートできるようにしましょう。
$ python >> import sys >> sys.path
Ubuntuの場合は、/usr/lib/python2.7/dist-packages/
だったので以下のようにコピーしました。
$ sudo cp lib/py3d.so /usr/lib/python2.7/dist-packages/
ネイティブのMacの場合は、pyenvを使っていたので/Users/denso/.pyenv/versions/anaconda3-4.4.0/envs/ml/lib/
となり、以下のようにコピーしました。
$ sudo cp lib/py3d.cpython-36m-darwin.so /Users/denso/.pyenv/versions/anaconda3-4.4.0/envs/ml/lib/
ここらへんは、ご自分の流儀に合わせて適宜変更下さい。pipで一発で入ってくると嬉しいのですけどね。
これ以降の内容は、上記の通りpy3dがパスの通ったディレクトリにコピーしてある前提で説明いたします。
続いて、以下コマンド実行してテストします。
$ cd lib/Tutorial/Basic $ python rgbd_redwood.py
以下のような画像が表示されればOKです。
Open3D+ROS連携
ここからいよいよ「open3d_ros」を使っていきます。ここからは以下のリポジトリを使用します。
あらかじめ、好きな場所に以下のコマンドで「open3d_ros」をcloneしておいて下さい。
$ git clone https://github.com/karaage0703/open3d_ros
次に、ターミナルのウィンドウを4つ立ち上げて、それぞれのターミナルでopen3d_ros
ディレクトリ内で以下コマンドを実行します。
1つ目でroscore立ち上げ
$ roscore
2つ目で、ログデータ(rosbag)再生
$ rosbag play -l rosbag_data/kinect_room.bag
3つ目でOpen3D使用
$ python down_sampling.py input:=/camera/depth_registered/points
4つ目でRviz立ち上げて3次元情報を可視化
$ rosrun rviz rviz -d kinect.rviz
以下のようにRviz上にダウンサンプリングされた点群が表示されます。
ダウンサンプリング前
ちなみに、down_sampling.py
は、以下のような30行にも満たないスクリプトです。面倒臭いROSとの連携部分はutil.py
というファイルに詰め込んでインポートしています(興味ある方はutil.pyの方も見てみて下さい)。
#! /usr/bin/env python import rospy from sensor_msgs.msg import PointCloud2 import util import py3d def down_sampling(pcl_data): downpcd = py3d.voxel_down_sample(pcl_data, voxel_size = 0.05) return downpcd def callback(data): pcl_data = util.convert_pcl(data) result_pcl = down_sampling(pcl_data) util.publish_pointcloud(result_pcl, data) if __name__ == "__main__": rospy.init_node('listener', anonymous=True) rospy.Subscriber('input', PointCloud2, callback) rospy.spin()
上記コードのdown_sampling
という関数を書き換えると、好きなように3次元処理ができます。これみると、なんとなく簡単に3次元画像処理ができそうな気がしてきますね(してきますよね?)。
今回はあらかじめ用意したログデータでテストしましたが、3次元センサを使っても、簡単に同様の画像処理ができます。具体的には、以下記事参考にKinectをセットアップして。
上記のログの再生のコマンドの代わりに以下コマンドを実行するだけです。
$ roslaunch freenect_launch freenect.launch
もちろん、Kinect以外も、ROSに対応している3次元カメラであれば、同じ要領で3次元画像処理が可能です。今だとRealsenseあたりがお手頃でしょうか。これもOpen3Dと同じくIntel製ですね。
まとめ
Open3D+ROS+Pythonで3次元画像処理のプロトタイピングができる「open3d_ros」というツールを自作して紹介しました。「Open3D」Python使えるのは、ビルドしなくてよいし、簡単にかけて良いですね(C++難しい…)。
Pythonで書くときは、Numpyが使えるのも魅力的です。3次元画像処理って、2次元画像処理と基本的な部分は共通するところが多いので、2次元画像と同じ要領で直接画素を弄って好きなフィルタを作ったりできるはずです。2次元画像の例ですが、Numpyで画像処理フィルタを作る方法は下記記事参照ください。
あとは、Pythonなので3次元のディープラーニングというのも中々面白いかもしれませんね。3次元でディープラーニングやっている例って、2次元に比べるとまだまだかなり少ない印象です。私が知っているのは、Appleの自動運転の研究くらいでしょうか(End-to-Endで物体検出しています)。
[1711.06396] VoxelNet: End-to-End Learning for Point Cloud Based 3D Object Detection
Open3Dによって、3次元のディープラーニングの研究も進んで行く可能性あるかもしれませんね。
そして何より、Open3DとROSの強力な可視化ソフトやツール群との組み合わせというのは、なかなかパワフルじゃないかなと思います。これ使って、色々試してみたいなと思います。それこそロボット作ってみたいですね。
参考リンク
Open3Dのお勉強(一回目) - 空飛ぶロボットのつくりかた
ROSのPointCloud2で独自のフィールドを定義 - Yura YuLife