pull/1464/head
Piero Toffanin 2022-05-25 12:50:57 -04:00
rodzic beb4a7e3ff
commit ecb82b9dd5
7 zmienionych plików z 108 dodań i 5 usunięć

Wyświetl plik

@ -142,6 +142,7 @@ set(custom_libs OpenSfM
OpenMVS
FPCFilter
PyPopsift
Obj2Tiles
)
# Build entwine only on Linux

Wyświetl plik

@ -1 +1 @@
2.8.4
2.8.5

Wyświetl plik

@ -156,6 +156,12 @@ def config(argv=None, parser=None):
'Can be one of: %(choices)s. Default: '
'%(default)s'))
parser.add_argument('--3d-tiles',
action=StoreTrue,
nargs=0,
default=False,
help='Generate OGC 3D Tiles outputs. Default: %(default)s')
parser.add_argument('--matcher-neighbors',
metavar='<positive integer>',
action=StoreValue,
@ -773,9 +779,6 @@ def config(argv=None, parser=None):
if args.fast_orthophoto:
log.ODM_INFO('Fast orthophoto is turned on, automatically setting --skip-3dmodel')
args.skip_3dmodel = True
# if not 'sfm_algorithm_is_set' in args:
# log.ODM_INFO('Fast orthophoto is turned on, automatically setting --sfm-algorithm to triangulation')
# args.sfm_algorithm = 'triangulation'
if args.pc_rectify and not args.pc_classify:
log.ODM_INFO("Ground rectify is turned on, automatically turning on point cloud classification")

93
opendm/ogctiles.py 100644
Wyświetl plik

@ -0,0 +1,93 @@
import os
import sys
import shutil
import json
import math
from opendm.utils import double_quote
from opendm import io
from opendm import log
from opendm import system
from opendm import concurrency
import fiona
from shapely.geometry import shape
def build_textured_model(input_obj, output_path, reference_lla = None, model_bounds_file=None, rerun=False):
if not os.path.isfile(input_obj):
log.ODM_WARNING("No input OBJ file to process")
return
if rerun and io.dir_exists(output_path):
log.ODM_WARNING("Removing previous 3D tiles directory: %s" % output_path)
shutil.rmtree(output_path)
log.ODM_INFO("Generating OGC 3D Tiles textured model")
lat = lon = alt = 0
# Read reference_lla.json (if provided)
if reference_lla is not None and os.path.isfile(reference_lla):
try:
with open(reference_lla) as f:
reference_lla = json.loads(f.read())
lat = reference_lla['latitude']
lon = reference_lla['longitude']
alt = reference_lla['altitude']
except Exception as e:
log.ODM_WARNING("Cannot read %s: %s" % (reference_lla, str(e)))
# Read model bounds (if provided)
divisions = 1 # default
DIV_THRESHOLD = 10000 # m^2 (this is somewhat arbitrary)
if model_bounds_file is not None and os.path.isfile(model_bounds_file):
try:
with fiona.open(model_bounds_file, 'r') as f:
if len(f) == 1:
poly = shape(f[1]['geometry'])
area = poly.area
log.ODM_INFO("Approximate area: %s m^2" % round(area, 2))
if area < DIV_THRESHOLD:
divisions = 0
else:
divisions = math.ceil(math.log((area / DIV_THRESHOLD), 4))
else:
log.ODM_WARNING("Invalid boundary file: %s" % model_bounds_file)
except Exception as e:
log.ODM_WARNING("Cannot read %s: %s" % (model_bounds_file, str(e)))
try:
kwargs = {
'input': input_obj,
'output': output_path,
'divisions': divisions,
'lat': lat,
'lon': lon,
'alt': alt,
}
system.run('Obj2Tiles --input "{input}" --output "{output}" --divisions {divisions} '.format(**kwargs))
except Exception as e:
log.ODM_WARNING("Cannot build 3D tiles textured model: %s" % str(e))
def build_3dtiles(args, tree, reconstruction, rerun=False):
tiles_output_path = tree.ogc_tiles
model_output_path = os.path.join(tiles_output_path, "textured_model")
if rerun and os.path.exists(tiles_output_path):
shutil.rmtree(tiles_output_path)
if not os.path.isdir(tiles_output_path):
os.mkdir(tiles_output_path)
if not os.path.isdir(model_output_path) or rerun:
reference_lla = os.path.join(tree.opensfm, "reference_lla.json")
model_bounds_file = os.path.join(tree.odm_georeferencing, 'odm_georeferenced_model.bounds.gpkg')
input_obj = os.path.join(tree.odm_texturing, tree.odm_textured_model_obj)
if not os.path.isfile(input_obj):
input_obj = os.path.join(tree.odm_25dtexturing, tree.odm_textured_model_obj)
build_textured_model(input_obj, model_output_path, reference_lla, model_bounds_file, rerun)
else:
log.ODM_WARNING("OGC 3D Tiles model %s already generated" % model_output_path)

Wyświetl plik

@ -289,6 +289,7 @@ class ODM_Tree(object):
# Tiles
self.entwine_pointcloud = self.path("entwine_pointcloud")
self.ogc_tiles = self.path("3d_tiles")
def path(self, *args):
return os.path.join(self.root_path, *args)

Wyświetl plik

@ -64,6 +64,7 @@ def get_processing_results_paths():
"dsm_tiles",
"dtm_tiles",
"orthophoto_tiles",
"3d_tiles",
"images.json",
"cameras.json",
"log.json",

Wyświetl plik

@ -5,6 +5,7 @@ from opendm import io
from opendm import log
from opendm import types
from opendm.utils import copy_paths, get_processing_results_paths
from opendm.ogctiles import build_3dtiles
class ODMPostProcess(types.ODM_Stage):
def process(self, args, outputs):
@ -43,7 +44,10 @@ class ODMPostProcess(types.ODM_Stage):
break
else:
log.ODM_WARNING("Cannot open %s for writing, skipping GCP embedding" % product)
if getattr(args, '3d_tiles'):
build_3dtiles(args, tree, reconstruction, self.rerun())
if args.copy_to:
try:
copy_paths([os.path.join(args.project_path, p) for p in get_processing_results_paths()], args.copy_to, self.rerun())