kopia lustrzana https://github.com/OpenDroneMap/ODM
Add --3d-tiles
rodzic
beb4a7e3ff
commit
ecb82b9dd5
|
@ -142,6 +142,7 @@ set(custom_libs OpenSfM
|
|||
OpenMVS
|
||||
FPCFilter
|
||||
PyPopsift
|
||||
Obj2Tiles
|
||||
)
|
||||
|
||||
# Build entwine only on Linux
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
2.8.4
|
||||
2.8.5
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
||||
|
|
|
@ -64,6 +64,7 @@ def get_processing_results_paths():
|
|||
"dsm_tiles",
|
||||
"dtm_tiles",
|
||||
"orthophoto_tiles",
|
||||
"3d_tiles",
|
||||
"images.json",
|
||||
"cameras.json",
|
||||
"log.json",
|
||||
|
|
|
@ -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())
|
||||
|
|
Ładowanie…
Reference in New Issue