Predator's Vision

画像処理、3D点群処理、DeepLearning等の備忘録

【PCL入門】 Point Cloud Library について

PCLはまだまだ英語の文献の方が多いと思うので、個人的に学んだことを何回かに分けて投稿しようと思います。

次のような読者を想定しています。

  • PCLをよく知らない
  • そもそもC/C++もあまり慣れていない
  • というかプログラミングにあまり慣れていない

ですので、分かる人にとっては冗長な説明ばかりかもしれません。

ちなみに、真の目的をぶっちゃけて言うと「私が大学の研究室でやっていたことを、将来誰かが引き継がなきゃいけなくなったときに見てもらうための覚書」です

続きを読む

Windows 8 で HSP3 アプリを終了時にランタイムエラーが発生する場合の対処

Windows Vista / 7 向けに作ったHSP3製アプリケーションを Windows 8 で動かすと、終了時に "Microsoft Visual C++ Runtime Library Runtime Error" が出る場合があることに気づきました。

同じ症状で困っている人もいるみたい。


なお私の場合は、onexitで別ラベルへ飛ばした後、endを実行するところでランタイムエラーが起こってしまうので原因が不明でした。


と、ここで下記情報を発見:


oncmdで飛んだ先のラベルの中だと普通のエラーがランタイムエラーになってしまうそうです。
この情報を元に下記のコードを試しに実行してみたところ、onexitでも同じようにランタイムエラーが起こることがわかりました。

	onexit goto *quit

*main
	wait 10
	goto *main
	
*quit
	mes "quit"
	error = 1 / 0	// 本来は「Error 19 : 0で除算しました」になる
	end


ということで、解決策として下記のようにコードを改造しました。

	onexit gosub *quit
	quitFlag = 0
*main
	if quitFlag : goto *terminate
	wait 10
	goto *main
	
*quit
	quitFlag = 1
	return
	
*terminate
	mes "quit"
	error = 1 / 0	// 「Error 19 : 0で除算しました」
	end

変更点は次の通り:

  • onexitで飛んだ先のラベル内では終了するというフラグだけを立てる
  • mainループの中で、常にフラグをチェック
  • フラグを元にonexit外のラベルから終了処理ラベルにジャンプ


かっこ悪いですが、これならちゃんと Error 19 になります。

ちなみに、先に述べた拙作アプリにこの改造を行ったところ、endで何のエラーも起こらず終了してくれるようになりました。

とりあえず Windows 8 でランタイムエラーが出るようになったら、まずはこんな風に改造してみるのがいいかもしれません。

VS2013 で FLANN 1.8.4 をビルド

VS2013 での FLANN 1.8.4 のビルドのメモ。

あるヘッダファイルを修正しないとうまくビルドできなかった。

環境

エラー内容

error C2228: '.serialize' : 左側がクラス、構造体、共用体ではありません。

修正箇所

  • 上記のサイトを参考に、serialization.h内の92行目あたりに3行追加
// declare serializers for simple types
BASIC_TYPE_SERIALIZER(char);
BASIC_TYPE_SERIALIZER(unsigned char);
BASIC_TYPE_SERIALIZER(short);
BASIC_TYPE_SERIALIZER(unsigned short);
BASIC_TYPE_SERIALIZER(int);
BASIC_TYPE_SERIALIZER(unsigned int);
BASIC_TYPE_SERIALIZER(long);
BASIC_TYPE_SERIALIZER(unsigned long);
BASIC_TYPE_SERIALIZER(float);
BASIC_TYPE_SERIALIZER(double);
BASIC_TYPE_SERIALIZER(bool);

#ifdef _MSC_VER   // 追加
BASIC_TYPE_SERIALIZER(unsigned __int64);   // 追加
#endif   // 追加

