Point cloud, textured model transform

pull/1565/head
Piero Toffanin 2022-12-07 13:43:40 -05:00
rodzic 7aec8925d7
commit 9a77a4e611
3 zmienionych plików z 77 dodań i 20 usunięć

Wyświetl plik

@ -1,15 +1,18 @@
import os import os
import shutil import shutil
import json
import codem import codem
import dataclasses import dataclasses
import pdal
import numpy as np
from opendm import log from opendm import log
def compute_alignment_matrix(input_laz, align_file, tmp_dir): def compute_alignment_matrix(input_laz, align_file, stats_dir):
if os.path.exists(tmp_dir): if os.path.exists(stats_dir):
shutil.rmtree(tmp_dir) shutil.rmtree(stats_dir)
os.mkdir(tmp_dir) os.mkdir(stats_dir)
conf = dataclasses.asdict(codem.CodemRunConfig(align_file, input_laz, MIN_RESOLUTION=0.2, OUTPUT_DIR=tmp_dir)) # TODO: how to compute this conf = dataclasses.asdict(codem.CodemRunConfig(align_file, input_laz, OUTPUT_DIR=stats_dir))
fnd_obj, aoi_obj = codem.preprocess(conf) fnd_obj, aoi_obj = codem.preprocess(conf)
fnd_obj.prep() fnd_obj.prep()
aoi_obj.prep() aoi_obj.prep()
@ -29,6 +32,30 @@ def compute_alignment_matrix(input_laz, align_file, tmp_dir):
None, None,
) )
return app_reg.get_registration_transformation() reg = app_reg.get_registration_transformation()
# if os.path.exists(tmp_dir): matrix = np.fromstring(reg['matrix'], dtype=float, sep=' ').reshape((4, 4))
# shutil.rmtree(tmp_dir) return matrix
def transform_point_cloud(input_laz, a_matrix, output_laz):
pipe = [
input_laz,
{
'type': 'filters.transformation',
'matrix': " ".join(list(map(str, a_matrix.flatten()))),
},
output_laz,
]
p = pdal.Pipeline(json.dumps(pipe))
p.execute()
def transform_obj(input_obj, a_matrix, output_obj):
with open(input_obj, 'r') as fin:
with open(output_obj, 'w') as fout:
lines = fin.readlines()
for line in lines:
if line.startswith("v "):
v = np.fromstring(line.strip()[2:] + " 1", sep=' ', dtype=float)
vt = v.dot(a_matrix)[:3]
fout.write("v " + " ".join(map(str, list(vt))) + '\n')
else:
fout.write(line)

Wyświetl plik

@ -85,3 +85,7 @@ def path_or_json_string_to_dict(string):
raise ValueError("{0} is not a valid JSON file.".format(string)) raise ValueError("{0} is not a valid JSON file.".format(string))
else: else:
raise ValueError("{0} is not a valid JSON file or string.".format(string)) raise ValueError("{0} is not a valid JSON file or string.".format(string))
def touch(file):
with open(file, 'w') as fout:
fout.write("Done!\n")

Wyświetl plik

@ -18,7 +18,7 @@ from opendm import point_cloud
from opendm.multispectral import get_primary_band_name from opendm.multispectral import get_primary_band_name
from opendm.osfm import OSFMContext from opendm.osfm import OSFMContext
from opendm.boundary import as_polygon, export_to_bounds_files from opendm.boundary import as_polygon, export_to_bounds_files
from opendm.align import compute_alignment_matrix from opendm.align import compute_alignment_matrix, transform_point_cloud, transform_obj
class ODMGeoreferencingStage(types.ODM_Stage): class ODMGeoreferencingStage(types.ODM_Stage):
def process(self, args, outputs): def process(self, args, outputs):
@ -170,18 +170,44 @@ class ODMGeoreferencingStage(types.ODM_Stage):
if tree.odm_align_file is not None: if tree.odm_align_file is not None:
tmp_dir = tree.path("odm_georeferencing", "codem") alignment_file = os.path.join(tree.odm_georeferencing, 'alignment_done.txt')
a_matrix = compute_alignment_matrix(tree.odm_georeferencing_model_laz, tree.odm_align_file, tmp_dir)
if a_matrix is not None: if not io.file_exists(alignment_file) or self.rerun():
print(a_matrix) stats_dir = tree.path("opensfm", "stats", "codem")
exit(1) a_matrix = compute_alignment_matrix(tree.odm_georeferencing_model_laz, tree.odm_align_file, stats_dir)
if a_matrix is not None:
log.ODM_INFO("Alignment matrix: %s" % a_matrix)
# Align point cloud
unaligned_model = io.related_file_path(tree.odm_georeferencing_model_laz, postfix="_unaligned")
if not os.path.isfile(unaligned_model):
os.rename(tree.odm_georeferencing_model_laz, unaligned_model)
try:
transform_point_cloud(unaligned_model, a_matrix, tree.odm_georeferencing_model_laz)
log.ODM_INFO("Transformed %s" % tree.odm_georeferencing_model_laz)
except Exception as e:
log.ODM_WARNING("Cannot transform point cloud: %s" % str(e))
os.rename(unaligned_model, tree.odm_georeferencing_model_laz)
# Align textured models
for texturing in [tree.odm_texturing, tree.odm_25dtexturing]:
obj = os.path.join(texturing, "odm_textured_model_geo.obj")
if os.path.isfile(obj):
unaligned_obj = io.related_file_path(obj, postfix="_unaligned")
if not os.path.isfile(unaligned_obj):
os.rename(obj, unaligned_obj)
try:
transform_obj(unaligned_obj, a_matrix, obj)
log.ODM_INFO("Transformed %s" % obj)
except Exception as e:
log.ODM_WARNING("Cannot transform textured model: %s" % str(e))
os.rename(unaligned_obj, obj)
else:
log.ODM_WARNING("Alignment to %s will be skipped." % tree.odm_align_file)
io.touch(alignment_file)
else: else:
log.ODM_WARNING("Alignment to %s will be skipped." % tree.odm_align_file) log.ODM_WARNING("Already computed alignment")
# Align
# - Compute alignment
# - Transform point cloud
# - Transform textured model(s)
#
point_cloud.post_point_cloud_steps(args, tree, self.rerun()) point_cloud.post_point_cloud_steps(args, tree, self.rerun())
else: else: