System Development 3D-реконструкции по фотографиям (Photogrammetry)
Фотограмметрия — реконструкция трёхмерной геометрии объекта по серии перекрывающихся фотографий с разных ракурсов. Результат: плотное 3D облако точек, mesh (полигональная сетка), текстурированная 3D модель. Applications: цифровые двойники объектов, архитектурная документация, судебная криминалистика, 3D-активы для игр и кино.
SfM + MVS пайплайн
Классический photogrammetry пайплайн состоит из двух этапов:
SfM (Structure from Motion): определение положения камер и разреженного облака точек по ключевым точкам (SIFT, SuperPoint):
import pycolmap
from pathlib import Path
def run_sfm_reconstruction(images_dir: str,
output_dir: str) -> dict:
"""Полный SfM пайплайн через COLMAP"""
image_path = Path(images_dir)
output_path = Path(output_dir)
output_path.mkdir(exist_ok=True)
database_path = output_path / 'database.db'
# Извлечение признаков
pycolmap.extract_features(database_path, image_path,
sift_options={'max_num_features': 8192})
# Сопоставление признаков
pycolmap.match_exhaustive(database_path)
# Инкрементальная реконструкция
maps = pycolmap.incremental_mapping(
database_path=database_path,
image_path=image_path,
output_path=output_path
)
reconstruction = maps[0] # largest map
return {
'num_cameras': len(reconstruction.cameras),
'num_images': len(reconstruction.images),
'num_3d_points': len(reconstruction.points3D)
}
MVS (Multi-View Stereo): плотное облако точек по позициям камер из SfM. OpenMVS или COLMAP dense:
import subprocess
def run_dense_reconstruction(sfm_output: str, output_dir: str):
"""Плотная реконструкция через OpenMVS"""
# Конвертация COLMAP → OpenMVS формат
subprocess.run([
'InterfaceCOLMAP',
'-i', sfm_output,
'-o', f'{output_dir}/scene.mvs'
], check=True)
# Плотная реконструкция
subprocess.run([
'DensifyPointCloud',
'-i', f'{output_dir}/scene.mvs',
'--resolution-level', '1',
'--number-views', '5'
], check=True)
# Построение mesh
subprocess.run([
'ReconstructMesh',
'-i', f'{output_dir}/scene_dense.mvs',
'--quality', '3'
], check=True)
# Текстурирование
subprocess.run([
'TextureMesh',
'-i', f'{output_dir}/scene_dense_mesh.mvs'
], check=True)
Open3D для обработки облаков точек
import open3d as o3d
import numpy as np
def process_point_cloud(pcd_path: str) -> dict:
pcd = o3d.io.read_point_cloud(pcd_path)
# Удаление выбросов
pcd_clean, _ = pcd.remove_statistical_outlier(nb_neighbors=20,
std_ratio=2.0)
# Нормализация
pcd_clean.estimate_normals(
o3d.geometry.KDTreeSearchParamHybrid(radius=0.05, max_nn=30)
)
# Poisson Surface Reconstruction
mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(
pcd_clean, depth=9
)
# Удаление низкоплотных вершин (края)
density_threshold = np.quantile(densities, 0.05)
mesh = mesh.select_by_index(np.where(densities > density_threshold)[0])
return {
'num_vertices': len(mesh.vertices),
'num_triangles': len(mesh.triangles),
'bounding_box': mesh.get_axis_aligned_bounding_box()
}
Требования к фотографиям
Качество реконструкции напрямую зависит от качества входных фото:
| Параметр | Рекомендация |
|---|---|
| Перекрытие кадров | 70–80% |
| Минимальное количество фото | 30–50 |
| Оптимальное количество | 100–300 |
| Угол между снимками | 15–30° |
| Освещение | Равномерное, без резких теней |
| Разрешение | 12 MP+ |
| Глубина резкости | Максимальная (f/8–f/16) |
Точность и время обработки
| Метод | Точность (мм) | Время (100 фото, CPU) |
|---|---|---|
| COLMAP + OpenMVS | 1–3 | 30–120 мин |
| Meshroom (AliceVision) | 1–5 | 45–90 мин |
| Reality Capture | 0.5–2 | 15–30 мин |
| Metashape (Agisoft) | 0.5–2 | 20–60 мин |
Applications и выходные форматы
Поддерживаемые форматы: PLY, OBJ+MTL, FBX, GLTF/GLB, USD. Integration с: Blender, Unity, Unreal Engine, Autodesk, trimble.
| Применение | Срок проекта |
|---|---|
| Пайплайн обработки фотосессий | 3–5 недель |
| Автоматическая фотостудия с роботом | 8–14 недель |
| Система для инспекции/документации | 6–10 недель |







