OpenDroneMap-ODM/scripts/odm_georeferencing.py

153 wiersze
6.9 KiB
Python
Czysty Zwykły widok Historia

2015-12-01 16:25:14 +00:00
import ecto
2016-02-25 19:51:03 +00:00
import csv
2015-12-01 16:25:14 +00:00
from opendm import io
from opendm import log
2015-12-10 17:17:39 +00:00
from opendm import types
2015-12-01 16:25:14 +00:00
from opendm import system
from opendm import context
2016-02-25 20:02:48 +00:00
2015-12-01 16:25:14 +00:00
class ODMGeoreferencingCell(ecto.Cell):
def declare_params(self, params):
params.declare("gcp_file", 'path to the file containing the ground control '
'points used for georeferencing.The file needs to '
'be on the following line format: \neasting '
'northing height pixelrow pixelcol imagename', 'gcp_list.txt')
params.declare("use_gcp", 'set to true for enabling GCPs from the file above', False)
params.declare("img_size", 'image size used in calibration', 2400)
2015-12-01 16:25:14 +00:00
def declare_io(self, params, inputs, outputs):
inputs.declare("tree", "Struct with paths", [])
2015-12-01 16:25:14 +00:00
inputs.declare("args", "The application arguments.", {})
inputs.declare("photos", "list of ODMPhoto's", [])
inputs.declare("reconstruction", "list of ODMReconstructions", [])
outputs.declare("reconstruction", "list of ODMReconstructions", [])
2015-12-01 16:25:14 +00:00
def process(self, inputs, outputs):
2016-02-29 14:45:00 +00:00
# Benchmarking
start_time = system.now_raw()
2015-12-01 16:25:14 +00:00
log.ODM_INFO('Running ODM Georeferencing Cell')
2015-12-01 16:25:14 +00:00
# get inputs
args = self.inputs.args
tree = self.inputs.tree
2016-04-05 15:12:47 +00:00
gcpfile = io.join_paths(tree.root_path, self.params.gcp_file)
2015-12-01 16:25:14 +00:00
# define paths and create working directories
system.mkdir_p(tree.odm_georeferencing)
2015-12-01 16:25:14 +00:00
# in case a gcp file it's not provided, let's try to generate it using
# images metadata. Internally calls jhead.
if not self.params.use_gcp and \
not io.file_exists(tree.odm_georeferencing_coords):
2016-02-25 20:02:48 +00:00
log.ODM_WARNING('Warning: No coordinates file. '
'Generating coordinates file in: %s'
% tree.odm_georeferencing_coords)
2015-12-01 16:25:14 +00:00
try:
# odm_georeference definitions
kwargs = {
'bin': context.odm_modules_path,
'imgs': tree.dataset_resize,
'imgs_list': tree.opensfm_bundle_list,
'coords': tree.odm_georeferencing_coords,
'log': tree.odm_georeferencing_utm_log
}
# run UTM extraction binary
2016-02-25 20:02:48 +00:00
system.run('{bin}/odm_extract_utm -imagesPath {imgs}/ '
'-imageListFile {imgs_list} -outputCoordFile {coords} '
'-logFile {log}'.format(**kwargs))
2015-12-01 16:25:14 +00:00
except Exception, e:
2016-02-25 20:02:48 +00:00
log.ODM_ERROR('Could not generate GCP file from images metadata.'
'Consider rerunning with argument --odm_georeferencing-useGcp'
' and provide a proper GCP file')
log.ODM_ERROR(e)
2015-12-01 16:25:14 +00:00
return ecto.QUIT
# check if we rerun cell or not
rerun_cell = (args.rerun is not None and
args.rerun == 'odm_georeferencing') or \
(args.rerun_all) or \
(args.rerun_from is not None and
'odm_georeferencing' in args.rerun_from)
2016-02-25 19:51:03 +00:00
if not io.file_exists(tree.odm_georeferencing_model_obj_geo) or \
not io.file_exists(tree.odm_georeferencing_model_ply_geo) or rerun_cell:
2015-12-01 16:25:14 +00:00
# odm_georeference definitions
kwargs = {
'bin': context.odm_modules_path,
'bundle': tree.opensfm_bundle,
'imgs': tree.dataset_resize,
'imgs_list': tree.opensfm_bundle_list,
'model': tree.odm_textured_model_obj,
'log': tree.odm_georeferencing_log,
'coords': tree.odm_georeferencing_coords,
2016-02-25 19:51:03 +00:00
'pc_geo': tree.odm_georeferencing_model_ply_geo,
'geo_sys': tree.odm_georeferencing_model_txt_geo,
'model_geo': tree.odm_georeferencing_model_obj_geo,
'size': self.params.img_size,
2016-04-05 15:12:47 +00:00
'gcp': gcpfile,
2015-12-01 16:25:14 +00:00
}
if args.use_opensfm_pointcloud:
kwargs['pc'] = tree.opensfm_model
else:
kwargs['pc'] = tree.pmvs_model
2015-12-01 16:25:14 +00:00
if self.params.use_gcp and \
2016-04-05 15:12:47 +00:00
io.file_exists(gcpfile):
2016-04-05 15:12:47 +00:00
system.run('{bin}/odm_georef -bundleFile {bundle} -imagesPath {imgs} -imagesListPath {imgs_list} '
2016-02-25 19:51:03 +00:00
'-bundleResizedTo {size} -inputFile {model} -outputFile {model_geo} '
'-inputPointCloudFile {pc} -outputPointCloudFile {pc_geo} '
'-logFile {log} -georefFileOutputPath {geo_sys} -gcpFile {gcp} '
'-outputCoordFile {coords}'.format(**kwargs))
else:
2016-02-25 19:51:03 +00:00
system.run('{bin}/odm_georef -bundleFile {bundle} -inputCoordFile {coords} '
'-inputFile {model} -outputFile {model_geo} '
'-inputPointCloudFile {pc} -outputPointCloudFile {pc_geo} '
'-logFile {log} -georefFileOutputPath {geo_sys}'.format(**kwargs))
# update images metadata
geo_ref = types.ODM_GeoRef()
geo_ref.parse_coordinate_system(tree.odm_georeferencing_coords)
for idx, photo in enumerate(self.inputs.photos):
geo_ref.utm_to_latlon(tree.odm_georeferencing_latlon, photo, idx)
# convert ply model to LAS reference system
2016-02-25 20:02:48 +00:00
geo_ref.convert_to_las(tree.odm_georeferencing_model_ply_geo,
tree.odm_georeferencing_pdal)
2016-02-25 19:51:03 +00:00
# XYZ point cloud output
log.ODM_INFO("Creating geo-referenced CSV file (XYZ format, can be used with GRASS to create DEM)")
with open(tree.odm_georeferencing_xyz_file, "wb") as csvfile:
csvfile_writer = csv.writer(csvfile, delimiter=",")
reachedpoints = False
with open(tree.odm_georeferencing_model_ply_geo) as f:
for lineNumber, line in enumerate(f):
if reachedpoints:
tokens = line.split(" ")
csv_line = [float(tokens[0])+geo_ref.utm_east_offset,
float(tokens[1])+geo_ref.utm_north_offset,
tokens[2]]
csvfile_writer.writerow(csv_line)
if line.startswith("end_header"):
reachedpoints = True
csvfile.close()
2015-12-01 16:25:14 +00:00
else:
2016-02-25 19:51:03 +00:00
log.ODM_WARNING('Found a valid georeferenced model in: %s'
% tree.odm_georeferencing_model_ply_geo)
2015-12-10 17:17:39 +00:00
if args.time:
2016-02-29 14:45:00 +00:00
system.benchmark(start_time, tree.benchmarking, 'Georeferencing')
log.ODM_INFO('Running ODM Georeferencing Cell - Finished')
return ecto.OK if args.end_with != 'odm_georeferencing' else ecto.QUIT