研究テーマ
「距離画像から光源推定を行い、仮想物体に陰影付けを行う」

1.はじめに

まず仮想物体を扱うにあたり、私が複合現実(以下MR)や拡張現実(以下AR)に興味を持った切っ掛けは、スマートフォンアプリの「ポケモンGo」のAR機能で遊んだ時に自分の想像するAR(画像 1.1)とアプリのAR(画像 1.2)が全然違うと思ったからです。

画像 1.1

画像 1.2


そこでAR・MRにおいて仮想物体(画像中ではポケモン)を現実世界に違和感なく表現するための条件について調べたところ、以下の3つの条件を満たすことが重要らしい。

  1. ① 幾何学的整合性(現実に沿った位置関係)
  2. ② 光学的整合性 (違和感のない陰影付け)
  3. ③ 時間的整合性 (仮想世界と現実世界の時間の一致)

この条件をふまえて再度画像1.1を見てみよう。(画像なので③の時間的整合性は省略)

画像 1.3


画像1.3のように条件にある①・②の整合性を満たしている。しかし、画像1.2では仮想物体は壁にのめり込み、周りの陰影にも適応していないので2つの整合性を満たしていない。AR機能を使ったときの違和感はこの条件を満たしていないのが原因だった。

そこでこの2つの整合性の内、光学的整合性を保つ手法を研究したいと思い研究し始めました。


2.手法

光学的整合性を保つために光源位置の推定を行います。光源の位置は光が強く当たっている現実空間の面の法線方向の領域に存在する(画像1.4)のでこのことを用いて推定を行います。

画像 2.1


よって明るい領域とその法線方向の情報を入手する必要があります。そこで今回は使用機材として「HoloLens」を用います。HoloLensには空間認識カメラなどの現実世界の物体を認識するセンサーが搭載されているので、これを用いて法線を求める。またHoloLensで写真を撮影することができるので、これで明るい領域の情報を入手します。それらを踏まえた全体的な流れは以下のようになります。

  1. ① 空間の認識
  2. ② 空間の一部の画像取得
  3. ③ 光源推定 ←現在(2020/4/16)ここまで
  4. ④ 仮想物体の陰影付け

以降、各流れごとの説明です。


3.空間の認識

HoloLensでは「spatial mapping」を有効にすると視線方向の空間をメッシュ化し記録します。下の画像3.1は研究室の空間を認識しメッシュ化したものです。実際にはこんなに広い範囲をメッシュ化しなくても大丈夫だと思われる。(法線方向を求めたい場所の情報が欲しいだけなので)

画像 3.1


4.画像取得

