Open3DのAzure Kinectのサンプルを動かし,簡易的な3D reconstrucionをするまで

こんにちは。ume-boshiです。

最近、研究室でAzure Kinectが一般販売され始めたことを情報シェアしたら、1つ返事で即座に買ってもらえました。恐るべしNAISTパワー。

始めは使う予定はなかったのですが、研究で使いそうなので環境構築してサンプルを動作させるまでたどり着きました。今回はその過程でサンプルが動作するまでの環境を構築し、簡易的に3D reconstructionを行いましたのでそれについて走り書きします。

https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RWsCgp?ver=3b47&q=90&m=6&h=600&w=1200&b=%23FFFFFFFF&f=jpg&o=f&aim=true オシャレだけど、ちょっとでかい。

開発環境

Windowsで実行した場合、後に説明するazure_kinect_mkv_reader.pyが正常に動作しませんでした。SDKのissueを見漁っていてもwindows環境でその問題を解決した人はいなさそうでした。そのため、いつまでも使用されずに研究室に放置されていたPCを借りてubuntu環境で構築してみました。

pip3やgitやcmakeなど、基本的なアプリケーションは既にapt installしてあるとします。

ubuntu WSL 18.04のほうでも環境構築して動くかを調査しましたが、WSLではKinectのようなUSBデバイスを認識できないため使用できませんでした。

Open3D

Pythonスクリプトを動作させるだけであれば、クローンしてくるだけで問題ないはずです。一部サンプルを実行したい場合はビルドをする必要があります(僕は何も考えず悶絶しながらbuildしましたが)。

Open3Dの環境構築手順は下記のとおりです。


1.cmakeのバージョンを上げる
cmakeはこちらのページから最新版を見つけてリンクをコピーしてきます(現バージョンの最新版は3.19.0)。パスの指定については各個人のビルド先になるので、適宜変更してください。

sudo apt purge cmake
sudo apt install -y libssl-dev
wget https://github.com/Kitware/CMake/releases/download/v3.19.0/cmake-3.19.0.tar.gz
tar xvf cmake-3.19.0.tar.gz
cd ./cmake-3.19.0
./bootstrap
make 
sudo make install

export PATH=$HOME/Open3D/build/bin:$PATH
export LD_LIBRARY_PATH=$HOME/Open3D/build/lib/:$LD_LIBRARY_PATH


2.GitHubからcloneする

git clone --recursive https://github.com/intel-isl/Open3D.git
cd Open3D
git submodule update --init --recursive

また、ubuntuの場合は ↓ を実行する必要があります。

~/Open3D/util/install_deps_ubuntu.sh


3.Pythonで動作するようにパッケージ取得
Pythonスクリプトを動作させるために、pipでパッケージを取得する必要もあります。

pip install open3D==0.10.0

※open3Dのバージョンが0.11.0だと、サンプルが正常に動作しませんでした。
※condaを使っている人は、open3dの他にopen3d-adminが必要だった気がします。


4.Open3Dをビルドする(c++で動作したい人向け?)

mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=.. .. 
make -j$(nproc)
sudo make install
make install-pip-package

python3 -c "import open3d"

最後の行で、何もエラーが出なければビルド成功です。

※INSTALL_PREFIXには、open3d_install_directoryを指定します。


Azure Kinect Sensors SDK

公式的に、Azure Kinectは「k4a」と略称するようです。そのため、ビューワやレコーダは「k4aviewer」や「k4arecorder」というような実行ファイル名となっています。
Azure Kinect Sensors SDKは、.soという動的ライブラリを生成するために(windowsでいう.dllファイル)ビルドをする必要があります。

Azure Kinect Sensors SDKの環境構築手順は下記のとおりです。


1.GitHubからcloneする

git clone https://github.com/microsoft/Azure-Kinect-Sensor-SDK.git
cd ./Azure-Kinect-Sensor-SDK


2.ビルドする

sudo apt install -y libsoundio-dev

mkdir build && cd build
cmake .. -GNinja
ninja
ninja install

このビルドの際、libusb関連のエラーが出ることがあります。その場合は次のようにして対応できる可能性があります。ちなみに、ninjaはmakeよりも実行が速いらしい。

  • sudo apt-get install libusb-1.0-0-devを実行し、libusbを入れる。
  • vim等を用いて、~/Azure-Kinect-Sensor-SDK/extern/libuvc/src/include/libuvc/libuvc-internal.h の"#include <libusb.h>"を"#include <libusb-1.0/libusb.h>"に書き換える
  • 再度ninjaから実行


3.パスを設定する
ビルドで生成されたbinディレクトリ内に、.soという動的ライブラリが生成されています。これにどこからでもアクセスできるようにパスを設定します。下記のどちらかを行なうだけでいいかもです(詳しくない)。

  • sudo vim /etc/ld.so.conf.d/libc.confを実行し、「~/Azure-Kinect-Sensor-SDK/build/bin」を追記する。
  • export LD_LIBRARY_PATH=$HOME//Azure-Kinect-Sensor-SDK/build/bin/:$LD_LIBRARY_PATHでパスを追加する


