AI-забезпечена 3D-реконструкція з фотографій (NeRF) у мобільних додатках
NeRF (Neural Radiance Field) на мобільному пристрої — це не «натисни кнопку, отримай 3D модель». Це багатоетапний процес із серйозними обчислювальними вимогами, який у 2024–2025 роках, нарешті, став реальним для виробничих додатків завдяки 3D Gaussian Splatting та новим моделям типу InstantNGP та Nerfacto.
NeRF проти Gaussian Splatting проти Photogrammetry
Три технології вирішують одну задачу: 3D-об'єкти з фотографій. Різниці принципові:
| Метод | Швидкість навчання | Час рендерингу | Якість | Редагованість |
|---|---|---|---|---|
| Класичний NeRF | Години–дні | Повільний | Висока | Погана |
| InstantNGP/Nerfacto | 5–30 хв | Швидкий | Хороша | Середня |
| 3D Gaussian Splatting | 10–40 хв | Реальний час | Відмінна | Хороша |
| Photogrammetry (Metashape, COLMAP) | 30 хв–кілька годин | Миттєвий (mesh) | Залежна від фото | Відмінна |
Для мобільних додатків у 2025 році: 3D Gaussian Splatting пропонує найбільш збалансований баланс швидкості та якості. Для швидких AR попередніх переглядів рекомендується photogrammetry з останньою версією COLMAP.
Архітектура: зйомка на пристрої, обробка в хмарі
On-device реконструкція практична лише в обмежених сценаріях (Apple Object Capture API—лише Mac з Apple Silicon). Практична архітектура для мобільних:
Мобільний пристрій:
- Направлений процес зйомки (20–60 фото на орбітальній траєкторії)
- Метаданні ARKit (camera poses)—спрощує COLMAP SfM
- Завантаження в хмару
Backend (GPU інстанс):
- COLMAP SfM (якщо немає ARKit poses) або оцінка pose з метаданих
- 3D Gaussian Splatting навчання (nerfstudio + gsplat)
- Експорт у .splat / .ply / .glb
- CDN → мобільний пристрій
Мобільний пристрій:
- Завантаження та рендеринг результату
- AR перегляд через RealityKit (iOS) / SceneView (Android)
Направлена зйомка на iOS з ARKit
Ключова вимога UX: користувач повинен орбітально обійти об'єкт правильно, інакше реконструкція матиме артефакти.
class GuidedCaptureSession: NSObject {
private var arSession: ARSession
private var capturedFrames: [(UIImage, simd_float4x4)] = [] // image + camera transform
private let targetFrameCount = 40
private let minAngleBetweenFrames: Float = 8.0 // градуси
func shouldCaptureFrame(currentTransform: simd_float4x4) -> Bool {
guard let lastTransform = capturedFrames.last?.1 else { return true }
// Кутова відстань від останнього захопленого кадру
let angularDistance = computeAngularDistance(currentTransform, lastTransform)
return angularDistance >= minAngleBetweenFrames
}
var captureProgress: Float {
// Оцініть покриття орбіти навколо об'єкту
let coveredAngles = estimateOrbitCoverage(capturedFrames.map { $0.1 })
return min(coveredAngles / 360.0, 1.0)
}
}
AR оверлей відображає «орбіту» навколо об'єкту: зелені дуги показують захоплені кути, сірі області показують те, що ще потрібно захопити. Це зменшує невдачі реконструкції через неповне покриття.
Вимоги до якості зображення
Перед завантаженням у хмару—базова валідація:
func validateCaptureSet(_ frames: [(UIImage, simd_float4x4)]) -> ValidationResult {
// Мінімальна кількість кадрів
guard frames.count >= 20 else {
return .insufficientFrames(current: frames.count, required: 20)
}
// Кутове покриття (мінімум 270° з 360°)
let orbitCoverage = estimateOrbitCoverage(frames.map { $0.1 })
guard orbitCoverage >= 0.75 else {
return .insufficientCoverage(coverage: orbitCoverage)
}
// Середня чіткість кадрів
let avgSharpness = frames.map { sharpnessScore($0.0) }.reduce(0, +) / Float(frames.count)
guard avgSharpness >= 60.0 else {
return .blurryImages
}
return .valid
}
Backend: 3D Gaussian Splatting навчання
# nerfstudio + gsplat pipeline
from nerfstudio.cameras.cameras import CameraType
from nerfstudio.pipelines.base_pipeline import Pipeline
def run_gaussian_splatting(
images_dir: Path,
camera_poses: list[np.ndarray] | None = None,
output_dir: Path = Path("output")
) -> Path:
"""
Якщо передаються camera_poses (з ARKit)—пропустити COLMAP SfM.
Це скорочує час обробки з 15-20 хв до 3-5 хв.
"""
config = SplatfactoModelConfig(
num_downscales=2, # зменшити для швидкості
use_scale_regularization=True,
max_gauss_ratio=10.0,
)
trainer = Trainer(config, output_dir=output_dir)
trainer.train() # ~10-40 хв на GPU (A100: 10 хв, T4: 25 хв)
# Експорт у веб-дружні формати
export_gaussian_splat(output_dir / "splat.ply")
export_glb(output_dir / "model.glb") # для AR Quick Look / SceneViewer
return output_dir
Відображення результатів у AR
// iOS: RealityKit Quick Look для .usdz / .glb
import RealityKit
import ARKit
class ModelViewerViewController: UIViewController {
func presentARModel(modelURL: URL) {
let arView = ARView(frame: view.bounds, cameraMode: .ar)
let anchor = AnchorEntity(plane: .horizontal)
ModelEntity.loadModelAsync(contentsOf: modelURL)
.sink(
receiveCompletion: { _ in },
receiveValue: { [weak self] entity in
entity.generateCollisionShapes(recursive: true)
anchor.addChild(entity)
arView.scene.anchors.append(anchor)
// Pinch до масштабування, pan для переміщення
arView.installGestures([.scale, .translation, .rotation], for: entity)
}
)
.store(in: &cancellables)
}
}
Кошторис за часом
MVP з направленою зйомкою, завантаженням у хмару, навчанням Nerfacto/Gaussian Splatting та базовим AR переглядом займає 3–4 тижні. Повна система з використанням ARKit camera poses (без COLMAP), відстеженням прогресу обробки, експортом у кілька форматів (.glb, .usdz, .obj), спільним використанням 3D-моделей та підтримкою iOS + Android вимагає 2–3 місяців.







