kopia lustrzana https://github.com/OpenDroneMap/ODM
159 wiersze
5.2 KiB
Python
159 wiersze
5.2 KiB
Python
import os, shutil
|
|
import numpy as np
|
|
import json
|
|
import rasterio
|
|
from osgeo import gdal
|
|
from datetime import datetime
|
|
|
|
from opendm import log
|
|
from opendm.photo import find_largest_photo_dims, find_mean_utc_time
|
|
from osgeo import gdal
|
|
from opendm.arghelpers import double_quote
|
|
|
|
class NumpyEncoder(json.JSONEncoder):
|
|
def default(self, obj):
|
|
if isinstance(obj, np.ndarray):
|
|
return obj.tolist()
|
|
return json.JSONEncoder.default(self, obj)
|
|
|
|
|
|
def get_depthmap_resolution(args, photos):
|
|
max_dims = find_largest_photo_dims(photos)
|
|
min_dim = 320 # Never go lower than this
|
|
|
|
if max_dims is not None:
|
|
w, h = max_dims
|
|
max_dim = max(w, h)
|
|
|
|
megapixels = (w * h) / 1e6
|
|
multiplier = 1
|
|
|
|
if megapixels < 6:
|
|
multiplier = 2
|
|
elif megapixels > 42:
|
|
multiplier = 0.5
|
|
|
|
pc_quality_scale = {
|
|
'ultra': 0.5,
|
|
'high': 0.25,
|
|
'medium': 0.125,
|
|
'low': 0.0675,
|
|
'lowest': 0.03375
|
|
}
|
|
|
|
return max(min_dim, int(max_dim * pc_quality_scale[args.pc_quality] * multiplier))
|
|
else:
|
|
log.ODM_WARNING("Cannot compute max image dimensions, going with default depthmap_resolution of 640")
|
|
return 640 # Sensible default
|
|
|
|
def get_raster_stats(geotiff):
|
|
stats = []
|
|
gtif = gdal.Open(geotiff)
|
|
for b in range(gtif.RasterCount):
|
|
srcband = gtif.GetRasterBand(b + 1)
|
|
s = srcband.GetStatistics(True, True)
|
|
|
|
stats.append({
|
|
'min': s[0],
|
|
'max': s[1],
|
|
'mean': s[2],
|
|
'stddev': s[3]
|
|
})
|
|
|
|
return stats
|
|
|
|
def get_processing_results_paths():
|
|
return [
|
|
"odm_georeferencing",
|
|
"odm_orthophoto",
|
|
"odm_dem",
|
|
"odm_report",
|
|
"odm_texturing",
|
|
"entwine_pointcloud",
|
|
"dsm_tiles",
|
|
"dtm_tiles",
|
|
"orthophoto_tiles",
|
|
"3d_tiles",
|
|
"images.json",
|
|
"cameras.json",
|
|
"log.json",
|
|
]
|
|
|
|
def copy_paths(paths, destination, rerun):
|
|
if not os.path.isdir(destination):
|
|
os.makedirs(destination)
|
|
|
|
for p in paths:
|
|
basename = os.path.basename(p)
|
|
dst_path = os.path.join(destination, basename)
|
|
|
|
if rerun:
|
|
try:
|
|
if os.path.isfile(dst_path) or os.path.islink(dst_path):
|
|
os.remove(dst_path)
|
|
elif os.path.isdir(dst_path):
|
|
shutil.rmtree(dst_path)
|
|
except Exception as e:
|
|
log.ODM_WARNING("Cannot remove file %s: %s, skipping..." % (dst_path, str(e)))
|
|
|
|
if not os.path.exists(dst_path):
|
|
if os.path.isfile(p):
|
|
log.ODM_INFO("Copying %s --> %s" % (p, dst_path))
|
|
shutil.copy(p, dst_path)
|
|
elif os.path.isdir(p):
|
|
shutil.copytree(p, dst_path)
|
|
log.ODM_INFO("Copying %s --> %s" % (p, dst_path))
|
|
|
|
def rm_r(path):
|
|
try:
|
|
if os.path.isdir(path) and not os.path.islink(path):
|
|
shutil.rmtree(path)
|
|
elif os.path.exists(path):
|
|
os.remove(path)
|
|
except:
|
|
log.ODM_WARNING("Cannot remove %s" % path)
|
|
|
|
def np_to_json(arr):
|
|
return json.dumps(arr, cls=NumpyEncoder)
|
|
|
|
def np_from_json(json_dump):
|
|
return np.asarray(json.loads(json_dump))
|
|
|
|
def add_raster_meta_tags(raster, reconstruction, tree, embed_gcp_meta=True):
|
|
try:
|
|
if os.path.isfile(raster):
|
|
mean_capture_time = find_mean_utc_time(reconstruction.photos)
|
|
mean_capture_dt = None
|
|
if mean_capture_time is not None:
|
|
mean_capture_dt = datetime.fromtimestamp(mean_capture_time).strftime('%Y:%m:%d %H:%M:%S') + '+00:00'
|
|
|
|
log.ODM_INFO("Adding TIFFTAGs to {}".format(raster))
|
|
with rasterio.open(raster, 'r+') as rst:
|
|
if mean_capture_dt is not None:
|
|
rst.update_tags(TIFFTAG_DATETIME=mean_capture_dt)
|
|
rst.update_tags(TIFFTAG_SOFTWARE='ODM {}'.format(log.odm_version()))
|
|
|
|
if embed_gcp_meta:
|
|
# Embed GCP info in 2D results via
|
|
# XML metadata fields
|
|
gcp_gml_export_file = tree.path("odm_georeferencing", "ground_control_points.gml")
|
|
|
|
if reconstruction.has_gcp() and os.path.isfile(gcp_gml_export_file):
|
|
gcp_xml = ""
|
|
|
|
with open(gcp_gml_export_file) as f:
|
|
gcp_xml = f.read()
|
|
|
|
ds = gdal.Open(raster)
|
|
if ds is not None:
|
|
if ds.GetMetadata('xml:GROUND_CONTROL_POINTS') is None or self.rerun():
|
|
ds.SetMetadata(gcp_xml, 'xml:GROUND_CONTROL_POINTS')
|
|
ds = None
|
|
log.ODM_INFO("Wrote xml:GROUND_CONTROL_POINTS metadata to %s" % raster)
|
|
else:
|
|
log.ODM_WARNING("Already embedded ground control point information")
|
|
else:
|
|
log.ODM_WARNING("Cannot open %s for writing, skipping GCP embedding" % raster)
|
|
except Exception as e:
|
|
log.ODM_WARNING("Cannot write raster meta tags to %s: %s" % (raster, str(e)))
|