# 視覚情報特論 期末レポート (公開版)
###### tags: `Class`
## 1. このレポートについて
このレポートでは、視覚情報特論で学んだ画像処理技術についてさらに学びを深めるべく、画像処理を用いた応用技術であるNeRF(3D スキャン技術)についてどのように実装されているのかを調査した結果を述べる。また、実装の理解を基にNeRFを使用して3Dスキャンを行いNeRFについてさらに理解を深める。なお、今回はLumaAIと呼ばれるNeRFを用いた3Dスキャンサービスを用いるため、LumaAIにおけるNeRFの実装について述べる。
このレポートの提出はTexやWordなどのよく用いられるものではなく、HackMDというマークダウン記述式のWebサービスを用いて作成したWebページによって行う。これは後述するNeRFによるスキャン結果をより効果的に示すためである。
## 2. NeRFの概要
NeRFとは、Neural **Radiance Field**の略である。
### 2.1 Radiance Fieldとボリュームレイキャスティング
そもそもRadiance Fieldとは、「ある位置と方向」からある点を見た時に「どんな色と密度」に見えるかを大量に記録した三次元空間のデータである。Radiance Fieldを用いて画像をレンダリングする際には、ボリュームレイキャスティングと呼ばれる手法が用いられる。
ボリュームレイキャスティングでは、ある位置におけるカメラから光線(レイ)を発射(キャスティング)して、光線が通過した三次元空間(ボリューム)内の点群が持つ情報からレンダリングされる画像の各ピクセルごとの値を決定する方法である。各ピクセルごとの値は光線が通過した点群における色と密度によって決定される。(参考:wikiwand , ボリュームレンダリング , https://www.wikiwand.com/ja/%E3%83%9C%E3%83%AA%E3%83%A5%E3%83%BC%E3%83%A0%E3%83%AC%E3%83%B3%E3%83%80%E3%83%AA%E3%83%B3%E3%82%B0 , 調査日:2023/08/07)
### 2.2 Neural Radiance Field
2.1節で述べたように、Radiance Fieldは「ある位置と方向」からある点を見た時に「どんな色と密度」に見えるかを大量に記録した三次元空間のデータである。しかしながら、「すべての方向」から「どんな色と密度」に見えるかの情報を記録するためには膨大な手間と時間をかける必要があり、これを実現するのは非常にコストがかかる。
そこで、畳み込み層を持たない**Neural** Networkを用いることで複数の「ある位置と方向」から見たときの正解データを学習し、正解データとして与えられていない未知の「ある位置と方向」からの見え方について推定することができるようにする。これがNeural Radiance Fieldである。以下にNeRFのシーン表現方法について説明した画像を示す。

画像1:NeRFのシーン表現方法と差別化されたレンダリング手順の概要(Ben Mildenhall et. al., NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis, https://arxiv.org/abs/2003.08934, 調査日:2023/08/07 より)
### 2.3 補足
2.1および2.2節で説明した内容ついてはNeRFの研究者であるBen Mildenhallらが公開している動画が直感的に理解しやすいのでここに引用する。
{%youtube JuH79E8rdKc %}
動画1:NeRF: Neural Radiance Fields(Matthew Tancik, NeRF: Neural Radiance Fields, https://www.youtube.com/watch?v=JuH79E8rdKc, 調査日:2023/08/07)
## 3. 画像から特徴点を抽出するしくみ
正解データを作成するため、入力された複数枚の画像から特徴点抽出を行い、複数画像における特徴点の位置関係の変化からカメラ位置の推定を行う。各画像における画像のピクセルごとの値と推定されたカメラ「位置と方向」を正解データとしてNeRFに入力し、未知の「位置と方向」について推定する。
特徴点抽出やカメラ位置の推定について、具体的にどのようなアルゴリズムが用いられているかについては公開されていないが、ここでは代表的な方法についてMATLABのコードを交えて述べる。
### 3.1 SURF
特徴点抽出のアルゴリズムとして代表的なものにSpeeded-Up Robust Features (SURF) アルゴリズムがある。SURFはガウシアンフィルタによって平滑化した画像の変化を見ることで特徴的な点を調べていく方法である。同様の機能を持ったScale-Invariant Feature Transform (SIFT)と比較して、ガウシアンフィルタの実装をSIFTはガウス差分を用いて行っているのに対して、SURFはボックスフィルタを用いて行っておりより計算量が小さく済む。
### 3.2 SfM
カメラ位置や向きの推定はStructure from Motion (SfM)と呼ばれる技術を用いて行われることが多い。SfMは一連の二次元画像から三次元空間における構造を推定する技術である。なお、MATLABでの`matchFeatures`関数はデフォルトでは画像間のペアワイズ距離を計算するExhaustive法によって計算が行われている。
### 3.3 MATLABにおける特徴的マッチングの実装
例としてMATLABにおける特徴点マッチングのソースコードを記載する。
```matlab=
% あるオリジナル画像
original = imread('image.tif');
% オリジナル画像を変形したもの
distorted = imread('image_distorted.tif');
% 特徴点の検出
ptsOriginal = detectSURFFeatures(original);
ptsDistorted = detectSURFFeatures(distorted);
% 特徴点記述子の抽出
[featuresOriginal,validPtsOriginal] = extractFeatures(original,ptsOriginal);
[featuresDistorted,validPtsDistorted] = extractFeatures(distorted,ptsDistorted);
% 記述子によるマッチング
indexPairs = matchFeatures(featuresOriginal,featuresDistorted);
```
(参考:MathWorks , 自動特徴マッチングを使用したイメージの回転とスケールの検出, https://jp.mathworks.com/help/vision/ug/find-image-rotation-and-scale-using-automated-feature-matching.html , 調査日:2023/08/07)

画像2:特徴点の対応(MathWorks , structure from motion の概要, https://jp.mathworks.com/help/vision/ug/structure-from-motion.html , 調査日:2023/08/07)
## 4. LumaAIにおけるNeRFの利用
[LumaAI](https://lumalabs.ai/)はPC版とios版があるが今回はPC版について述べる。LumaAIは動画またはZIP化された複数枚の画像からNeRFを用いて3Dスキャンを行う(ように見せる)サービスである。
### 4.1 NeRFの特性から考える3Dスキャンを成功させるための工夫
#### 4.1.1 カメラの移動について
3章で述べたように、NeRFに入力する正解データのために特徴点マッチングを行う必要がある。LumaAIにおける特徴点のマッチングは自動で行われ、手動で修正を行うことができないためにできるだけ**手ブレを起こさないようにする**必要がある。
また、カメラ位置の推定は各画像におけるカメラの視差を利用して行われる。つまり撮影する際にはその場でターンするような動きを避け、**前後左右に平行移動するような移動をする**必要がある。
#### 4.1.2 撮影の時間帯について
日中、特に晴れている日には撮影する画像は影の影響を強く受ける。今回はLiDARなどを使用せず画像の情報のみにより特徴点マッチングを行うため、画像中に影が入っているとうまく特徴点を抽出することができない可能性が高まる。撮影の際には**影のない曇りの日か薄明・薄暮の時間帯に行う**とよい。
また、近年のカメラやスマートフォンには自動露光機能が備わっている。これは撮影環境の明るさに対して自動で画面の明るさを調整する機能であるが、特徴点マッチングを行う際には同じ特徴点は同じ画素値であることが望ましいため**自動露光機能をオフ**にしておくとよい。
### 4.2 3Dスキャンの実践
#### 4.2.1 撮影機材
撮影機材は魚眼レンズでの広角撮影が可能なInsta360 ONE RS 1インチ 360度版および自身が以前から所有しているスマートフォン(Xiaomi Mi Note 10 Lite)を用いた。
カメラ性能は以下の通りである。
| 名称 | 画素数 | f値 | レンズ | fps(最大) |
| -------- | -------- | -------- | -------- | -------- |
| Insta360 ONE RS 1インチ 360度版 | 2,100万画素 | 2.2 | 広角 | 60fps |
| Mi Note 10 Lite | 6,400万画素 | 1.89 | ワイド | 60fps |
#### 4.2.2 撮影環境
撮影は愛知県立大学長久手キャンパスのC棟横駐車場前からA棟前の道路脇を往復する形で行った。撮影は4月から5月にかけて行った。撮影時間帯は4.1.1節で述べた通り、撮影は影のない曇りの日か薄明・薄暮の時間帯に行った。また、大学構内での撮影であるため大学利用者に配慮して、利用者の多い1限~4限および登下校の時間帯(8:00~16:30)の時間帯には撮影を行わず、午後に授業のない水曜日に集中して撮影を行った。

画像3:撮影時の移動範囲(Google Map , 愛知県立大学長久手キャンパス , https://www.google.co.jp/maps/place//@35.1813849,137.0876683,18z?entry=ttu , 調査日:2023/08/07)
#### 4.2.3 撮影方法
LumaAIが推奨する方法で撮影を行った。以下に推奨されている撮影方法を示す。なお、3回ループしたときの撮影時間は約15分ほどであった。
撮影時のカメラの高さ:以下の3つの高さからループで撮影するのが理想的。
1. 胸の高さで前を向く
1. 頭の少し上でシーンの中心を少し下に向く
1. 膝の高さで少し上に向く
その他の注意点:
* 動画撮影時のHDRを無効にする.
* ループで回って、シーンやオブジェクトを捉える
* ブレを抑えるためにゆっくり撮影する
* 通常の動画と魚眼動画のどちらかをアップロードすることができる
* 動画の最大サイズは5ギガバイト
(参考:Luma AI Inc , Luma AI Dashboard , https://lumalabs.ai/dashboard/captures , 調査日:2023/08/07)
## 5. LumaAIによる3Dスキャンの結果と考察・改善
### 5.1 【失敗】Insta360 ONE RS 1インチ 360度版による撮影画像を入力した結果
LumaAIの入力動画には魚眼レンズを用いて撮影した動画を入力することが出来るため、Insta360 ONE RS 1インチ 360度版を用いて撮影した動画を入力した。3回ほど撮影を行い入力を行ったが、どの結果も以下の動画のように物体の構造をうまくとらえられずぼやけたスキャン結果となった。LumaAIでの処理は自動で行われるため詳細は定かではないが、魚眼レンズの較正がうまくいっておらず歪んだ画像が入力データとして使われた可能性が考えられる。
{%youtube BviLMqzORVM %}
動画3:魚眼レンズを用いて撮影した動画を入力した結果
` `

画像4:物体の構造を再現することに失敗しているスキャン結果
### 5.2 Mi Note 10 Liteによる撮影画像を入力した結果
魚眼レンズを用いて撮影した動画では期待するスキャン結果を得ることができなかったため、自身が所有するスマートフォンを用いて撮影した動画をNeRFへの入力として使用することにした。
#### 5.2.1 【失敗】推奨されている3回ループした動画を入力した結果
3回ループした動画を入力した結果、画像4に示す通り特徴点のマッチングが失敗していると思われるスキャン結果となった。各ループごとにスキャンされた結果はある程度うまくいっているように見えるものの、ループごとの点群の位置の対応は取れておらず同じ個所のスキャン結果が異なる位置に存在している。これはおそらくループごとの切り返しにおいてカメラ位置の推定がうまくいかなかったためであると考えられる。
{%youtube c1yJ2LJ9GVQ %}
動画3:推奨されている3回ループした動画を入力した結果
` `

画像5:特徴点のマッチングに失敗しているスキャン結果
#### 5.2.2 【成功】3回ループした動画のうち、1回目のみを入力した結果
3回ループした動画を入力した結果、ループごとの切り返しにおいてカメラ位置の推定がうまくいっていないのではないかと考察した。しかし、各ループごとのスキャン自体はうまくいっているように見える。そこで3回ループした動画から1回目のループのみを切り出し入力することにした。結果は以下の通りNeRFの出力結果に特有のフォグは見られるものの、撮影した動画に写っている範囲のスキャンでは期待した結果が得られた。
{%youtube OoAbTJDKdLw %}
動画4:推奨されている3回ループした動画から1回目のみを入力した結果
` `

画像6:期待した結果となったスキャン結果
#### 5.2.3 【失敗】3回ループした動画のうち、2回目のみを入力した結果
3回ループした動画から1回目のみを切り取って入力した動画がうまくいったため、2回目のみ切り取ったものについても入力することにした。結果は以下の通り特徴点のマッチングに失敗し道路と街路樹が一体化したようなスキャン結果となっている。なお、3回目のみを入力した結果についても同様であった。この結果となった理由として考えられるのはやはり動画中の回転方向への移動である。
{%youtube Ekq0OPCENbo %}
動画5:推奨されている3回ループした動画から2回目のみを入力した結果
` `

画像7:特徴点のマッチングに失敗しているスキャン結果
#### 5.2.4 【成功】3回ループした動画のうち、2回目のみかつ回転する場面をカットした動画を入力した結果
以上より、動画の入力の際には極力回転方向への移動は避けた方がよいという仮説を立てた。そこで、先ほどスキャンに失敗した3回ループした動画のうち2回目を動画編集ソフトを用いて編集し、回転方向への移動が含まれない部分のみを切り出した動画を入力として用いることにした。結果は以下の通りフォグ等も少なく今までのスキャンで最も正確に路面や建築物の構造を正確に再現したものとなった。
{%youtube e_0VrjSZKIA %}
動画6:3回ループした動画から2回目のみを切り取り、その中からさらに回転方向への移動を行っていない範囲を切り出して入力した結果
` `

画像8:期待した結果となったスキャン結果
## 6. まとめ
今回のレポートでは、NeRFについてその仕組みを学んだうえで、LumaAIを利用して実際に3Dスキャンを行いNeRFの特性をより深く理解することを目指した。
NeRFやその入力の前処理には、視覚情報特論で学んだ様々な画像処理の応用技術が含まれていたが、その多くは基本的な画像処理アルゴリズムを基に発展させた内容であり、改めて基本的な画像処理アルゴリズムを理解することの重要性を感じた。
また、3Dスキャンの実践では事前に考えていたよりもカメラを回転させないよう平行移動することが重要であり、理論だけではつかめない感覚的な3Dスキャンのコツについて理解することができた。
最後に、今回学んだLumaAIを用いたNeRFによる3Dスキャンは使い方によっては非常に便利なツールであるため今回の知見を活かして今後の自身の研究に取り入れていきたい。
## 7. 付録
今回LumaAIの入力のために用いた動画を添付する。
なお、アップロードの関係で一部省略している箇所がある。
### 7.1 Insta360 ONE RS 1インチ 360度版による撮影動画
{%youtube herbo7qp8Sc %}
### 7.2 Mi Note 10 Liteによる撮影動画
{%youtube I0FFA_EelIQ %}