Contents — 10 sections
公開写真だけで、東大寺南大門をどこまで3D化できるか試した。
候補画像を165件集め、123枚を取得し、重複や低解像度、ブレなどを落として83枚まで絞った。
COLMAPでSfMを回すと、それらしい点群ができた。最初は順調に見えた。
ただ、カメラ位置を確認するとおかしい。
北側から撮られたはずの写真が、南側のカメラとして並んでいた。
建物が壊れたのではなく、SfMが北面と南面を同じ面として扱っていた。
83枚あっても、視点が偏っていれば足りない
入力した83枚は、撮影者40名、撮影年1999〜2023年の公開写真だった。
採用したライセンスは CC BY / CC BY-SA / CC0 / Public Domain に限定した。
画像選別では、
- pHashによる重複
- 1000px未満
- 極端な縦横比
- ブレ
- 魚眼・円筒投影
などを落とした。
枚数だけ見れば十分に思える。
しかし観光写真は、撮られる場所が偏る。
南大門の場合、写真の多くが参道の軸線上、方位でいうとおよそ±7°へ集中していた。
つまり「83枚ある」のに、東西側面を見る写真がほとんどない。
この偏りは後でSide fidelityの低さとして、そのまま返ってきた。
一括SfMで前後面が混ざった
83枚を一括でMappingしたところ、北面写真14枚が南面側へ誤登録された。
南大門は前後がかなり似ている。
柱、軒、組物、開口のパターンが似ていれば、画像特徴だけでは「似た別の面」と「同じ面」を区別しにくい。
今回の失敗は、いわゆるDoppelganger問題だった。
面白いのは、再投影誤差だけを見ていると「それなりに正しそう」に見えることだ。
数値が低いから正しい、とは限らない。
誤った面に対しても、画像特徴の対応がうまく合えば、低い誤差で整合してしまう。
だからカメラ位置そのものを見る必要があった。
南面だけにある扁額を手掛かりにした
南面には扁額がある。
そこで扁額の3D位置を写真へ投影し、南面か北面かを分ける材料にした。
自動判定だけで確定できないものは目視も併用した。
南北を分けて再Mappingした結果、
- 南面: 38 / 55枚
- 北面: 16 / 16枚
が正しい面へ登録された。
全83枚に対して正しい面へ登録された枚数は54枚、65.1%。
平均再投影誤差は、
- 南面: 1.18px
- 北面: 0.75px
だった。
ただし、この回避策は南大門固有の扁額に依存している。
汎用的な対称誤登録の解決法ではない。
ここは成功談に変換しないで、そのまま制約として残す。
GPUなしだったのでDenseはOpenMVSへ逃がした
実行環境は、
- Ubuntu 24.04
- Intel Xeon 2.1GHz
- 4 vCPU
- RAM 16GB
- GPUなし
だった。
COLMAPのDenseをそのまま使うにはCUDAが問題になったため、OpenMVS v2.2.0をCPUでビルドして使った。
最終的なDense pointは、
- 南面: 941,404 points
- 北面: 288,364 points
Raw Meshは、
- 南面: 427,821 faces
- 北面: 258,462 faces
まで作れた。
計算時間の合計は約1.2時間。
ただし、実際の経過時間はもっと長い。
画像取得中にWikimediaのCDNで429を踏み、約4時間止まった。
規約を迂回するような取得方法は使わず、最終的にはローカルPCで画像を取得した。
3D復元より先に、画像取得で止まるとは思っていなかった。
実寸は1点だけ使ってスケールを合わせた
外部の実寸値として使ったのは、間口28.79mの1点だけ。
これを柱芯の総長として解釈し、全体のスケールを合わせた。
そこからSfMや写真を使って、
- 柱間: 5.34 / 6.13 / 5.84 / 6.13 / 5.34m
- 基壇: 約1.0m
- 下層軒先: 約12.1m
- 上層軒先: 約18.7m
- 棟の上端: 約26.9〜27.1m
- 扁額: 約4.2 × 1.45m
などを得た。
ただし、ここでも「測れたもの」と「推定したもの」を混ぜないようにした。
モデル側には、可能な範囲で observed / estimated の区別を持たせた。
見えていない内部空間を、見栄えのためだけに創作することもしなかった。
最終モデルはゲーム向けLODまで落とした
最終Meshは、
- LOD0: 24,470 tris
- LOD1: 7,862 tris
- LOD2: 1,454 tris
まで落とした。
出力は、
- GLB: 12.7MB
- FBX: 10.2MB
- Texture: 1024² × 12枚
になった。
Textureは写真投影ではなく、実写から色相を拾った手続き生成。
風化、汚れ、丹塗りの残りなどを忠実に再現したものではない。
正面はかなり合った。側面はまだ弱い
比較5視点では、SfM点がモデルのシルエット内へ入る割合が93.3〜99.5%。
正面の点群とモデル面の距離中央値は約0.155mだった。
正面はかなり合っている。
背面も一定の一致は出た。
ただし北面は、南面で較正したモデルへICPで合わせている。
つまり完全に独立した品質評価ではない。
さらに側面は弱い。
観光写真が参道方向へ偏り、側面写真が十分に登録できなかったため、東西側面の多くは推定になった。
失敗は10個残した
このPoCでは、うまくいかなかったこともそのまま記録した。
- Wikimedia CDNで429
- 南北面のDoppelganger
- 北面の鉛直方向が4.9°傾く
- 軒下・内部・極端な近接写真17枚が登録できない
- 側面入力不足
- 人・鹿・暗い開口で地上階の点群が疎
- z=0基準に不確かさ
- GPUなしでCOLMAP Denseを使えずOpenMVSへ
- 幕・幟・灯籠など一時設置物
- 写真投影Texture未実装
特に対称誤登録は、合成データでも同種の現象を再現した。
偶然ではなく、構造的なリスクだった。
このPoCで足りなかったのは「もっと強いAI」ではなく入力画像だった
PoC判定は CONDITIONAL GO。
正面・背面の主要形状は作れた。
LOD化してGLB / FBXまで出せた。
比較数値もある程度出た。
一方で、側面は弱い。
対称誤登録の汎用解もない。
写真投影Textureも未実装。
次の改善要因はアルゴリズムより、入力画像の不足だった。
そのため次フェーズは現地撮影。
撮影仕様は約370枚、約1.5時間。
- 外周2周
- 35m / 20mの2距離
- 5°刻み
- 隣接画像70%以上overlap
- 各立面80%以上overlap
- 側面で間隔を空けない
成功目標は、
- 登録率90%以上
- 単一モデル
- 周回カメラ360°連続
- 側面の点群-モデル距離中央値0.10m以下
- 全体中央値0.10m以下
- 対称誤登録0件
とした。
いまの結論
Photogrammetryは、画像枚数を増やせば勝てるわけではなかった。
今回一番効いたのは、
何枚あるかより、どこから撮られているか。
そしてもう一つ。
低い誤差で綺麗に間違っている結果は普通に出る。
自動化するほど、結果を疑う仕組みが必要になる。
PicoTowaでは、こういう「それっぽく成功している失敗」をできるだけ残していく。