最終的なビルド手順

  1. FLANNのソースコードをダウンロード・解凍。今回はC:\FLANN下に解凍した。
  2. src/cpp/flann/util/serialization.hを上述の通り修正
  3. cmake して Visual Studio で開けるソリューションファイルを作成
    • スタートメニューからCMake (cmake-gui) を起動
    • 必要事項を入力して "Configure" を押す
      • "Where is the source code:" に "C:\FLANN"
      • "Where to build the binaries:" に "C:\FLANN\build" (どこでもいい)
    • 何か設定が必要であればする
      • 今回は特に何もしない
    • "Generate" を押す
  4. C:\FLANN\build に作成された flann.sln を管理者権限で開く
    • 下記のINSTALLで、ビルドしたファイルをProgram Files下にコピーするのに管理者権限が必要
      • INSTALLしなくていいなら flann.sln は普通に開いてよい
    • 先に Visual Studio 2013 を管理者権限で開いてから flann.sln を開くとよい
  5. メニュー「ビルド」→「バッチビルド」をクリック
  6. 次の4つにチェックを入れて「ビルド」を押す
    • ALL_BUILD (Debug)
    • ALL_BUILD (Release)
    • INSTALL (Debug)
    • INSTALL (Release)

VS2013 で Boost 1.55.0 をビルド

VS2013 での Boost 1.55.0 のビルドのメモ。あるヘッダーファイルに修正を加えてからでないとビルドが成功しなかった。

環境

エラー内容

c:\Boost\boost_1_55_0\boost/archive/iterators/transform_width.hpp(151) : error C2039: 'min' : 'std' のメンバーではありません。
c:\Boost\boost_1_55_0\boost/archive/iterators/transform_width.hpp(151) : error C3861: 'min': 識別子が見つかりませんでした

修正箇所

#include <boost/config.hpp>
#include <boost/serialization/pfto.hpp>
#include <algorithm>    // 追加箇所

#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/iterator_traits.hpp>

最終的なビルド手順

  1. Boostのソースをダウンロードして解凍する。今回はC:\Boost下に解凍。
  2. boost/archive/iterators/transform_width.hppを上述の通り修正
  3. 開発者コマンドプロンプトを開く
  4. コマンドを入力してビルド、インストール
    • パラメータの意味は次の通り
      • toolset: msvc-12.0 (VS2013) のコンパイラを使用
      • link: static link library (.lib) か dynamic link library (.dll) か
      • runtime-link: C/C++ランタイムライブラリを static link するか dynamic link するか
      • address-model: 32bit か 64bit か
      • build-dir: ビルド用ディレクトリ
      • stagedir: libを出力する場所
      • j: このビルドをする際に使用するCPUコア数 (並列処理)
      • install --prefix: インストール先
> cd C:\Boost\boost_1_55_0
> bootstrap.bat
> b2.exe toolset=msvc-12.0 link=static runtime-link=static,shared --build-dir=build/x64 --stagedir=stage/x64 address-model=64 -j 8 install --prefix="../"

Structure Sensor から距離画像やポイントクラウドを取得

前回の「Structure Sensor を Windows へ接続」の続きです。OpenNI2を使って距離画像(深度画像)・赤外線画像・ポイントクラウドを取得してみました。

ソースコード

Structure Sensor からデータを取得するC++のモジュール "structure_grabber" をGithubにおきました。

概要

距離画像・ポイントクラウドの取得は下記4つのファイルとOpenNI2ライブラリで可能です。

  • structure_grabber.h
  • structure_grabber.cpp
  • oni2_grabber.h
  • oni2_grabber.cpp

ただし、上記GitHubのサンプル内では、Visualizeのために距離画像についてはOpenCVを、ポイントクラウドについてはPoint Cloud Library (PCL)を使っています。

簡単な使い方

データ取得の方法を簡単に書くと下記の通りになります。

  • インクルード:
#include <opencv2/opencv.hpp>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include "structure_grabber.h"
  • 設定
StructureGrabber grabber;
grabber.enableDepth();
grabber.enableInfrared();
grabber.setDepthRange(0.3, 5.0);
grabber.open();
  • データの取得:
cv::Mat depth_image, infrared_image;
pcl::PointCloud<pcl::PointXYZ> cloud;

grabber.acquire();
grabber.copyDepthImageTo(depth_image);
grabber.copyInfraredImageTo(infrared_image);
grabber.copyPointCloudTo(cloud);

ビルド方法

  • ダウンロード後、CMakeLists.txtの中のOpenCVやOpenNI2に関するディレクトリ設定を適切に書き換えます。
  • コマンドプロンプトでCMakeLists.txtがあるフォルダに移動します
  • CMakeでプロジェクトを作成し、ビルドします。
cmake .

撮影結果1

撮影対象:
f:id:presan:20140702114608p:plain
机の上にコップとお椀、後ろには椅子とホワイトボード。


距離画像と赤外線画像:
f:id:presan:20140702115522p:plain
赤外線のLightCodingパターンが辛うじて見えます


(おまけ) 色付き距離画像:
f:id:presan:20140702115826p:plain


ポイントクラウド
f:id:presan:20140702134803p:plain
結構キレイにとれている感じがします。

撮影結果2

撮影対象:
f:id:presan:20140702135132p:plain
廊下のT字路


距離画像と赤外線画像:
f:id:presan:20140702135436p:plain
赤外線画像は人の目には何も見えない状態です。


ポイントクラウド
f:id:presan:20140702135751p:plain
3本の線は座標軸です。交点が撮影視点で、赤がX軸、緑がY軸、青がZ軸。


ちなみに俯瞰すると、遠くの方では誤差が目立ちます。
f:id:presan:20140702140115p:plain
Kinectでも遠すぎるとこうなりますね。


さらに、4,5m離れた先では取得データが丸みを帯びてしまいます。
f:id:presan:20140702140623p:plain
画像左側の円弧のように点が濃く分布しているところは、実際には平面です。公式データでは「40cm~3.5mの範囲で利用可能」と書いてありましたが、その通りなようです。

まとめ

  • Structure Sensor を叩くモジュールを実装しました。
  • 4m以上遠い場所の正確な3次元データは得られないことがわかりました。

Structure Sensor を Windows へ接続

f:id:presan:20140619021657p:plain

はじめに

"Structure Sensor" というiOS向けの超小型デプスセンサーについて、いろいろな方が既にレビューをされています。(ちなみにデプスセンサーとは距離情報を取得できるセンサーで、MicrosoftKinectを契機にかなり有名になりました。)


ただ、書かれている記事のほとんどが「iOSに繋げてみた」「デモアプリを使ってみた」ばかりのようなので、私は「iOS以外にUSB接続して、自力でデータを取り出す方法」を書きたいと思います。具体的には、今回はまず「Windowsから Structure Sensor を触る方法」を書いて、後に「Windowsで深度画像とポイントクラウドを取り出す方法」を書く予定です。

環境の準備

Structure Sensor は iOS からは Structure SDK というものを使えば触ることができます。そしてiOS以外の場合は OpenNI2 (OpenNI1ではダメ) を使えばよいそうです。

というわけで、まずOpenNI2を用意。
OpenNI2は今はStructure Sensorの下記のサイトからバイナリやドキュメントがダウンロードできます。

インストール後はOpenNI2のフォルダ内のどこかにあるPS1080.ini内の

;UsbInterface=2

になっているところを

UsbInterface=0

に修正します。これでStructure Sensorからデータを読み出すことができるようになりました。

接続確認

サンプルプログラムのNiViewerを起動したところ下記のようにちゃんと動作しました。(Win7Win8でそれぞれ動作を確認)左側がデプスで、右側が赤外線です。

f:id:presan:20140619020545p:plain

f:id:presan:20140619020556p:plain


次回は深度画像とポイントクラウドを取得したいと思います。