1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MoGe-2 で1枚の画像から面の向きと3Dを推定する — Apple Siliconで検証

1
Last updated at Posted at 2026-07-16

MoGe-2 で1枚の画像から面の向きと3Dを推定する — Apple Siliconで検証

こんにちは、皆さん。

1枚の写真から、物体までの距離だけでなく、道路が上を向いている、建物の壁が横を向いている、といった「面の向き」まで取得できると、3D化や照明処理へ使える情報が増えます。

さて、今日は MoGe-2 ViT-S Normal を Apple Silicon で動かし、surface normal の見え方、CPUとMPSの速度、同時に得られる3D情報との整合性を検証しました。

先に結果を書くと、Apple M1 Max のMPSでは推論中央値が 212.13 ms で、CPUの 1,259.34 ms より 5.94倍高速 でした。道路、卓上物体、群衆の3画像で面の向きと物体境界を目視でき、道路、猫、女の子の1枚絵から、カメラを左右へ動かす2.5D動画も作成できました。

MoGe-2とは

MoGe-2 は、Microsoft Research の研究者らが 2025年6月10日 に公開した単眼geometry推定モデルです。単眼とは、ステレオカメラではなく1枚のRGB画像だけを使う、という意味です。論文は同年7月3日に arXiv へ投稿されました。

初代MoGeが画像内の相対的な3D形状を得意としていたのに対し、MoGe-2はメートル単位のscale、細部の鋭さ、normal推定をまとめて強化しています。

surface normal(法線)は、各画素に写る面がどちらを向いているかを表す3次元ベクトルです。この記事のカラフルなnormal画像では、そのx・y・z方向をRGBへ割り当てています。色は物体の種類ではなく、面の向きを示します。

今回検証する内容

公式のnormal対応モデルで最小の Ruicheng/moge-2-vits-normal を使い、次を確認します。

  • Apple M1 Max のCPUとMPSで追加patchなしに動くか
  • 同じFP32モデルでMPSがCPUよりどの程度速いか
  • 道路、卓上物体、群衆のnormalを目視できるか
  • 直接予測したnormalと、3D point mapから計算したnormalがどの程度一致するか
  • point mapをtexture付き3D meshへ変換できるか

MPSは、MacのGPUをPyTorchから使うbackendです。対象のlabはこちらです。

kiarina/labs/2026/07/16/moge2-surface-normal-apple-silicon

検証環境の再現

Apple Silicon Mac、miseuv、初回のモデル・共有画像取得にインターネット接続が必要です。

git clone --depth 1 --filter=blob:none --sparse \
  https://github.com/kiarina/labs.git
cd labs
git sparse-checkout set .gitignore .mise/tasks Makefile mise.toml 2026/07/16/moge2-surface-normal-apple-silicon
mise -C 2026/07/16/moge2-surface-normal-apple-silicon run

初回は固定revisionのcheckpointを取得し、SHA-256を検証します。道路画像からGLBと4秒のBlender動画まで作る場合は、Blender 5.1.2とFFmpegを用意して次を実行します。

mise -C 2026/07/16/moge2-surface-normal-apple-silicon run render-video

使用したモデル、仕組み、ライセンス

使用した学習済みモデルは1つです。複数のAIモデルを順に呼ぶ構成ではありません。1つのcheckpoint内で、画像特徴を読むencoderと、各出力を作るheadが役割分担します。

RGB画像
  -> DINOv2 ViT-S encoder: 画像全体と細部の特徴を抽出
  -> shared neck: 解像度の異なる特徴へ展開
  -> points head: 各画素の3D座標
     normal head: 各画素の面の向き
     mask head: 信頼できる画素
     scale head: メートル単位へ合わせるscale
  -> metric point map / depth / normal / mask / camera intrinsics
  -> (任意)point map + 元画像texture -> GLB mesh

headは、共有した特徴から目的別の値を出す小さな出力部分です。point mapは各画素をカメラ座標系の3D点へ変換したもの、camera intrinsicsは画角や焦点距離に関係するカメラ内部情報です。

