軽量な深度推定 ZipDepth を Apple Silicon で動かす
こんにちは、皆さん。
1枚の写真から、手前と奥を見分けられたら便利ですよね。背景ぼかしや3D表現、ロボットの周辺認識など、深度情報にはいろいろな使い道があります。
さて、今日は軽量な深度推定モデル ZipDepth を Apple Silicon で動かし、PyTorch CPU、PyTorch MPS、ONNX Runtime CPU の速度と出力を比較します。
先に結果を書くと、Apple M1 Max では MPS が平均 15.34 ms で最速でした。同じ通常版モデルの PyTorch CPU より約5倍高速です。3種類の画像でも、手前と奥の関係をわかりやすく出力できました。
今回検証する内容
深度推定は、画像の各画素がカメラからどのくらい手前か、奥かを予測する処理です。今回は1枚のRGB画像だけを使う「単眼深度推定」を試します。
- ZipDepth を Apple Silicon の CPU と GPU で実行できるか
- NPU互換版を ONNX へ変換して実行できるか
- backendごとの推論時間と出力差
- 道路、卓上、群衆で前後関係を捉えられるか
検証に使った道路画像です。
対象の lab: kiarina/labs/2026/07/15/zipdepth-apple-silicon
検証環境の再現
mise と uv、Apple Silicon Mac、初回のモデル・共有画像取得にインターネット接続が必要です。
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/15/zipdepth-apple-silicon
mise -C 2026/07/15/zipdepth-apple-silicon run
初回は checkpoint を取得して SHA-256 を検証し、NPU互換版を ONNX opset 18 へ変換します。速度測定と比較画像の生成まで task に含まれています。
ZipDepthとは
ZipDepth は、2026年7月に論文が公開され、ECCV 2026 で発表された単眼深度推定モデルです。パラメータ数は610万、384x384入力で3.0 GMACsと小さく、サーバーGPUからモバイル端末までの実行を狙っています。
出力は相対的な inverse depth です。この記事の画像では、明るいほど手前、暗いほど奥を表します。ただし「3メートル」のような実距離は出ません。
モデルは、Depth Anything V2 Large が作った擬似深度を教師データとして、17領域、約1,407万枚の画像から知識蒸留されています。知識蒸留とは、大きなモデルの予測を使って、小さなモデルを学習する方法です。
データの流れを短く表すと次のようになります。
学習時(ZipDepth作者による事前学習)
RGB画像 -> Depth Anything V2 Large -> 擬似深度 -> ZipDepthを学習
今回の推論
RGB画像 -> 短辺384へ縮小 -> ZipDepth -> inverse depth map
-> 色を付けて可視化
Depth Anything V2 Large は学習時の教師役です。今回の lab では動かしていません。
使用したモデルとライセンス
ZipDepth には、出力を元の大きさへ戻す方法が異なる2つの checkpoint があります。
| checkpoint | 役割 | 実行先 |
|---|---|---|
zipdepth_base.pth |
通常版。Unfold を使って拡大する |
PyTorch CPU / MPS |
zipdepth_base_npu.pth |
変換しやすい unfold-free 版 | PyTorch CPU / ONNX Runtime CPU |
MPS は Apple Silicon の GPU で PyTorch を動かす backend です。NPU互換版という名前ですが、今回は Apple Neural Engine ではなく CPU で実行しています。
- ZipDepth のコードと checkpoint: MIT License
- 使用 commit:
a302e5437bc58f15c4efd41d3e8222bf24f7d470 - 通常版 SHA-256:
a55910bb0b99c8c5e641cb9206e810b269690ad94e8a2ef08c827c4679391a65 - NPU互換版 SHA-256:
627c04fda584133ead4310074884a4a037061b4c01ba86e73e492ea30fab570d
学習時の教師である Depth Anything V2 Large は CC BY-NC 4.0 です。Small だけは Apache-2.0、Base / Large / Giant は CC BY-NC 4.0 とされています。今回配布・実行するのは MIT License の ZipDepth checkpoint であり、Depth Anything V2 Large の checkpoint は取得しません。
検証方法
画像は縦横比を保ち、短辺を384画素へ縮小します。速度測定には768x384の道路画像を使い、3回の warm-up 後に10回推論しました。warm-up は初回だけの準備時間を測定から外すための事前実行です。
モデル読み込み、画像読み込み、前処理、可視化、保存は推論時間に含めません。出力の見た目は、道路、卓上、群衆の3画像で確認しました。
machine: MacBook Pro (Apple M1 Max, 64 GB, arm64)
OS: macOS 26.5.2
Python: 3.12.10
PyTorch: 2.13.0
ONNX Runtime: 1.27.0
input: FP32, batch 1, 768x384(速度測定)
warm-up: 3回
measurement: 10回
検証結果
左が入力、右が ZipDepth の出力です。画像ごとに色の範囲を調整しているため、画像をまたいだ色の直接比較はできません。
道路では手前の路面と車が明るく、遠方の建物や道路の消失点が暗くなりました。卓上では机、本、ノートPC、窓外の背景が段階的に分かれています。群衆も前景の人物ほど明るくなりました。ただし、遠方の小さな人物は1人ずつ分かれず、滑らかな領域になる部分があります。
これらは見た目の確認であり、正解深度と比べた精度評価ではありません。
推論速度
| backend / model | mean | median | min | max | std dev |
|---|---|---|---|---|---|
| PyTorch CPU / 通常版 | 77.78 ms | 77.49 ms | 75.75 ms | 80.89 ms | 1.65 ms |
| PyTorch MPS / 通常版 | 15.34 ms | 15.56 ms | 14.36 ms | 15.89 ms | 0.55 ms |
| PyTorch CPU / NPU互換版 | 101.49 ms | 100.47 ms | 97.44 ms | 109.55 ms | 3.26 ms |
| ONNX Runtime CPU / NPU互換版 | 47.08 ms | 47.17 ms | 46.54 ms | 47.46 ms | 0.33 ms |
中央値では、MPS は同じ通常版の PyTorch CPU より約4.98倍高速でした。ONNX Runtime CPU は、同じNPU互換版の PyTorch CPU より約2.13倍高速です。
MPS と ONNX Runtime の出力も、見た目ではほぼ同じでした。
数値出力の差
相対深度は値の倍率と基準点が違っても同じ奥行きを表せます。そこで scale と shift を最小二乗法で合わせてから誤差を測りました。
| comparison | aligned MAE | aligned RMSE |
|---|---|---|
| 通常版: PyTorch CPU vs MPS | 0.00000002 | 0.00000002 |
| NPU互換版: PyTorch vs ONNX Runtime CPU | 0.00000001 | 0.00000002 |
| PyTorch CPU: 通常版 vs NPU互換版 | 0.00044436 | 0.00086735 |
同じ checkpoint の backend 間差は、FP32の丸め誤差ほどでした。通常版とNPU互換版は完全には同じではありませんが、道路画像では見分けられませんでした。
ONNX変換で詰まった点
最初は onnxscript がなく、ONNX export に失敗しました。PyTorch 2.13.0 の exporter が必要とするため、依存関係へ追加して解消しました。
また opset 17 を指定すると、内部で生成された opset 18 からの変換に失敗しました。生成された opset 18 は ONNX checker を通り、ONNX Runtime でも実行できたため、実際の出力に合わせて18を採用しました。
結果の考察
専門的な数値は上に載せましたが、要点は3つです。
- MPSなら約65 FPS相当だった
モデル推論だけなら平均15.34 msでした。追加patchなしで動き、Apple Silicon のローカル画像処理へ組み込みやすい速度です。
- ONNX RuntimeもCPU実行を約2倍にできた
同じNPU互換版で比べると、PyTorch CPU の101.49 msに対し47.08 msでした。出力差もごく小さい値です。
- MPSとONNXの直接比較には注意が必要
両者は拡大方法の異なる checkpoint を使っています。そのため、約3倍という速度差を backend だけの差とは断定できません。
今回は生成画像3枚、速度測定は道路画像1枚、M1 Max 1台だけの検証です。メートル単位の距離精度、公式 benchmark、動画の安定性、Core ML、Apple Neural Engine、量子化、消費電力、メモリ使用量は確認していません。
検証後の感想
610万パラメータの小さなモデルで、車や人の輪郭を残しながら前後関係を出せたのは良い結果でした。とくに MPS の約15 msは、背景ぼかしや簡単な3D効果をローカルで試すには十分そうです。
一方、出力は相対深度なので、実距離が必要な用途にはそのまま使えません。遠くの小さな人物もまとまりやすいため、安全性が関わる認識へ単独で使うのは難しいです。それでも、物体検出や追跡と組み合わせれば、LLMエージェントの制御下でリアルタイムに障害物との前後関係を捉えたり、人物を追従したりするための補助情報として使えそうです。


