Time-of-Flightカメラの仕組み
こんにちはtatsyです。しばらく更新ができずにいたのですが、久しぶりに記事を書きたいと思います。
今回、Microsoft Kinectなどの深度センサに用いられているTime-of-Flightカメラ(ToFカメラ)の仕組みについて解説します。
インターネット上を調べてみると、簡単な技術解説のようなものは見つかったのですが、背景理論のようなものまで説明しているものは見当たらなかったので、今回は技術背景をを中心に解説できればと思っております。
ToFカメラを用いた技術についてはSIGGRAPH 2014でコンピューテーショナル・フォトグラフィの権威でもあるMITのRasker先生のコースがありましたので、さらに詳しく知りたい方はこちらの資料を参考にすることをおすすめします。
3D Imaging with Time-of-Flight Camera (Open Accessです)
https://dl.acm.org/citation.cfm?id=2615433
ToFカメラとは?
ToFカメラの最も一般的(になった)用途は深度の測定です。この技術を利用したもので最も有名と思われるものがMicrosoft Kinectで、新式のKinectはToFカメラの技術により深度を測定しています。
ToFカメラは光が光源から出てからどのくらいの時間でセンサに捉えられたのかを計測することで深度を測定します。例えば光源を出た光がToFカメラに1秒後に捉えられた(そんなことは実際にはありませんが)とすると、光源からカメラまでの距離は光速と同じく300,000,000メートルになります。
深度を測定する場合には、カメラと光源がほぼ同じ位置に置かれていて、光源から発せられた光が深度を測定したいシーンの何処かで反射してからセンサーに捉えられるまでの時間を測ります。今、カメラと光源は同じ位置にありますので、捉えられるまでの時間の半分が光が物体にあたってからカメラに捉えられるまでの時間になり、これから物体までの距離が分かるというわけです。
おそらく、ここまでの解説はウェブ上の多くの資料でなされていると思うのですが、それでは、どうして光が発せられてからセンサで捉えられるまでの時間が分かるのでしょうか?それをここから解説したいと思います。
ToFカメラによる深度測定
ToFカメラで用いられる光源は一定の周期で明滅を繰り返しています。この明滅により変化する光の強度をコサイン波で表現することにします。この明滅の周波数を$f_\omega$で表します。
$$ f_\omega(t) = A \cos(\omega t) $$
仮に、光が発せられて$\phi = -\omega_t t_0$だけズレていることが分かります。もし、このズレを観測することができれば、それを使っている光の周波数で割ることで光が発せられてからの時間が分かり、深度も計算することができます。
なるほど、では、光の波を観測できるセンサを使えばいいですね。となりそうですが、実際には$\phi$を求めることはできません。そこでToFカメラではPhotonic Mixer Device(PMD)と呼ばれる特殊なデバイスを使います。
通常、光のセンサは入ってくる光を電気的な波の情報に変換するのですが、PMDはこうして得られる電気的な波の情報に別の波を重ね合わせる変調と呼ばれる処理を行って波の性質を変化させます。一般的なToFカメラでは、PMDは光源に使っている周波数と同じ周波数$\omega$を持つ波で変調を行います。これを専門的な言葉でhomodyneと呼びます。
今、センサで捉えられた光が電気的な波の情報に変換され、
$$ \displaystyle s_\omega(t) = B \cos(\omega t + \phi) $$
に変化したとしましょう。この時、光が電気に変化したとしても周波数と位相差に変化がないことに注目してください。これを同じ周波数を持つ波で変調します。変調というのは言ってしまえばただの掛け算ですので、変調後の波は次のようになります。
$$ \begin{aligned} \cos(\omega t + \psi) \cdot B \cos(\omega t + \phi) &= \frac{B}{2} \left( \cos((\omega t + \psi) + (\omega t + \phi)) + \cos((\omega t + \psi) - (\omega t + \phi)) \right) \\ &= \frac{B}{2} \cos(2 \omega t + \psi + \phi) + \frac{B}{2} \cos(\psi - \phi) \end{aligned} $$
この波が電気信号として入ってくるのですが、カメラのセンサ上では、この波が時間的に積分されて最終的な信号強度として記録されます。
この時に時間的に積分される時間$\omega$が入っている項は0になって消えてしまいます。従って、この時間積分により得られる信号は、
$$ \displaystyle \frac{B}{2} \cos(\psi - \phi) $$
となります。一般に振幅Bの値は未知ですので、ここで更にもうひと工夫付け加えます。深度を推定する場合には、変調に用いる波の位相を0ずらしたものと$i_0, i_{\frac{\pi}{2}}$とすると、以下のように書けます。
$$ \begin{aligned} i_0 &= \frac{B}{2} \cos(-\phi) \\ i_{\frac{\pi}{2}} &= \frac{B}{2} \cos(\frac{\pi}{2} - \phi) = \frac{B}{2} \sin(-\phi) \end{aligned} $$
上記の2つの値が得られればあとは、以下のようにして位相差$\phi$を得ることができます。
$$ \displaystyle \phi = -\arctan \left( \frac{i_{\frac{\pi}{2}}}{i_0} \right) $$
この位相差は光が発せられてから戻ってくるまでの時間ですので深度を$2d \omega / c = \phi$となります。従って、最終的な深度は次のように計算されます。
$$ \displaystyle d = \frac{c \phi}{2 \omega} $$
ToFカメラによる深度測定の問題点
上記の通り、ToFカメラでは光が発せられてからカメラに捉えられるまでの時間に生じる位相差を求めることで深度を計測しています。ToFカメラの問題点についても簡単にご紹介します。
まず、よく知られた問題としてToFカメラは屋外のような周りから光が多く取り込まれる環境に弱いとされています。これは、深度計測に用いる近赤外光源から発せられた光以外に屋外環境からカメラに入り込む近赤外光の影響を受けてしまうためです。
そうすると、カメラセンサ上での積分により得られる位相差に誤差が生じるため、これにより正しく深度が計算できないという問題が起こります。
もう一つの問題はMulti-Path Interference (MPI)と呼ばれる問題で、これも比較的よく知られた問題です。カメラのセンサは通常1方向から来る光だけでなく、いろいろな方向から光が入ってきます。
通常、Kinectのような深度カメラでは1つのセンサが物体のある1領域を担当していますが、その領域以外から反射した光がセンサに入ってきてしまいます。これにより位相差が正しく求まらない問題が起こり、深度も正しく計算できなくなるというのがMPI問題です。
ただ、これらの問題を緩和する研究は2010年以降、かなり盛んに行われていて、屋外環境で使えるToFカメラ[1]や、MPIを緩和するための変調のやり方[2]などが多く提案されています。ですので、将来的には、商用のセンサでも上記の問題は緩和されていくものと思います。
[1] Achar et al., “Epipoler Time-of-Flight Imaging”, ACM Trans. Graph. 2017.
[2] Heide et al., “Doppler Time-of-Flight Imaging”, ACM Trans. Graph. 2015.
まとめ
今回はMicrosoft Kinectなどに用いられるTime-of-Flightカメラの仕組みについてご紹介いたしました。少なくとも日本語では、上記のような技術的背景について触れている資料は珍しい(?)と思いますので、こちらの記事が何かの助けになれば幸いです。
最後までお読みいただき、ありがとうございました。