項目 固定値
checkpoint Ruicheng/moge-2-vits-normal/model.pt
parameters 35,103,656
file size 140,550,416 bytes
SHA-256 79a16621928c2bf0ed04659218c55c01075e950507f40bb3332fb4c873d3e1dc
Hugging Face revision 679230677b4d282c6f304189a93e98e14f085902
MoGe repository commit 07444410f1e33f402353b99d6ccd26bd31e469e8

ライセンスは次のとおりです。

checkpointそのものはlabへcommitせず、実行時に固定revisionから取得します。再配布や製品組み込みでは、利用時点の公式条件も確認してください。

検証方法

入力は短辺384へ縮小し、resolution_level=5、FP32、batch 1に固定しました。速度は道路画像で3回warm-upした後に10回測定し、モデル・画像の読み込み、前処理、保存は含めていません。warm-upは初回だけ発生する準備処理の影響を減らす事前実行です。

直接予測normalの比較相手は正解データではありません。同じ推論で得たpoint mapの隣接3D点から面の向きを計算し、画素ごとの角度差を測りました。2つの出力が内部でどの程度整合するかを見るテストです。

before / after

左が入力、右がMoGe-2の直接予測normalです。

道路

道路画像とMoGe-2が推定したsurface normalのbefore/after

路面、左右の建物、自動車、樹木が異なる向きとして分かれました。空は無効領域として黒くなっています。

卓上物体

卓上物体画像とMoGe-2が推定したsurface normalのbefore/after

机や本の広い面は色がまとまり、カップとボトルでは曲面に沿って色が連続的に変わりました。

群衆

群衆画像とMoGe-2が推定したsurface normalのbefore/after

顔や肩の丸み、重なった人物の境界が残りました。一方、遠景や細かな人物には不安定な縞も見られました。

検証結果

CPUとMPSの速度

backend mean median min max std dev
PyTorch CPU 1,272.74 ms 1,259.34 ms 1,244.37 ms 1,340.16 ms 28.24 ms
PyTorch MPS 211.58 ms 212.13 ms 208.75 ms 214.68 ms 1.88 ms

中央値ではMPSがCPUより 5.94倍高速 でした。MPSの約212 msは、モデル推論だけなら約4.71 FPSに相当します。同じ入力に対するCPUとMPSのnormal角度差は平均0.0063度、中央値0度、最大0.0396度でした。

記事執筆時に同じコマンドで再実行すると、CPUの中央値は1,299.96 ms、MPSは175.88 msで、MPSが7.39倍高速でした。model hash、normal角度差、3画像の整合性データは元の測定と一致しました。推論時間は実行時の状態で変動するため、速度は単一の固定値ではなく、今回の2回の測定範囲として見る必要があります。

2種類のnormalの整合性

image valid pixels mean median p90
street 90.80% 30.75° 18.69° 78.55°
objects 100.00% 14.41° 7.05° 35.86°
crowd 98.63% 37.94° 33.04° 73.47°

卓上画像の広い平面ではよく一致し、物体境界、細い構造、樹木、群衆、遠景で差が大きくなりました。point map側のnormalは隣接画素の差から計算するため、奥行きが急に変わる境界をまたぐと崩れやすくなります。この角度差を、直接予測normalの精度とは断定できません。

3枚の画像を3D動画に変換

公式CLIでpoint mapを三角形へ変換し、元画像をtextureにしたGLBを生成しました。さらにBlenderで元のカメラ位置から左右へ移動し、視差が見える4秒の動画にしました。

掲載しているAPNGは表示用に512x288、10 FPSへ軽量化しています。labには1280x720、30 FPSの元MP4が生成されます。

車のある道路

MoGe-2で1枚の道路画像を2.5D化してカメラを左右へ動かした動画

手前の自動車、道路、左右の建物、人物の間に視差が出ました。カメラを横へ動かすだけでも、1枚の画像が奥行きを持つsurfaceへ変換されたことが分かります。

