VR技術者試験と3Dセンサー

3D Sensor Advent Calendar 2019の18日目の記事です。

## 概要
3D センサー歴 3 か月程度の初心者ですが、今日はVR技術者試験を受けて、3Dセンサーの理解が深まった部分について、いくつか記載したいと思います。
当初は、箔付け、ぐらいのつもりで受けた試験ですが、その内容は自分の今やっている3Dセンサー開発、xR開発の理解を大きく助けるものでした。
今回、主にアプリケーション側で学習した中で、 3Dセンサーの理解に役立つ知識を紹介したいと思います。
（時間が足りず、どこまで触れられるか分かりませんが・・・）

### バーチャルリアリティ学を通した 3Dセンサー技術

今回参考にする書籍は、VR技術者試験のテキストである日本バーチャルリアリティ学会編の『バーチャルリアリティ学』です。その中の特にVR技術者アプリケーション試験の範囲となる 5章-8章 から抜粋して、実際にどのような使われ方をしているのかなどをご紹介します。（主に自分が読んで理解したもので、間違っている部分があるかもしれません・・・）

3Dセンサー関連の話題は、『5章 リアルとバーチャルの融合』 の中で多く語られています。
今回は 3Dセンサーの技術面に焦点を当てて、ご紹介します。

##### 本書P.139（幾何学的）レジストレーション


このレジストレーション、カメラの位置、サイズ、傾きを合わせる「位置合わせ」という意味で、VR世界と現実世界の三次元座標系を一致させる作業を指します。VRでは、複数の Color カメラや Depth カメラからの画像を合わせる行為もレジストレーションといいます。

サンプルとして、点群の位置合わせで、回転行列Tと平信行列Rの例を使ったレジストレーションです。
（以下は玉木徹先生の三次元レジストレーションより抜粋させていただきました）
https://www.slideshare.net/ttamaki/3pcl
<img width="1053" alt="スクリーンショット 2019-12-16 19.25.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389500/724acc1d-0538-549b-5199-e4487cba99e9.png">



#### 本書p.140（カメラ）キャリブレーション

本書ではレジストレーションという言葉とキャリブレーションという言葉が出てきます。どちらも3Dセンサー関連の用語ではありますが、キャリブレーションとは、測定の意味です。
VR内でもいくつか意味があるのですが、今回はカメラキャリブレーションの話です。カメラキャリブレーションは、レンズ焦点距離などの内部パラメータ、カメラの位置・姿勢を表す外部パラメータ、レンズの歪収差係数を求め、画像を補正する作業を指します。

レンズは曲面になっているので、それを補正するためにカメラ固有の補正パラメータである内部パラメーターを使います。
内部パラメータ補正は OpenCV だと以下のようなイメージになります。

（出典元）
https://www.yukisako.xyz/entry/2015/09/02/155433

<img width="732" alt="スクリーンショット 2019-12-16 19.54.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389500/361579ed-5e64-7a37-7855-38555ea4678c.png">


ちなみに、AzureKinect の場合は、内部パラメータをマーカーなどを使用せずに
depth画像 は、calibration.depth_camera_calibration
color画像 は、calibration.color_camera_calibration
で取得することができます。


ワールド座標系からカメラ座標系に変換するビューイング変換（外部パラメータでの補正）だとカメラで見える角度を絶対的な座標に置き換えることができるので、以下のようにイメージなります。

（出典元）
https://watlab-blog.com/2019/06/01/projection-transform/

<img width="717" alt="スクリーンショット 2019-12-16 20.03.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389500/fa7924a8-6039-af8a-8b5f-4c795e90922a.png">

こういった、パラメータ変換を通して、VRと現実世界を繋ぐわけですね。

#### 本書p141アウトサイドイン方式、インサイドアウト方式
VRで位置情報と姿勢情報を得る場合、カメラを自らの視点でつけるインサイドアウト方式と、外部に複数のカメラを置いて情報を得るアウトサイドイン方法があります。3Dセンサーはアウトサイドインで外部から対象の深度とカラー画像をとりながら位置と姿勢情報をとる感じでしょうか。

![コメント 2019-12-17 190537.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389500/033b10f3-ea5d-0591-d59f-fce173792803.png)
画像著作権： Ishii, K. (2010)

#### 本書p141 マーカ方式、自然特徴
位置や姿勢を取得する際、カメラ方式では、マーカ方式と自然特徴方式が取られます。xRでは一般的なマーカ方式ですが、3Dセンサーでも位置を把握し幾何学的レジストレーションをするためにもよく使用します。

#### p152 レンジセンサ、ToF
物体の表面形状データの取得にはレンジセンサ、という画素中に奥行き情報を持つ2.5次元の距離画像を取得します。
こちらの情報から三次元座標を復元し、隣り合う頂点をつなぎ合わせることで表面形状データを得ることができます。
また、この中で紹介されているTime of Flight は、Kinect V2,Kinect V4(Azure Kinect)にも使われている手法で、比較的遠くでも精度の高い深度が得られます。

#### p154 ICP
ICP、というのは Iterative Closest Point の略です。二つの形状データを一個に結合する際、頂点の位置が一番近くなるように繰り返し計算し探索する方法です。部分的な 3Dのdepthデータを位置合わせするのにも使用します。
3Dセンサーでも、複数の3Dデータからひとつの3Dデータに結合する場合などに使用されます。

例えば、以下の例ですと、c++の関数で、同一形状で傾きが違うオブジェクトなどを位置合わせしていくことになります。
void icp(std::vector<Point*> &dynamicPointCloud, std::vector<Point*> &staticPointCloud);
https://github.com/Gregjksmith/Iterative-Closest-Point

何度か試行しないといけないようで、上は100回繰り返したもの下は400回繰り返すことでばっちりあった状態です
![コメント 2019-12-17 211200.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389500/6b33a6b2-eccf-1895-c188-4e48a08e1880.png)
![コメント 2019-12-17 211221.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389500/3d34ce4c-9b3f-2681-f38f-2479cb1bb49c.png)


## 最後に

VR技術者試験中、勉強だけだときつかったので、色々なものを試験期間中調べてました。
身近なワードが試験の中に現れることで、理解が深まるのが非常によく、3DセンサーやDepth関連についてもVRのテキストに出たことで身近なものとして再学習することもでき、結論としては、VR技術者試験を受けて良かったなと思ってます。

今回、学習に忙しくいろいろ学んだことをまだ実装や開発にまで落とし込めていないのは残念です。
もっと深い知識と理解を得て、自分で各サンプルを実行できる、くらいにはしておきたいなと思う今日この頃・・・


## 参考

マイナビニュース | 意外と知らないカメラキャリブレーション
https://news.mynavi.jp/article/cv_future-5/

トマシープが学ぶ | VR技術者試験の過去問やってググっていく（アプリケーションコース）

http://bibinbaleo.hatenablog.com/entry/2019/11/02/161401


明日はpisa-kun さんの 「KinectAzure SDKでなんかやってみる c#」 です。来年には日本でも正式発売の Azure Kinectですが、触る人はもっともっと増えてほしいですね。みんなで頑張りましょう！