前回の記事で
Jetson TX1にOpenframeworksを動かす環境ができました。どんどん面白い環境ができつつありますが、今回はZedステレオカメラを動かしてみます。この種のステレオカメラとしては、昨今話題になっているIntelのリアルセンスカメラが存在します。これはKinectと同じように赤外線センサーで距離を認識するようなので、対象物が周囲と同じ温度になると「多分」距離を認識しなくなります。つまり、炎天下など、外部ではあまり役に立たないことになります。今回のZedステレオカメラは光学式なので、内外部共、周囲の温度の影響は受けませんが、暗闇では当然使い物になりません。両者とも一長一短。せっかくTX1とZEDを持ってるので、認識画像範囲の任意の点で、カメラからの距離を表示させるプログラムをOpenframeworksを使って作って見ました。
※TX1には通常Openframeworksはインストールできません。インストールするには手順が必要です。今まで成功した方はいないと思いますので、最短で実行したい場合は前回の記事を参考に!!
今回の機器構成
中央付近をマウスで指定してカメラからの距離を表示させているところ(赤い点と緑の距離)。720pで11fpsくらいです。VGA(672x376)に落とすと18fpsくらいにスピードが上がるので、今回の目標ほぼ達成。
実際に距離を認識している動画。これはカメラ解像度が720p(1080x720)で距離を測定してます。カメラからの距離を確実に判別しているのがわかると思います。
このZED、基本は2つのカメラを同時に動かして、左右画像を1つの画面に合成して出力しているだけなんです。OpenCVでもステレオカメラで画像深度を測定する例題があります。どうやらフォローするソフトが要なんですね。実行ライブラリはZED SDKをダウンロードすることで手に入りますが、ソースは公開していないようです。まー当然と言えば当然でしょうけど。
ここの会社が公開しているサンプルとライブラリは、前にも紹介したように、なかなかなんですが、これをOpenframeworksに移植した熱意のある人がいます。「OfxkuZed」。https://github.com/kuflex/ofxKuZed
でも、このaddonは、Windows環境のOpenframeworksしかサポートしていません。Linuxの場合は自分でやってくださいですって。仕方ないので挑戦して見ました。結果的にリンクファイルオプションをどう追加するかだけの問題でした。
まずZED SDKをダウンロードして、Examplesをビルドします。前バージョンではうまくコンパイルできなかったのですが、V1.2.0になってうまく行くようになりました。で、サンプルの中から、/usr/local/zed/sample/gpu/ogl-->の中にあるどちらかをコンパイルします(mkdir build --> cd build --> cmake .. --> makeの順で実行)。ビルドが成功したら(ここではopenGL_gpu_interropでコンパイルした場合)、
/usr/local/zed/sample/gpu/ogl/openGL_gpu_interrop/build/CMakeFiles/ZED_openGL_gpu_interop.dir/link.txtファイル(まさに自分の環境に合ったリンクオプション!!)が、作成されるので、このデータをOpenframeworks環境のプロジェクトフォルダに入っているconfig,makeの中に追加してやります。この方法を使うと、自分の環境によってリンクファイルが自動でカスタマイズされるので超簡単。この前のOpenframeworksのインストールと同じように、真面目に働いているスクリプトが作り出すデータをぶんどっちゃおうという安易な発想です。
試しにOfxkuZedのお試しサンプルzedExampleの中に入っているconfig.makeを以下に修正。中間付近の PROJECT_LDFLAGS= 以降が該当リンク部分です。多分このままでコンパイルできますが、できない場合は上記ZED SDKのexampleをコンパイルしてlink.txtの中身をコピーして見てください。一応変更したaddonと今回試して見た距離測定プログラムをダウンロード可能にしときます。一今後ZEDを使ったアプリを作成する場合は、このフォルダ(zedExample)をコピーすればOK。
以下OfxkuZed-->zedExample-->config.make の中身
赤文字部分を追加する。
################################################################################
# CONFIGURE PROJECT MAKEFILE (optional)
# This file is where we make project specific configurations.
################################################################################
################################################################################
# OF ROOT
# The location of your root openFrameworks installation
# (default) OF_ROOT = ../../..
################################################################################
# OF_ROOT = ../../..
################################################################################
# PROJECT ROOT
# The location of the project - a starting place for searching for files
# (default) PROJECT_ROOT = . (this directory)
#
################################################################################
# PROJECT_ROOT = .
################################################################################
# PROJECT SPECIFIC CHECKS
# This is a project defined section to create internal makefile flags to
# conditionally enable or disable the addition of various features within
# this makefile. For instance, if you want to make changes based on whether
# GTK is installed, one might test that here and create a variable to check.
################################################################################
# None
################################################################################
# PROJECT EXTERNAL SOURCE PATHS
# These are fully qualified paths that are not within the PROJECT_ROOT folder.
# Like source folders in the PROJECT_ROOT, these paths are subject to
# exlclusion via the PROJECT_EXLCUSIONS list.
#
# (default) PROJECT_EXTERNAL_SOURCE_PATHS = (blank)
#
# Note: Leave a leading space when adding list items with the += operator
################################################################################
# PROJECT_EXTERNAL_SOURCE_PATHS =
################################################################################
# PROJECT EXCLUSIONS
# These makefiles assume that all folders in your current project directory
# and any listed in the PROJECT_EXTERNAL_SOURCH_PATHS are are valid locations
# to look for source code. The any folders or files that match any of the
# items in the PROJECT_EXCLUSIONS list below will be ignored.
#
# Each item in the PROJECT_EXCLUSIONS list will be treated as a complete
# string unless teh user adds a wildcard (%) operator to match subdirectories.
# GNU make only allows one wildcard for matching. The second wildcard (%) is
# treated literally.
#
# (default) PROJECT_EXCLUSIONS = (blank)
#
# Will automatically exclude the following:
#
# $(PROJECT_ROOT)/bin%
# $(PROJECT_ROOT)/obj%
# $(PROJECT_ROOT)/%.xcodeproj
#
# Note: Leave a leading space when adding list items with the += operator
################################################################################
# PROJECT_EXCLUSIONS =
################################################################################
# PROJECT LINKER FLAGS
# These flags will be sent to the linker when compiling the executable.
#
# (default) PROJECT_LDFLAGS = -Wl,-rpath=./libs
#
# Note: Leave a leading space when adding list items with the += operator
#
# Currently, shared libraries that are needed are copied to the
# $(PROJECT_ROOT)/bin/libs directory. The following LDFLAGS tell the linker to
# add a runtime path to search for those shared libraries, since they aren't
# incorporated directly into the final executable application binary.
################################################################################
# PROJECT_LDFLAGS=-Wl,-rpath=./libs
PROJECT_LDFLAGS=-L/usr/lib/aarch64-linux-gnu/tegra -L/usr/local/zed/lib -L/usr/local/cuda-8.0/lib64 -L/usr/local/lib -rdynamic /usr/local/zed/lib/libsl_zed.so /usr/local/zed/lib/libsl_depthcore.so /usr/local/zed/lib/libsl_calibration.so /usr/local/zed/lib/libsl_tracking.so /usr/local/zed/lib/libsl_disparityFusion.so /usr/local/zed/lib/libsl_svorw.so /usr/local/zed/lib/libcudpp.so /usr/local/zed/lib/libcudpp_hash.so -lX11 -lpthread -lGLEW -lGLU -lGL /usr/local/lib/libopencv_videostab.so.2.4.13 /usr/local/lib/libopencv_ts.a /usr/local/lib/libopencv_superres.so.2.4.13 /usr/local/lib/libopencv_stitching.so.2.4.13 /usr/local/lib/libopencv_contrib.so.2.4.13 -lglut -lXmu -lXi /usr/local/cuda-8.0/lib64/libcudart.so /usr/local/cuda-8.0/lib64/libnppi.so /usr/local/cuda-8.0/lib64/libnpps.so -lGLU -lGL /usr/local/lib/libopencv_nonfree.so.2.4.13 /usr/local/lib/libopencv_ocl.so.2.4.13 /usr/local/lib/libopencv_gpu.so.2.4.13 /usr/local/lib/libopencv_photo.so.2.4.13 /usr/local/lib/libopencv_objdetect.so.2.4.13 /usr/local/lib/libopencv_legacy.so.2.4.13 /usr/local/lib/libopencv_video.so.2.4.13 /usr/local/lib/libopencv_ml.so.2.4.13 /usr/local/lib/libopencv_calib3d.so.2.4.13 /usr/local/lib/libopencv_features2d.so.2.4.13 /usr/local/lib/libopencv_highgui.so.2.4.13 /usr/local/lib/libopencv_imgproc.so.2.4.13 /usr/local/lib/libopencv_flann.so.2.4.13 /usr/local/lib/libopencv_core.so.2.4.13 /usr/local/cuda-8.0/lib64/libcudart.so /usr/local/cuda-8.0/lib64/libnppc.so /usr/local/cuda-8.0/lib64/libnppi.so /usr/local/cuda-8.0/lib64/libnpps.so /usr/local/cuda-8.0/lib64/libcublas.so /usr/local/cuda-8.0/lib64/libcufft.so -ldl -lm -lpthread -lrt -Wl,-rpath,/usr/lib/aarch64-linux-gnu/tegra:/usr/local/zed/lib:/usr/local/lib:/usr/local/cuda-8.0/lib64
################################################################################
# PROJECT DEFINES
# Create a space-delimited list of DEFINES. The list will be converted into
# CFLAGS with the "-D" flag later in the makefile.
#
# (default) PROJECT_DEFINES = (blank)
#
# Note: Leave a leading space when adding list items with the += operator
################################################################################
# PROJECT_DEFINES =
################################################################################
# PROJECT CFLAGS
# This is a list of fully qualified CFLAGS required when compiling for this
# project. These CFLAGS will be used IN ADDITION TO the PLATFORM_CFLAGS
# defined in your platform specific core configuration files. These flags are
# presented to the compiler BEFORE the PROJECT_OPTIMIZATION_CFLAGS below.
#
# (default) PROJECT_CFLAGS = (blank)
#
# Note: Before adding PROJECT_CFLAGS, note that the PLATFORM_CFLAGS defined in
# your platform specific configuration file will be applied by default and
# further flags here may not be needed.
#
# Note: Leave a leading space when adding list items with the += operator
################################################################################
# PROJECT_CFLAGS =
################################################################################
# PROJECT OPTIMIZATION CFLAGS
# These are lists of CFLAGS that are target-specific. While any flags could
# be conditionally added, they are usually limited to optimization flags.
# These flags are added BEFORE the PROJECT_CFLAGS.
#
# PROJECT_OPTIMIZATION_CFLAGS_RELEASE flags are only applied to RELEASE targets.
#
# (default) PROJECT_OPTIMIZATION_CFLAGS_RELEASE = (blank)
#
# PROJECT_OPTIMIZATION_CFLAGS_DEBUG flags are only applied to DEBUG targets.
#
# (default) PROJECT_OPTIMIZATION_CFLAGS_DEBUG = (blank)
#
# Note: Before adding PROJECT_OPTIMIZATION_CFLAGS, please note that the
# PLATFORM_OPTIMIZATION_CFLAGS defined in your platform specific configuration
# file will be applied by default and further optimization flags here may not
# be needed.
#
# Note: Leave a leading space when adding list items with the += operator
################################################################################
# PROJECT_OPTIMIZATION_CFLAGS_RELEASE =
# PROJECT_OPTIMIZATION_CFLAGS_DEBUG =
################################################################################
# PROJECT COMPILERS
# Custom compilers can be set for CC and CXX
# (default) PROJECT_CXX = (blank)
# (default) PROJECT_CC = (blank)
# Note: Leave a leading space when adding list items with the += operator
################################################################################
# PROJECT_CXX =
# PROJECT_CC =
2017/1/12追記:それから、ofConstants.h にバグがあって、コンパイルエラーになります。これは随分前から指摘があって、まだ修正されていないようです。
Using Eigen library with Makefile (or Eclipse) - linux - openFrameworksに対策が記載されています。
Openframeworksのディレクトリに行き、libs/openFrameworks/utils/ofConstants.hの中身185行目付近に(上図参照)
#ifdef Success
#undef Success
#endif
を追加します。この後ofxKuZed-->zedExampleに行って make -j4 make run で今回の距離測定アプリの実行確認ができます。
2017/1/27追記:Camera.hpp で include error が出た場合は、/usr/local/zed/inclede/zed/Camera.hpp の最初の方4行について下記のように(赤字部分)自分の環境に合わせて絶対パスを書き込んでください。多分このように直せばOK。
#ifndef CAMERA_HPP
#define CAMERA_HPP
#include "zed/Mat.hpp"
#include "zed/utils/GlobalDefine.hpp"
#include </usr/local/cuda-8.0/include/cuda.h>
#include </usr/include/eigen3/Eigen/Core>
#include </usr/include/eigen3/Eigen/Eigen>
#include </usr/local/include/opencv2/opencv.hpp>
ofxKuZedに入っている標準サンプルを実行してみると....。
サンプルプログラムをそのまま実行720pで6fps程度しかスピードが出ません。
TX1では遅い!!。が、ちゃんと動いてます。 ZED SDKのサンプルと比べるとOpenframeworksの実行画像に変換する手間がある分、スピードは明確に落ちているようです。でも機能を絞ればTX1でも十分に実用スピードになります。何と言ってもOpenframeworks上でのZED稼働により応用範囲が飛躍的に高まりますので、実験には十分な性能です。試しに720pからVGAに変更するとこうなります。
カメラ読み取り画像をVGA(672x376)に落とすと11fpsくらいに上がります。さらに不要な処理を削除すれば最大17fps程度にスピードアップ!!
ZED SDKのExampleは一般受けを狙い3Dで立体化させて「わーっ」と言わせるものが大半ですが、この機器の一押しは画像深度ですから、使う側にとっては、カメラ画像の指定した部分が、カメラからどのくらいの距離か確認できればOKだと思います。一般的な距離センサーで測定できるのは狙った一点だけです。広範囲の測点を同時に計測するのは不可能。ZEDの価値は、その測点での圧倒的な優位性を如何にして利用するかだと、個人的には思ってます。できたのが冒頭の画像です。見た目は単純ですが、これを距離センサーで実現しようとすれば、到底不可能であることが経験者なら理解できると思うんですが。どうでしょうか?。ofxKuZedアドオンのGrayScale関数を利用してるので、0.6〜20mの範囲256段階での距離測定になります。測定上限は20m。上限を2.55mにすると精度は10mmになります(上限20mの場合、精度は78mm)。上限の範囲はキーボードから'0'、'9'を入力することで変更可能です。
次回はなんと倍くらいにスピードアップ!!。画像中の人物を見つけ出して、その人物までの距離を測定させてみました。
では、また。