Intel RealSense Depth Cameraがいかにやばいかについて

#TL;DR

- Intel RealSense Depth Cameraはやばい
    - Intel Euclid Development Kitが神デバイス過ぎてやばい
        - 手のひらサイズなのにDepthを処理しながら映像をエンコーディングできてやばい
    - 次のＤ400シリーズの解像度が高いのに値段が安くてやばい


# はじめに

はじめに武蔵野アドベントカレンダーの枠を譲ってくださったnishiyさんに
この場を持って感謝の意をお伝えしたいと思います。
ありがとうございます。

私は武蔵野に縁のある会社に勤めてはおりますが、
**武蔵野にはいません**。横須賀にいます。
武蔵野とは違い、横須賀では窓から富士山がきれいに見えます。
横須賀にいる人は誰しもが自慢します。そしてそれぐらいしか自慢するところがありません。

![IMG_5036.JPG](https://qiita-image-store.s3.amazonaws.com/0/78052/7ad4f9c8-f475-2fa6-cbc1-2edcf638e1cb.jpeg)
図1 横須賀という場所から見える富士山

**はい**

# なぜデプスカメラの話をするのか
そんな富士山がよく見える横須賀で、私は人とロボットとのインタラクションについて調べています。
ロボットが人とインタラクションするには*人の位置*をしっかり把握することがかかせません。そうでないとロボットと人がぶつかります。 **ロボット三原則もクソもないです。**
そこで役立つのがデプスカメラです。
デプスカメラとは映像の奥行きが測定できるカメラのことです。デプスカメラは奥行きが測定できることから、人や物体の位置をロボットが認識することに使われます。つまり、*ロボットの目*として使われています。たとえば、デプスカメラを組み込んだロボットとして、○epperくんとかHSRとかがあります。

このデプスカメラの１つとして、Intelが作っているRealSenseデプスカメラ（以下、RealSense）を紹介します。

今回、このRealSenseがいかにやばいのかを語らせていただこうと思います。

なお、デプスカメラがわからない人のために、これからデプスカメラの詳細を説明します。デプスカメラを知っている人は次の章まで読み飛ばしてください。

## デプスカメラってなにさ
デプスカメラとは画像の各画素が距離を表している深度画像を撮影することができるカメラのことです。

![depth.PNG](https://qiita-image-store.s3.amazonaws.com/0/78052/4411f3ff-d538-0809-857d-95e1c52fbeb0.png)
図2　デプスカメラにて撮影した自室と私（画素値が赤いほど近く、緑ほど遠い）

~~デブスちゃうで~~
デプスカメラはいろいろ製品があります。
たとえば、先述のRealSenseやKinect、Xtion、Leapがあります。

![IMG_4291.jpg](https://qiita-image-store.s3.amazonaws.com/0/78052/3d2c2b80-1ded-88ed-b3ff-a9c02a993eff.jpeg)![kinect.png](https://qiita-image-store.s3.amazonaws.com/0/78052/07b23114-8303-84ba-74a6-6a8b9c91ade8.png)![IMG_4288.jpg](https://qiita-image-store.s3.amazonaws.com/0/78052/afce9748-5373-9cf6-47c7-c24dbb1337d3.jpeg)


図3 いろんなデプスカメラ（左：Realsense、真ん中：Kinect、右：Leap）

特に圧倒的な販売量を誇るのはKinectです。 **3500万台** 売れたそうです。
なぜそんなに売れたのかというと、Xboxのおまけだったことと **モーションキャプチャー機能** があったからです。
モーションキャプチャーとは人の位置や姿勢などを非接触に取ることができる機能のことです。
これは発売当時画期的なことでした。
これまでモーションキャプチャーといえば、*数百万から数千万円のシステム*を買う必要がありました。
一方で、Kinectは*2万円*ぐらい、1/1000ぐらいの価格に破壊してしまったのです。
ただし、精度はそんなに高くなかったので、新しいモーションキャプチャー市場を開拓したという感じでした。
ちなみにKinectのアルゴリズムは画像処理の最難関国際会議ICCVで最優秀賞Best paperを取っています。
Kinectはアカデミアでもビジネスでも成功した稀有な製品なんです。
そんなKinectで実際に撮影してみたのがこちらです。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Kinectで取ったデプスカメラのサンプル動画です。リアルタイムに三次元情報が取得できていることがわかります。後ろの洗濯物や手前のエアーバッグ（ストレス発散用）もちゃんと取れています。逆に近すぎると測定不能として黒くなります。 <a href="https://t.co/X5LsEXr0R9">pic.twitter.com/X5LsEXr0R9</a></p>&mdash; あるふ (@alfredplpl) <a href="https://twitter.com/alfredplpl/status/943307687894204416?ref_src=twsrc%5Etfw">2017年12月20日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

体を3次元で撮影している感じがよくわかります。この情報を使って、モーションキャプチャーを行うのです。
他のRealSenseやLeapもモーションキャプチャー機能を持っています。特にLeapは手のモーションキャプチャーに特化しているため、*VRのHMDに無理やり引っ付けてVR空間に自分の手を飛ばす*という無茶な用途に利用されています。

ちなみにLeapの使い方を説明した「自然非言語処理」という私の*一人アドベントカレンダー*もあるので、そちらもあわせてご覧ください（ステマ）
[自然非言語処理第１１日目：運動を用いた非言語処理(知覚・認知編)](https://qiita.com/alfredplpl/items/eef0d5605771b5f3c3c9)

さて、最近問題となっているのは、Kinectが販売終了してしまったことです。
~~この原因は、Kinectの中に入っていたパーツをPrimeSenseという会社が作っていたのですが、
AppleがPrimeSenseを買収して、パーツを他の会社に売らなくなったかららしいです[2][3]。~~
(誤情報でした。すいません*1)

ちなみにiPhone XのFace IDはこのPrimeSenseのデプスカメラをセンサとして使っています。

~~Xboxとセットで販売せず、Kinectを単体で売ると赤字になるからMSは売るのを止めたかったとかいうずっと前から通の間では噂があったからAppleに売っちゃったから生産むりぽという言い訳を作ったんでしょうね~~

**今後のデプスカメラ覇権は誰が手にとるのか？**
というところが画像処理界隈の*ほんのりホットな話題*です。

# Intel Euclid Development Kitが神デバイス過ぎてやばい
Intel Euclid Development Kit（以下、Euclid）とは、このデプスカメラとそれを処理するためのコンピュータが一体となったプロトタイピング用の製品です。
画像のディープラーニングで有名な東大の中山先生もEuclidがいかに神デバイスであるかをたたえています。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">intelのEuclid、控えめに言って神</p>&mdash; Hideki Nakayama (@n_hidekey) <a href="https://twitter.com/n_hidekey/status/891297197731397632?ref_src=twsrc%5Etfw">2017年7月29日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

このEuclidの性能をユニポスというサイト[4]から引用すると、

>・Intel Atom x7-8700 Quad-Core プロセッサ搭載
>・Intel RealSense ZR300 デプスカメラ搭載
>・Wi-Fi / Bluetooth無線通信機能
>・IMU、気圧センサ、GPS、近接センサなどの環境センサ
>・Ubuntu 16.04 OSプリインストール
>・ROS(Kinetic Kame)プリインストール

ちなみに僕がさらにいいところを追加すると

>・外部バッテリー付属。5V3Aアダプター付属。
>・ファン内蔵。高負荷にも安定動作。
>・ちゃんと技適マークを取っており、日本でも使用可能
>・物体検出、人物検出、モーションキャプチャーなどのライブラリがプリインストール。
>・出荷時キャリブレーション済み。キャリブレーション用ソフトもプリインストール。

これでお値段 **399ドル** 。
完全に赤字商品。

ちなみに同じぐらいの性能を同じデプスカメラであるKinectで再現するとダンボール1箱ぐらいになります。

![IMG_4292.jpg](https://qiita-image-store.s3.amazonaws.com/0/78052/7635ffec-68c6-3cd4-4028-c65c705ad301.jpeg) ![IMG_4293.jpg](https://qiita-image-store.s3.amazonaws.com/0/78052/b3ee0e90-fcc9-5508-0d9d-a3e9e5f77e9d.jpeg)

図4 EuclidとKinect+PCのサイズの比較（ライターが手の幅サイズだと思ってください）

いかに効率よく小型化をおこなったのかがわかります。

さて、このEuclidの性能を実際に見ていただくために、
*モーションキャプチャしながらその様子を可視化してエンコーディングするというデモ*を
これからお見せします。

## 手のひらサイズなのにDepthを処理しながら映像をエンコーディングできてやばい
それではEuclidをつかって、モーションキャプチャしながら、その様子を可視化して**H.264**でリアルタイムエンコードするソースコードを以下に示します。
ちなみにこのソースコードはIntelのGithubにあるサンプルコードをもとに作成されています。
その為、このコードだけでは動きません。
以下にあるリポジトリのpt_tutorial_2のメイン部分を置き換えるとたぶんcmakeができるはずです。
https://github.com/IntelRealSense/realsense_samples

```c++:RecorderWithXZPlot.cpp
// License: Apache 2.0. 
// Copyright(c) 2016 Intel Corporation and Alfred Increment. All Rights Reserved.

#include <iostream>
#include "version.h"
#include "rs_sdk.h"
#include <stdio.h>
#include <chrono>
#include <opencv2/opencv.hpp>
#include <thread>

#include "pt_utils.hpp"

using namespace cv;
using namespace std;
using namespace rs::person_tracking;

// constants
const int WIDTH=640;
const int HEIGHT=480;
const int GRAPH_SIZE=200;

// Version number of the samples
extern constexpr auto rs_sample_version = concat("VERSION: ",RS_SAMPLE_VERSION_STR);

int main(int argc, char** argv)
{


    pt_utils pt_utils;
    // H.264 encording
    VideoWriter videowriter("video.avi",VideoWriter::fourcc('H','2','6','4'),30,Size(640,480));

    rs::core::video_module_interface::actual_module_config actualModuleConfig;
    rs::person_tracking::person_tracking_video_module_interface* ptModule = nullptr;

    // Initializing Camera and Person Tracking modules
    if(pt_utils.init_camera(actualModuleConfig) != rs::core::status_no_error)
    {
        cerr << "[RealsenseManager] Error: Device is null." << endl << "Please connect a RealSense device and restart the application" << endl;
        return -1;
    }

    pt_utils.init_person_tracking(&ptModule);

    ptModule->QueryConfiguration()->QueryTracking()->Enable();

    // Configure enabled module
    if(ptModule->set_module_config(actualModuleConfig) != rs::core::status_no_error)
    {
        cerr<<"[RealsenseManager] Error : Failed to configure the enabled module" << endl;
        return -1;
    }

    // Start the camera
    pt_utils.start_camera();

    cout<<"[RealsenseManager] Management has started."<<endl;
    auto startTime=std::chrono::high_resolution_clock::now();

    while(true)
    {
	auto diff=std::chrono::high_resolution_clock::now()-startTime;
	auto duration=std::chrono::duration_cast<std::chrono::seconds>(diff).count();
	if(duration>30)break;

        rs::core::correlated_sample_set sampleSet = {};

        // Get next frame
        if (pt_utils.GetNextFrame(sampleSet) != 0)
        {
            cerr << "[RealsenseManager]Error: Invalid frame" << endl;
            continue;
        }

	// copy original a image.
	Mat frameOrg(Size(WIDTH,HEIGHT),CV_8UC3,(uchar *)sampleSet.images[static_cast<uint8_t>(rs::core::stream_type::color)]->query_data());
	Mat frame(Size(WIDTH,HEIGHT),CV_8UC3);
	cvtColor(frameOrg,frame,COLOR_BGR2RGB);

	Mat graph=Mat::zeros(GRAPH_SIZE,GRAPH_SIZE,CV_8UC3);

	//plot x axis and z axis
	line(graph,Point(GRAPH_SIZE/2,0),Point(GRAPH_SIZE/2,GRAPH_SIZE),Scalar::all(255),1);
	line(graph,Point(0,GRAPH_SIZE/2),Point(GRAPH_SIZE,GRAPH_SIZE/2),Scalar::all(255),1);
	
        // Process frame
        if (ptModule->process_sample_set(sampleSet) != rs::core::status_no_error)
        {
            cerr << "[RealsenseManager]Error : Failed to process sample" << endl;
            continue;
        }
	

        Intel::RealSense::PersonTracking::PersonTrackingData *trackingData = ptModule->QueryOutput();

        for (int index = 0; index < trackingData->QueryNumberOfPeople(); index++)
        {
            Intel::RealSense::PersonTracking::PersonTrackingData::Person *personData = nullptr;
            personData = trackingData->QueryPersonData(Intel::RealSense::PersonTracking::PersonTrackingData::ACCESS_ORDER_BY_INDEX, index);

            if (personData)
            {

                Intel::RealSense::PersonTracking::PersonTrackingData::PersonTracking *personTrackingData = personData->QueryTracking();
                Intel::RealSense::PersonTracking::PersonTrackingData::PointCombined centerMass = personTrackingData->QueryCenterMass();

                float centerMassWorldX = centerMass.world.point.x;
                float centerMassWorldY = centerMass.world.point.y;
                float centerMassWorldZ = centerMass.world.point.z;


		//draw a user's position.
		circle(graph,Point(centerMassWorldX*GRAPH_SIZE/2+GRAPH_SIZE/2,GRAPH_SIZE-centerMassWorldZ*GRAPH_SIZE/2),10,Scalar::all(255),-1);

            }
        }
	//paste graph into frame.
	graph.copyTo(frame(Rect(WIDTH-GRAPH_SIZE-GRAPH_SIZE/4,HEIGHT-GRAPH_SIZE-GRAPH_SIZE/4,GRAPH_SIZE,GRAPH_SIZE)));

	//encord		
	videowriter<<frame;

        // Release color and depth image
        sampleSet.images[static_cast<uint8_t>(rs::core::stream_type::color)]->release();
        sampleSet.images[static_cast<uint8_t>(rs::core::stream_type::depth)]->release();

    }
    pt_utils.stop_camera();
    actualModuleConfig.projection->release();

    cout << "-------- Stopping --------" << endl;

    return 0;
}
```
動作結果は以下の通りとなります。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Intel RealSense Euclid Dev. Kitを使ってモーションキャプチャしながら、その様子を可視化してH.264でリアルタイムソフトウェアエンコードしました。右下が俯瞰図です。丸が私の位置を表しています。なお、仮面があれですが、某ハッカー集団とは何の関わり合いもありません。 <a href="https://t.co/TzWd7OGMbh">pic.twitter.com/TzWd7OGMbh</a></p>&mdash; あるふ (@alfredplpl) <a href="https://twitter.com/alfredplpl/status/943505670220869632?ref_src=twsrc%5Etfw">2017年12月20日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

*ね、やばいでしょ。*

## Euclidに関する悲しいお知らせ
このEuclid、今年2017年5月31日に発売されたのですが、ユニポスによると

> **本製品は販売終了となりました**

ということです。

なぜこんなにたたえているのかわかりますね。

**頼む再販してくれ**

そういうことです。

# 次のD400シリーズの解像度が高いのに値段が安くてやばい
Euclidは販売終了してしまいましたが、ちゃんと次世代のRealSense、D415とD435は開発されており、
来年には販売される予定です。
D415とD435の情報は公式のWebサイトにたくさん載っていますが、arXivに性能やアルゴリズムが公開されているというところ[5]がインテル入ってる感あります。
ちなみに現行のRealSenseと次世代のRealSenseの性能を比較したのが以下の図5らしいです。

![D400シリーズ.png](https://qiita-image-store.s3.amazonaws.com/0/78052/90b60090-77c3-955e-4693-580eb8a094b0.png)
図5 現行のR200と次世代のD400シリーズの精度比較（[5]より引用）

質で見れば一目瞭然。せっかくなので、量を表で比較して見ましょう。

| 比較軸 | R200[6] | Kinect v2[7]  | D435[8] |
|:-:|:-:|:-:|:-:|
| 解像度  | 640 x 480  | 512×424  | 1280 x 800  |
| FPS |  60 |  30 | 30  |
| 画角(HxV) | 59x46  | 70x60 | 91.2x65.5 |
| 動作範囲[m] |  0.4-2.8  | 0.5-4.5  | 0.2-約10  |
| 価格[US$] | 99 | 199  | 179 |
| 方式 | Active IR Stereo  | Time-of-Flight  | 	Active IR Stereo (Global Shutter)  |
| 電源  | USB3.0  | コンセント  | USB type-C  |
| 屋外での利用  | ○  | ×  | ○ |


大手が提供するレーダーレンジファインダーでも最低30万円、LiDARに至っては最低100万円のところをD435は約2万円。
やばい。

ちなみに予約サイトはこちらになります。
1/8の週からshipping予定らしいです。日本に届くのはいつでしょうね。
https://click.intel.com/realsense.html
https://www.mouser.jp/new/Intel/intel-realsense-camera-400/

# 最後に
実はマイクロソフトからKinect終了に関してお気持ちが表明されています[7]。

>Kinect センサーとアダプターの製造は終了しましたが、Kinect 技術は HoloLens、Cortana 音声アシスタント、Windows Hello 生体顔認識、コンテキスト対応のユーザー インターフェイスで今も活用されています。
>マイクロソフトでは Intel と協力して、Kinect for Windows プラットフォームからの開発者向けの移行オプションに取り組んでいます。マイクロソフトは、オンライン フォーラム、プレミア サポート、有料のテクニカル サポートを通じて、引き続き Kinect for Windows SDK のサポートを提供します。開発者の間では Kinect ハードウェアからの移行が進んでいるため、開発者の皆様には、**Intel RealSense デプスカメラ**の検討をお勧めします。

**Intel RealSense Depth Cameraはやばい**
![IMG_4314.jpg](https://qiita-image-store.s3.amazonaws.com/0/78052/d2e24e4d-2fff-92f0-f4cf-c584bc6ee837.jpeg)
図6 Euclid上でゴリゴリ開発するときのEuclid覚醒状態の様子

# 参考文献
[1] https://www.mouser.jp/new/Intel/intel-realsense-camera-400/
[2] http://allthingsd.com/20131124/apple-confirms-acquisition-of-3d-sensor-startup-primesense/
[3] https://japan.cnet.com/article/35109375/
[4] https://www.unipos.net/find/product_item.php?id=3229
[5] Leonid Keselman, John Iselin Woodfill, Anders Grunnet-Jepsen, Achintya Bhowmik, "Intel RealSense Stereoscopic Depth Cameras," arXiv, 2017
[6] https://software.intel.com/sites/default/files/managed/d7/a9/realsense-camera-r200-product-datasheet.pdf
[7] https://developer.microsoft.com/ja-jp/windows/kinect/hardware
[8] https://www.mouser.com/pdfdocs/Intel_D400_Series_Datasheet.pdf

*1 
>Microsoft now deploys its own homegrown sensor technology for the current generation of Kinect devices, which ship with the recently launched Xbox One.

[2]とあり、v2や最新型はPrimeSense社関係ないようです。