Depth Engineの.soファイルを設定

k4aのreaderを実行するためには、libdepthengine.so.2.0 という動的ライブラリをDLし、パスを通す必要があります。


また、Azure Kinectのruleファイルをシステム側にコピーする必要があります。

cp ~/Azure-Kinect-Sensors-SDK/scripts/99-k4a.rules /etc/udev/rules.d


Azure Kinectのサンプルで動作確認

↓ のディレクトリにAzure Kinect用のサンプルスクリプトが3つ存在しています。

~/Open3D/example/python/reconstruction-system/sensors/

  • azure_kinect_viewer.py → Azure kinectから映像を取得し、カラーとDepthイメージを表示
  • azure_kinect_recorder.py → viewerに加え、「space/esc」の押下で録画を開始/終了できる
  • azure_kinect_mkv_reader.py → recorder.pyで保存された.MKVファイルを見る + 1フレームごとに画像を分割できる


ex) すでにrecordした映像「movie.mkv」を、存在していないimagesディレクトリに出力 python3 azure_kinect_mkv_reader.py --input movie.mkv --output ./images

→ ./images/color や ./images/depth や、config.jsonなどが出力される

コントローラの形状をreconstructしたい

何の研究をしているんだと思うかもしれませんが、研究課程でDualShockのコントローラのモデルを取得したいなと考えていました。結果的には良い出来ではないですが、部屋などを取得したい人には役に立つ情報だと思います。

では、reconstrucionの手順を説明します。


1.recorderで物体の周囲から映像を取得する
python3 azure_kinect_recorder.pyを実行し、物体の周りを歩き回って動画を撮影します。この際に、足やコードが映像に入らないように、なおかつ、ケーブルの長さ制限にも気を付けましょう。

↓ これが私がrecordした映像の例です。

youtu.be


2.取得した映像の各フレームからJPG画像を出力
python3 azure_kinect_mkv_reader.py --input ほげほげ.mkv --output ./imagesというように実行し、映像をフレーム枚の画像に変換します。

↓ が出力画像例です。depthは色が薄いですね。

1枚目:カラー画像、2枚目:depth画像(jpg)

3.config.jsonの内容を変更
mkv.reader.pyの実行で生成されたconfig.jsonファイルをvim等で編集します。
編集内容は、"icp_method": "color",という箇所を"icp_method": "point_to_plane",に変更することです。

この変更をしない場合、5手順目の--refineオプションでの実行時に、正しく動作しませんでした。


4.Pythonスクリプトの書き換え "~/Open3D/example/python/reconstruction-system/"にあるpythonスクリプトを少し書き換えます。具体的には、o3d.pipelines.となっている箇所をすべてo3d.に短くします。
Open3Dのバージョン違いで書き換えの必要性がなくなるかもしれないので、一度次の手順を行なってから行なうのでも構いません。


5.run_system.pyを実行しまくる "~/Open3D/example/python/reconstruction-system/"にあるrun_system.pyを実行します。実行するのは4回であり、それぞれ mkv_reader.pyで出力されたディレクトリ内のconfigを引数として、別々のオプションを付けています。

python3 run_system.py ./sensors/images/config.json --make
python3 run_system.py ./sensors/images/config.json --register
python3 run_system.py ./sensors/images/config.json --refine
python3 run_system.py ./sensors/images/config.json --integrate

行なっている内容は、下記の模様です。
①画像からいくつかのフラグメントを生成(config.jsonがあるディレクトリに./fragmentディレクトリが出来ており、そこに.plyファイルが新しく存在)
②③平面を綺麗に合わせる段階?あまりよくわかっていません
④複数のfragmentを統合し、実際に1つの.ply形式として出力(./sceneディレクトリが出来ている)


6.見る!
やっと出力できました! が、あまりきれいではないですね。

f:id:ume-boshi:20201120183416p:plainf:id:ume-boshi:20201120183418p:plain
重要なコントローラは取れてねぇ。。。


精度が微妙な理由には、次の可能性があると考えています。

  • コントローラの色や光沢が測距に影響
  • 映像撮影時の手振れが影響
  • 撮影が近距離過ぎた
  • 第5手順の--refineがうまくいっていない(point_to_planeよりもcolorのほうが高精度?)


おわりに

物体のモデリングに使うのではなく、周囲環境を取る場合は、綺麗にできると思います。なんにしろ、環境構築さえできれば簡単にモデル化できるのはとても便利ですね!

f:id:ume-boshi:20201120165853p:plain
こいつは失敗作だ


最近忙しく、あまり記事を投稿できてません。。。ただ、気まぐれでQiitaのカレンダー企画?に参加してみるので、12月中旬にはまた別の1作品をお見せできると思います。