画像の取得はプログラム(C#)を書いてAirTapで行う。プログラム自体はMicrosoftホームページにあるものを参考にした。

取得した画像について、処理の流れは以下のようになる。

  1. ① 画像の平滑化
  2. ② 画像中の光源の有無について場合分け
  3. ③ 場合分けにふさわしい光源の推定

平滑化について

取得した画像は、明るい領域を求める前に平滑化処理を行います。平滑化のために今回は5×5画素に平均化フィルター処理をします。5×5の平均化フィルターは、画素値(RGB値)を周囲5×5画素の画素値の平均にするフィルターです。(画像4.1) 明るい領域は画素値を参考にして求めるので、これを行うことにより床の模様などの急な画素値の変化を小さくし、領域の判定をより正確なのもにします。

画像 4.1


どのように変わるか試してみよう。下の画像4.2はフィルター処理前の元画像で、画像4.3はフィルター処理後の画像です。わかりにくいですが、若干ぼやけた感じになっています。

画像 4.2 : 平滑前

画像 4.3 : 平滑後


変化の具合をさらに可視化するために、本研究では用いないが各画素を水平方向に微分した(左右の画素の画素値の差を表す)ものを以下に示します。簡単に説明すると、ある画素に対して右にある画素の画素値から左にある画素の画素値を引いているので、黒色に近いほど左右の画素値の差が無いことを表しています。以下の画像の帽子に付いている毛?(デザイン)を見ると、細かい変化が緩やかになっています。

画像 4.4 : 平滑前

画像 4.5 : 平滑後


ある一定の面積のある領域(今回は明るい領域)を求めたいので、画像取得後はこの処理を行う。また、この処理はCompute Shaderで行う。Compute Shaderで処理を行う利点を以下に示します。

  1. ・Graphic Processing Unit (GPU) で計算を行うことができる。(C#で書いたプログラムはCPUで計算されるので、GPUで計算する分だけCPUに余裕ができる。)
  2. ・CPUからGPU、GPUからCPUへのデータの受け渡しができる。
  3. ・並列処理に特に優れている。(大量の画素に対して処理が速やか)

画像の場合分け

平滑化した画像を基に光源推定を行うが、求める理由は「その領域は光源から強く光を受けている場所なので、その法線方向に光源があるだろう」という推測ができるからです。つまり、そもそも画像内に光源が存在する場合は、法線方向を求める処理を行ってはいけないということになる。よって、光源が画像内に存在するかしないかの場合分けを先に行います。

光源が画像中に存在する場合

本研究では機械学習を用いないので、画素値を基に光源の有無の判定を行います。判定方法は、「画素値(RBGの各値)が0.98(最大値を1とした場合)以上ならば光源である」とする。RGB値すべてが1の場合は白色を表すので、この0.98という値は限りなく白色に近いことを表し、また白色光の判定しかできないということを表します。(本研究ではこの部分は重要ではないのでこの問題は解決せず、条件とする。)判定結果を視覚化したものを以下の画像に示します。紫色に塗られている領域が光源と判定された領域です。

画像 4.6 : 空間画像

画像 4.7 : 光源判定結果


画像中に光源が存在しない場合

ここからが本題です。画像中に光源がない場合の光源推定について考えていきます。2章で説明したように推定するためには画像中の明るい領域を求める必要があります。その領域を求めるために、今回は「K-means法」を用いて画像中の画素を画素値を参考にクラス分けします。「K-means法」についての詳細は以下。(クリックで表示)

K-means法について

K-means法は機械学習の一種で、データを複数の(K個の)クラスタに分ける手法です。以下図を用いて詳しい手法や説明をしていきます。

まずランダムに事前にK個の重心点を決めます。(下の画像では例として3個の重心点を配置しています。)

各データを、最も近い距離にある重心点と同じクラスタに振り分けます。

クラスタの重心点の位置を再度計算し(平均を求める)、位置を更新します。

重心点が更新されたので、再び各データと重心点の距離を計算し、クラスタを振り分けます。

クラスタ内のデータに変化があれば、重心位置も変化するので再度重心点を計算。

このように重心の更新とクラスタの割り振りを繰り返し、重心の位置が変化しなくなったらデータのクラスタリングが終了したことになります。

条件などの説明の前に、まず画像を画素値を基に「K-means法」でクラスタリングした結果を以下に示します。

画像 4.8 : 空間画像

画像 4.9 : クラスタリング結果


画像のクラスタリングにあたり、本研究では以下のような条件で行いました。(クリックで詳細)

  1. クラスタの数は7つ

        クラスタ数が多すぎると求める領域が狭くなり、逆に少ないと求める領域が広くなってしまうので調節した結果7つになりました。また、画素値が0.98以下で構成されているので(画像中に光源が無い)7だと均等に割り切れるため。


  2. 重心位置が一定値を下回れば、クラスタリングを終了する

        本来であれば重心位置が変化しなくなればクラスタリング終了であるが、プログラムの計算上全く同じ位置になることはきわめて稀で計算量が莫大になるので、基準値を決めそれを下回るとクラスタリングを終了にしすることで計算量を調節することができます。


  3. 初期重心位置はランダムではなく、こちらが指定する

        初期重心位置は本来ならランダムだが、それだと明るさの分類分けが不安定になり、明るい領域が光源推定に用いることができないほど狭かったり、逆に広すぎるということが発生してしまう。また、計算量もそれに伴い大きく変化する。よって、初期重心位置は以下のように均等に割り振ることで、安定して領域を求めることができ、また計算量も安定させることができる。
    第1クラス(0.00, 0.00, 0.00)、第2クラス(0.14, 0.14, 0.14)、
    第3クラス(0.28, 0.28, 0.28)、第4クラス(0.42, 0.42, 0.42)、
    第5クラス(0.56, 0.56, 0.56)、第6クラス(0.70, 0.70, 0.70)、
    第7クラス(0.84, 0.84, 0.84)


クラスタリングの結果最も画素値の高い重心にクラスタリングされた領域を「明るい領域」とすることで光源を推定していく。画像4.9で最も画素値の高い領域を紫色に塗りつぶし、わかりやすくしたのが以下の画像です。

画像 4.10


5.光源推定

※ここからは一部実装がまだできていない部分があるので、提案手法を示します。

画像から明るい領域を求めることができたので、これを用いて光源推定していきます。画像中に光源が存在する場合と存在しない場合の2通りに分けて考えていましたが、まずどちらにも必要な「座標変換」について説明します。座標変換は、画像座標を空間座標に変換することです。4章で求めた「明るい領域」や「光源判定された領域」は全て画像座標(二次元)です。しかし、MR・ARにおいて仮想物体は3次元で扱うので空間座標(3次元)に変換しないといけません。よって「座標変換」は画像中の光源の有無に関わらず必要になります。では、その手法について説明します。

画像座標から空間座標への変換は「透視投影変換」を利用して行う。「透視投影」は遠くのものを小さく、近くのものを大きく投影するもので図5.1のように空間上の点Pは視点と点Pを結ぶ直線上の点P'に投影されます。つまり、視点から画像上の点の延長線上に現実空間の物体(画像に写ってる物体)が存在することになります。また、空間座標とカメラ座標は透視投影変換行列によって下の関係式をもちます。よってカメラ座標から空間座標への変換はこれを逆算することで求められます。(画像座標からカメラ座標への変換は下に詳細あり)

画像 5.1


関係式

\[ \begin{pmatrix} x’ \\ y’ \\ z’ \\ 1 \end{pmatrix} =M_p \begin{pmatrix} X \\ Y \\ Z \\ 1 \end{pmatrix}\quad \begin{matrix} カメラ座標...p'(x',y',z')\\ 空間座標...P(X,Y,Z)\quad\\ 透視投影変換行列...M_p\\ \end{matrix} \]

透視投影変換行列について

\[ M_p = \begin{pmatrix} 1.51606 & 0.00000 & -0.00154 & 0.00000 \\ 0.00000 & 2.69217 & -0.00569 & 0.00000 \\ 0.00000 & 0.00000 & -1.00000 & 0.00000 \\ 0.00000 & 0.00000 & -1.00000 & 0.00000 \end{pmatrix} \]

画像座標からカメラ座標への変換はこちら

まず、各座標系について説明します。画像座標は下画像のように画像の左上が(0,0)で右下が(画像の幅, 画像の高さ)になります。(画像左下が(0,0)じゃないので注意)また、カメラ座標は下画像のように画像の幅と高さを-1~1の範囲にしたもの(画像の中心座標が(0,0)でz座標は1になります。(今回の場合)

画像座標

カメラ座標


変換について説明していきます。画像幅をwidth、画像の高さをheightとして、画像上の任意の点の座標を(i,j)(画像座標で)をカメラ座標に変換するとします。

まず、画像の幅をwidthで、高さをheightで割ります。


画像座標のy座標は下が正の方向になっているので、これを上向き正にするためにy座標だけ1引きます。


カメラ座標の範囲は-1~1で幅が2あるため、幅を合わすために座標の値を全て2倍します。


最後に、範囲を-1~1にあわすために1引きます。これで変換終了です。



次に光源推定について光源がある場合と無い場合で分けて説明していきます。


光源が画像中に存在する場合

画像中に光源が存在すると判定された場合は、その画像座標をそのまま空間座標に変換して光源推定を行います。以下が推定結果です。同じ光源に対して2つの方向から光源推定を行いました。黄色い球体が推定された光源位置になります。

画像 5.2 : 空間画像1

画像 5.3 : 推定結果1


画像 5.4 : 空間画像2

画像 5.6 : 推定結果2


結果に対して考察していきます。
図5.3では実際の光源位置に仮想の光源を推定できていますが、図5.6では少し横にずれています。透視投影変換行列は定数でなので画像座標から現実空間座標への変換の間でずれが生じることはありません。よって画像座標を求める過程でずれが発生していると考察することができます。画像座標についてずれが発生すると考えられるのは以下の処理中だと思われます。


  1. HoloLens で撮った画像をプログラムに取り込む処理
  2. 画像座標の範囲を-1 から1の範囲に正規化する処理

この (1) について空間画像の図5.2の画像サイズは 1408×792 画素です。しかし、座標変換の処理中の画像サイズは2048×1152画素となっている。これは実際の画像をプログラムに取り込む際にプログラムが処理しやすいように自動的に変換されたと思われます。この変換により、元画像と縦横比が多少変わってしまうためずれが生じたと考えることができます。また(2)について画像座標及び画像サイズは int 型から float 型へ型変換した後に画像サイズが−1から1の範囲になるように正規化を行っています。その時に画像中の光源座標を画像サイズで除算を行いますが、その値は多くが無限小数になります。しかし計算結果はfloat型なので表すことができる値には限りがあります。その誤差により座標のずれが発生すると考察することができます。


光源が画像中に存在しない場合

※ここからは実装がまだできていないので、提案手法を示します。

光源が存在しないときは、K-means法で処理した画像を用いて以下の通りで仮想物体に陰影付けを行います。

  1. ① 画像で明るい領域の座標と法線方向を求める
  2. ② 求めた座標と方向から、仮想物体を取り巻く球体に明るさの分布マップを作成
  3. ③ 球体の分布マップから、仮想物体にライティングを行う

ここで②・③にある「球体」について説明するために「Image Based Lighting」という手法について説明する。

Image Based Lightingについて

3Dレンダリングにおける陰影付けにおいて、現実世界の物理法則を忠実に再現する場合は光源の位置から光線を伸ばし、物体などに反射して自分の目(視点)に入ってくる光線を計算しないといけない。しかし、Image Based Lighting(以下IBL)というレンダリング手法は、周囲の光源情報を持った画像を光源として陰影付けを行う手法である。以下の画像5.7のように周囲に画像(画像5.7ではHDRIの360度画像を用いている)を配置し、仮想物体の各面の法線方向の明るさを参照するといったものである。②・③の「球体」は、この仮想物体を取り巻く画像の球体のことである。

画像 5.7


以下はUnityでIBLを試した例です。若干物体の色が背景画像に近い色になってます。(物体の表面の反射率をもっと上げると画像が鏡のように映されます)

デフォルト


参考画像1

IBL結果1


参考画像2

IBL結果2


参考画像3

IBL結果3


ここで本題に戻ります。K-means法から求めた領域の法線方向に光源が存在するとして、球体に光源の分布マップを作ってIBLを行えば、その場に合ったライティングができるのでは、というのが提案手法です。

画像5.8

画像5.9


ここから先はまだ実装ができていないので、進捗があり次第更新します。