vertices: 233,120
triangles: 449,292
dimensions: 約30.75 x 114.21 x 21.15 m
estimated horizontal FoV: 60.52°
GLB size: 13,342,320 bytes

猫のキャラクター

MoGe-2で猫のキャラクター画像を2.5D化してカメラを左右へ動かした動画

ピンクの猫が木、ベンチ、花壇より手前へ配置され、はっきりした視差が出ました。頭部には緩やかな丸みがありますが、耳、手、蝶ネクタイ、胴体はカメラから見えていた面を中心にした薄い形です。

女の子のキャラクター

MoGe-2で女の子のキャラクター画像を2.5D化してカメラを左右へ動かした動画

女の子、ベンチ、街灯、看板、背景の木々が異なる奥行きへ分かれました。一方、髪、腕、脚は独立した完全な立体ではなく、輪郭に沿う薄いsurfaceとして見えます。

3つのmeshの実測値です。

image vertices triangles FoV x / y GLB size
street 233,120 449,292 60.52° / 32.53° 13,342,320 bytes
cat 312,105 599,514 54.27° / 42.05° 17,893,416 bytes
girl 325,649 621,216 60.30° / 47.08° 18,731,304 bytes

道路ではカメラを左右へ±0.8 m、猫と女の子では被写体が近く推定されたため±0.5 m動かしました。これは見えている面を奥行き方向へ配置した 2.5D です。2.5Dとは、元視点の近くでは立体的に見えても、物体の裏側まで復元した完全な3Dではない、という意味です。

3例とも小さな視点移動には使えましたが、空、木の葉、髪、物体境界ではtriangleを除去した黒い穴が見えます。写実画像だけでなくアニメ調画像も動かせる一方、細い輪郭やstylized shapeの3D解釈には限界がありました。

試行中にわかったこと

最初はdepth画像の上下左右の差だけからnormalを作り、角度差の中央値が113〜143度になりました。この方法は透視投影とカメラ内部情報を無視していました。metric point mapの3D点から計算する方法へ変えると、比較可能な向きになりました。

また、公式実装はCPUとMPSでFP32 autocast未対応のwarningを出しましたが、autocastが自動的に無効になり、patchなしで推論は完了しました。

検証環境は次のとおりです。

machine: MacBook Pro (Apple M1 Max, 64 GB, arm64)
OS: macOS 26.5.2
Python: 3.12.10
PyTorch: 2.13.0
OpenCV: 5.0.0
NumPy: 2.5.1
Blender: 5.1.2
FFmpeg: 8.1.2

結果の考察

専門的な数値は上に載せたとおりですが、簡単に読むと次の3点です。

  1. MacのGPUで実用的に待てる速度になった

    MPSでは1枚約176〜212 msでした。リアルタイム動画にはまだ遅いものの、画像編集や3D化の前処理なら使いやすい速度です。

  2. 1回の推論から複数の3D情報を得られた

    depthだけでなく、metric point map、normal、mask、camera intrinsicsが同時に得られます。別モデルをつなぐ必要がなく、各出力を組み合わせやすい構成です。

  3. 境界と見えない面には限界がある

    normalは広い面や曲面を捉えましたが、細い構造や遠景は不安定でした。1枚の画像から作るmeshも、裏側を含む完全な3D空間ではありません。

本検証は正解normal・depthのない生成画像3枚、速度測定は道路画像1枚、短辺384、FP32、1台のM1 Maxに限られます。公式benchmark、実写、ViT-B/L、FP16、Core ML、Apple Neural Engine、動画の時間的一貫性、消費電力、正解データに対する精度は未検証です。

検証後の感想

1枚の画像から道路の向き、物体の丸み、メートル単位のpoint mapまで一度に得られるのは、思っていた以上に扱いやすい結果でした。特に、normal専用headの出力はpoint mapから単純計算したものより境界が滑らかで、直接予測する意味が見えました。

一方、3D meshは小さく視点を動かす用途には面白いものの、自由に歩き回れる空間ではありません。

1枚の絵にほんの少し視点の動きを加えたいとき、こんな使い方も楽しそうですね。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?