Tech Sketch Bucket of Technical Chips by TIS Inc.

Kinect + OpenNIを使用して取得した「空間の使用頻度」をsocket.ioを利用してリアルタイムに確認する - ③(Kinect編)

Pocket

前回前々回で環境構築とサーバ側の実装まで完了しました。今回はKinect側の実装を進めていきます。

Kinect側の実装はC++を利用して実装していきます。
必要なミドルウェアは以下のとおりです。

  • Microsoft Visual C++ 2010 Express
  • 開発にはMicrosoft Visual C++ 2010 Expressを使いました。

  • OpenNI
  • OpenNIのインストールや設定、実装は以下のサイトを参考にさせていただきました。ありがとうございます。
    OpenNI2入門(http://www.naturalsoftware.jp/blog/category/introduction/openni2-introduction)

  • OpenCV
  • OpenCVに関しては以下のサイトを参考にさせていただいています。
    opencv.jp(http://opencv.jp/)

  • libcurl
  • 前回作成したサーバにデータを送信するために、C++でHTTP通信が可能なlibcurlを使います。
    libcurlのインストールやサンプルは本家のサイトの解説が分かりやすいと思います。
    http://curl.haxx.se/

それではみていきましょう。

実装のイメージ

今回Kinect側のプログラムのイメージ図を以下に示します。

kinect_image.png

今回は以下の箇所を解説していきます。

  1. OpenNI/OpenCVによるKinectからのデータ取得~データの描画まで(図中①~③まで)
  2. libcurlによるHTTP通信(図中④)

作成するアプリケーションのイメージは以下のとおりです。

jikkou.png

上図の左半分は、Kinectから取得したデータを加工して表示したものです。画像データを一定範囲に区切り、その範囲に物体が入った場合そのDepth値に応じて色を表示しています。画像の加工や表示にはOpenCVを利用しました。また、図の右半分にはあらかじめ用意した画像を表示しておき、先ほど区切った範囲に物体が入った時点でkinectからの距離を計算し、どこに触れているのかを表示しています。

ではソースコードを見ていきましょう
ソースコードが長いため、詳細はhttps://github.com/tech-sketch/kinect_realtime_sample/tree/master/kinect_libcurl_sample/kinect-libcurlをご参照ください。

OpenNI/OpenCVによるKinectからのデータ取得~データの描画まで

OpenNIを利用してKinectからColorデータとDepthデータを受け取りOpenCVで使える形式に変換する

OpenNIで取得されたColorデータは、RGB形式になっているため、
そのままOpenCVに渡すと色が正しく表示されません。そのため、「cv::cvtColor」で色の変換を実施しています。

物体の検出

OpenNIのライブラリであるNiTEを使うことで、Kinectから撮影される画像や深度データから人や骨格(ボーン)を検出することが可能です。しかし、今回はKinectを床から見上げる形で設置しているため、上記手法は適用せず深度データのみを利用し物体を検出しました。

今回作成するアプリケーションはKinectを地面から見上げるような設置方法にしています。また、物体(手など)が調査対象の空間に入っていることを調べることが目的であり、人の全体像を写すことが難しかったためDepthデータから物体の検出を実施しました。

物体の検出は以下の方法で実現しています。

  1. OpenNIで取得できるプロジェクション空間をx、y座標とDepth値で区切る。
  2. x, yの各PixelごとにDepthの値を取得し、1で定義した範囲に入っているPixel数を調べる
  3. 2.で物体があると判断された座標をプロジェクション空間からワールド座標に変換する
  4. 3.で変換した座標を正面から見た座標にマッピングする
  • OpenNIで取得できるプロジェクション空間をx、y座標とDepth値で区切る。
  • main.cpp(抜粋)

    pointArea.cpp

    • x, yの各PixelごとにDepthの値を取得し、1で定義した範囲に入っているPixel数を調べる
    • 2.で物体があると判断された座標をプロジェクション空間からワールド座標に変換する

  • 3.で変換した座標を正面から見た座標にマッピングする
  • OpenCVで画像を合成し表示

    color画像に、物体が入っていると検知された画像を合成して表示しています。

    libcurlによるHTTP通信

    サーバ側にデータ通信する部分については以下の箇所に記載してあります。

    初期化

    curlの初期設定を実施している箇所です。上記、「curl_easy_setopt」には環境に合わせた値を
    入れてください。

    HTTP通信

    postthisの内容をcurlで送付しています。

    その他

    色の表現について

    今回のプログラムでは範囲内に入っていることを示す描画を18行目〜82行目に実装していますが、色の表現については、以下のサイトを参考させていただきました。

    PHPでヒートマップを生成する

    完成版

    第1回~3回までの実装をすべて完成させると、以下のようになります。


    今回作成したKinectに関する実装は箇所はデモの画面左になります。
    設定された範囲内に手を入れると、Kinectから取得したx, y, Depthを元にKinectと手がどれくらいの距離にあるかが描画されます。
    また、第2回で作成したサーバにデータを送信することで画面右にあるようなリアルタイム描画を行うことが可能になります。

    おわりに

    前々回前回と3回に分けて、Kinectからデータを取得し別の場所にあるPC等にリアルタイム通信を行うサンプルを作成しました。
    今回のようなアプリの構成にすることで、Webアプリの入力媒体としてKinectを使うことが可能になります。

    なかなか使う機会の少ないKinectですが、色々と楽しいので皆さんも遊んでみてください。

    エンジニア採用中!私たちと一緒に働いてみませんか?