RealityCapture intrinsic / extrinsicパラメータ

「instantNeRFで遊ぶ Advent Calendar 2022」の14日目です。

今日は「RealityCaptureのregistrationデータを流用する検討」の課題2として、RealityCapture intrinsic / extrinsicパラメータについて調べました。

:::note
業務外の個人的な検討活動です。
間違っていても責任はとれません。
間違っていたらできましたらご指摘ください。
:::

#### テストデータ
sketchfabのNefertiti statueを使用させていただきました。ありがとうございます。

https://sketchfab.com/3d-models/nefertiti-statue-d148f771c3f44225b56cb7ce8d3c5ce6

objファイルをBlenderへ取り込み、所定の位置に配置したカメラの画像をrenderしました。

![14-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/d05eef33-6c6b-4383-00f3-d5fffea39c2c.png)

6枚の画像をRealityCaptureに取り込み、カメラの焦点距離と座標を入力しました。

カメラの座標はカメラを選んでいるときの1Dsに出るPrior poseのAbsolute poseをpositionにして入力しました。
![14-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/f42956bc-d3d4-5ecf-c5d4-78556a7ae3c2.png)


#### intrinsic
RealityCaptureが出力するカメラの内部パラメータは焦点距離、主点位置、歪係数です。
ここで焦点距離は画角からフルサイズセンサに換算した値（単位はmm）、主点距離はセンサ中心からのずれ（単位はmm）、歪係数はcamera modelの設定に対する値（単位は無次元）です。

主点距離の変化を確認するため、X, Y軸方向に150, 50pixずらした画像をRealityCaptureに入力しRegistrationを出力しました。
![cam1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/f213b497-7a5b-03da-2d6e-4c22e45bb37a.png)

なお、今回の2Kサイズ画像6枚の使用料は4cregit $0.01、約2円でした。
![14-8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/bc0e2f37-71be-ea67-2080-cc49da57deb9.png)

ここで気が付いたのはpx, pyの値が画面の1Dsの表示と異なることです。
2.48 / 36 = 0.0692なので画面に表示されている数字をフルサイズの横幅36で割るとexportの値になるようでした。

![14-9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/0a604a08-caea-81d4-79f4-e8ec0af082f2.png)

焦点距離と主点位置をpixel単位に変換した検算結果がこちらです。

![14-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/43be7cc5-cda8-3999-4272-8853fef3898c.png)


同じ画像群をCOLMAPへ入力した焦点距離と主点位置の解析結果と検算結果がこちらです。
誤差があるので今後の課題です。

COLMAPの結果　images.txt
![14-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/9afe342b-8a6f-a3e7-f20a-123d5a696d50.png)



#### extrinsic
カメラの座標はCatpturingRealityのフォーラムに記載してありました。右手座標系のようです。
ただGizmoは回転中に反転するので注意が必要です。

https://support.capturingreality.com/hc/en-us/articles/5329988829724-Differences-between-exported-coordinate-systems-in-RealityCapture

> 軸の向きは（上から見たとき）。Yは北を向いており、緑の矢印、Xは東を向いており、青の矢印、Zは上を向いており、赤の矢印です。
(DeepLで翻訳しました　https://www.deepl.com/translator)

Gizmoを見ていると回転中に前後が分からなくなったので、NumPADの数字で指定した3Dsのビューを見てカメラの向きの変化を判断しました。上段左が"2"のTopビュー、下段の左から"7","4","6"を押したときのsideビューです。この図ではsideをfront, right, backに分けました。

![14-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/748446d2-e7cc-9b53-6b55-4c25a6fa1c3e.png)

Registrationを押してカメラパラメータをexportしたところ、カメラの座標の出力結果はRealityCapture内のカメラの座標とほぼ同じでした。
![14-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/6914e33e-a52d-e04e-d639-138250845b53.png)

次にカメラの向きについて、回転する軸と順番を調べました。

公式のFAQに説明にあったBlenderでの設定の仕方も参考にしました。

https://support.capturingreality.com/hc/en-us/articles/360020679799-How-to-work-with-RealityCapture-registration-export#article-comments

> 次にBlenderで回転モードを "YXZ Euler "に設定します。
X = pitch, Y = roll, Z = negative heading
(DeepLで翻訳しました　https://www.deepl.com/translator)

ここでBlenderの回転モードの表記の順番は実際に回転させる順番と反対でしたので、YXZモードの場合はZ,X,Yの順番に回転させるようです。

https://docs.blender.org/manual/en/latest/advanced/appendices/rotations.html#euler-modes

> これら（Euler rotation）のモードは、軸のアルファベットを順番に使って命名されており、階層の一番下にある軸から始まって、一番上にある軸で終わります。
(DeepLで翻訳しました　https://www.deepl.com/translator)

<iframe width="560" height="315" src="https://www.youtube.com/embed/T5G0wlw-bx4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

以下、ポップアップの表記とは異なる結果になりましたが、挙動を調べた画面の様子です。

##### 回転1番目 yaw Z軸・右ねじの逆方向
![14-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/4922fe93-6813-dcf9-1ead-cf0e44079324.png)

##### 回転2番目 pitch X軸・右ねじの順方向
![14-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/9d325b90-2ed7-9057-e388-b1c3623dda94.png)

##### 回転3番目 Roll Y軸・右ねじの順方向
![14-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/64c0edba-36f1-72d7-76b5-b96934d1a3e8.png)

#### 閑話休題　Euler角の説明図
Euler角の説明図を探すと飛行機を例にしているものが多く見つかりましたが、回転の名前をカメラに当てはめようとすると混乱するかもしれません。
飛行機の場合は進行方向をXにして尾翼が伸びている方向をZとするのに対して、カメラの場合は画像の右方向をXと下方向をYとするとレンズが向いている方向をZにすることになります。
回転は飛行機のrollは進行方向がX軸、pitchがY軸、yawがZ軸になります。
対してカメラの場合のrollはレンズの方向のZ軸、pitchはX軸、yawはY軸になります。

![14-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/a929b274-8e1e-ca21-bdb5-e46133faf7fd.png)


:::note
このBlenderのモデルのCamera（視錐台）は組み合わせるときに座標を反転・回転させています。
:::

#### まとめ
- 座標系はCOLMAPと同じ　右手系
- intrinsicは単位がmm　COLMAPと合わせるためにはフルサイズのセンササイズを使って換算する必要がある
- extrinsic
    - カメラの向きはZXY軸の順番　内因性のオイラー角　ただしZだけは逆回転
    - カメラの位置は座標の値そのまま