kopia lustrzana https://github.com/OpenDroneMap/ODM
feat: add --compact-overviews config param for slim orthophoto overviews
rodzic
29800652c6
commit
7f3a40c45f
|
|
@ -5,7 +5,7 @@ from opendm.concurrency import get_max_memory
|
||||||
from opendm import io
|
from opendm import io
|
||||||
from opendm import log
|
from opendm import log
|
||||||
|
|
||||||
def convert_to_cogeo(src_path, blocksize=256, max_workers=1, compression="DEFLATE"):
|
def convert_to_cogeo(src_path, blocksize=256, max_workers=1, compression="DEFLATE", compact_overviews=False):
|
||||||
"""
|
"""
|
||||||
Guarantee that the .tif passed as an argument is a Cloud Optimized GeoTIFF (cogeo)
|
Guarantee that the .tif passed as an argument is a Cloud Optimized GeoTIFF (cogeo)
|
||||||
The file is destructively converted into a cogeo.
|
The file is destructively converted into a cogeo.
|
||||||
|
|
@ -15,39 +15,49 @@ def convert_to_cogeo(src_path, blocksize=256, max_workers=1, compression="DEFLAT
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not os.path.isfile(src_path):
|
if not os.path.isfile(src_path):
|
||||||
logger.warning("Cannot convert to cogeo: %s (file does not exist)" % src_path)
|
log.ODM_WARNING("Cannot convert to cogeo: %s (file does not exist)" % src_path)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
log.ODM_INFO("Optimizing %s as Cloud Optimized GeoTIFF" % src_path)
|
log.ODM_INFO("Optimizing %s as Cloud Optimized GeoTIFF" % src_path)
|
||||||
|
|
||||||
|
|
||||||
tmpfile = io.related_file_path(src_path, postfix='_cogeo')
|
tmpfile = io.related_file_path(src_path, postfix='_cogeo')
|
||||||
swapfile = io.related_file_path(src_path, postfix='_cogeo_swap')
|
swapfile = io.related_file_path(src_path, postfix='_cogeo_swap')
|
||||||
|
|
||||||
kwargs = {
|
# Configuration params
|
||||||
'threads': max_workers if max_workers else 'ALL_CPUS',
|
threads = max_workers if max_workers else 'ALL_CPUS'
|
||||||
'blocksize': blocksize,
|
predictor = '2' if compression in ['LZW', 'DEFLATE'] else '1'
|
||||||
'max_memory': get_max_memory(),
|
max_memory = get_max_memory()
|
||||||
'src_path': src_path,
|
|
||||||
'tmpfile': tmpfile,
|
# Build gdal_translate command
|
||||||
'compress': compression,
|
cmd = [
|
||||||
'predictor': '2' if compression in ['LZW', 'DEFLATE'] else '1',
|
'gdal_translate',
|
||||||
}
|
'-of', 'COG',
|
||||||
|
'-co', f'NUM_THREADS={threads}',
|
||||||
|
'-co', f'BLOCKSIZE={blocksize}',
|
||||||
|
'-co', f'COMPRESS={compression}',
|
||||||
|
'-co', f'PREDICTOR={predictor}',
|
||||||
|
'-co', 'BIGTIFF=IF_SAFER',
|
||||||
|
'-co', 'RESAMPLING=NEAREST',
|
||||||
|
]
|
||||||
|
|
||||||
|
if compact_overviews:
|
||||||
|
cmd.extend([
|
||||||
|
'-co', 'PHOTOMETRIC_OVERVIEW=YCBCR',
|
||||||
|
'-co', 'INTERLEAVE_OVERVIEW=PIXEL',
|
||||||
|
])
|
||||||
|
|
||||||
|
cmd.extend([
|
||||||
|
'--config', 'GDAL_CACHEMAX', f'{max_memory}%',
|
||||||
|
'--config', 'GDAL_NUM_THREADS', str(threads),
|
||||||
|
src_path,
|
||||||
|
tmpfile,
|
||||||
|
])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
system.run("gdal_translate "
|
system.run(' '.join(cmd))
|
||||||
"-of COG "
|
|
||||||
"-co NUM_THREADS={threads} "
|
|
||||||
"-co BLOCKSIZE={blocksize} "
|
|
||||||
"-co COMPRESS={compress} "
|
|
||||||
"-co PREDICTOR={predictor} "
|
|
||||||
"-co BIGTIFF=IF_SAFER "
|
|
||||||
"-co RESAMPLING=NEAREST "
|
|
||||||
"--config GDAL_CACHEMAX {max_memory}% "
|
|
||||||
"--config GDAL_NUM_THREADS {threads} "
|
|
||||||
"\"{src_path}\" \"{tmpfile}\" ".format(**kwargs))
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.ODM_WARNING("Cannot create Cloud Optimized GeoTIFF: %s" % str(e))
|
log.ODM_WARNING("Cannot create Cloud Optimized GeoTIFF: %s" % str(e))
|
||||||
|
return False
|
||||||
|
|
||||||
if os.path.isfile(tmpfile):
|
if os.path.isfile(tmpfile):
|
||||||
shutil.move(src_path, swapfile) # Move to swap location
|
shutil.move(src_path, swapfile) # Move to swap location
|
||||||
|
|
@ -57,6 +67,7 @@ def convert_to_cogeo(src_path, blocksize=256, max_workers=1, compression="DEFLAT
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
log.ODM_WARNING("Cannot move %s to %s: %s" % (tmpfile, src_path, str(e)))
|
log.ODM_WARNING("Cannot move %s to %s: %s" % (tmpfile, src_path, str(e)))
|
||||||
shutil.move(swapfile, src_path) # Attempt to restore
|
shutil.move(swapfile, src_path) # Attempt to restore
|
||||||
|
return False
|
||||||
|
|
||||||
if os.path.isfile(swapfile):
|
if os.path.isfile(swapfile):
|
||||||
os.remove(swapfile)
|
os.remove(swapfile)
|
||||||
|
|
|
||||||
|
|
@ -740,6 +740,12 @@ def config(argv=None, parser=None):
|
||||||
default=False,
|
default=False,
|
||||||
help='Build orthophoto overviews for faster display in programs such as QGIS. Default: %(default)s')
|
help='Build orthophoto overviews for faster display in programs such as QGIS. Default: %(default)s')
|
||||||
|
|
||||||
|
parser.add_argument('--compact-overviews',
|
||||||
|
action=StoreTrue,
|
||||||
|
nargs=0,
|
||||||
|
default=False,
|
||||||
|
help='Use addtional compression for orthophoto overviews, to improve viewing performance. Default: %(default)s')
|
||||||
|
|
||||||
parser.add_argument('--cog',
|
parser.add_argument('--cog',
|
||||||
action=StoreTrue,
|
action=StoreTrue,
|
||||||
nargs=0,
|
nargs=0,
|
||||||
|
|
|
||||||
|
|
@ -29,15 +29,31 @@ def get_orthophoto_vars(args):
|
||||||
'NUM_THREADS': args.max_concurrency
|
'NUM_THREADS': args.max_concurrency
|
||||||
}
|
}
|
||||||
|
|
||||||
def build_overviews(orthophoto_file):
|
def build_overviews(orthophoto_file, compact_overviews=False):
|
||||||
|
"""
|
||||||
|
Build overviews for an orthophoto file using gdaladdo
|
||||||
|
:param orthophoto_file: path to orthophoto
|
||||||
|
:param compact_overviews: whether to use compact overview settings
|
||||||
|
"""
|
||||||
log.ODM_INFO("Building Overviews")
|
log.ODM_INFO("Building Overviews")
|
||||||
kwargs = {'orthophoto': orthophoto_file}
|
|
||||||
|
|
||||||
# Run gdaladdo
|
# Build gdaladdo command
|
||||||
system.run('gdaladdo -r average '
|
cmd = [
|
||||||
'--config BIGTIFF_OVERVIEW IF_SAFER '
|
'gdaladdo',
|
||||||
'--config COMPRESS_OVERVIEW JPEG '
|
'-r', 'average',
|
||||||
'{orthophoto} 2 4 8 16'.format(**kwargs))
|
'--config', 'BIGTIFF_OVERVIEW', 'IF_SAFER',
|
||||||
|
'--config', 'COMPRESS_OVERVIEW', 'JPG',
|
||||||
|
]
|
||||||
|
|
||||||
|
if compact_overviews:
|
||||||
|
cmd.extend([
|
||||||
|
'--config', 'PHOTOMETRIC_OVERVIEW', 'YCBCR',
|
||||||
|
'--config', 'INTERLEAVE_OVERVIEW', 'PIXEL',
|
||||||
|
])
|
||||||
|
|
||||||
|
cmd.extend([orthophoto_file, '2', '4', '8', '16'])
|
||||||
|
|
||||||
|
system.run(' '.join(cmd))
|
||||||
|
|
||||||
def generate_png(orthophoto_file, output_file=None, outsize=None):
|
def generate_png(orthophoto_file, output_file=None, outsize=None):
|
||||||
if output_file is None:
|
if output_file is None:
|
||||||
|
|
@ -172,7 +188,7 @@ def post_orthophoto_steps(args, bounds_file_path, orthophoto_file, orthophoto_ti
|
||||||
Cropper.crop(bounds_file_path, orthophoto_file, get_orthophoto_vars(args), keep_original=not args.optimize_disk_space, warp_options=['-dstalpha'])
|
Cropper.crop(bounds_file_path, orthophoto_file, get_orthophoto_vars(args), keep_original=not args.optimize_disk_space, warp_options=['-dstalpha'])
|
||||||
|
|
||||||
if args.build_overviews and not args.cog:
|
if args.build_overviews and not args.cog:
|
||||||
build_overviews(orthophoto_file)
|
build_overviews(orthophoto_file, compact_overviews=args.compact_overviews)
|
||||||
|
|
||||||
if args.orthophoto_png:
|
if args.orthophoto_png:
|
||||||
generate_png(orthophoto_file)
|
generate_png(orthophoto_file)
|
||||||
|
|
@ -186,7 +202,7 @@ def post_orthophoto_steps(args, bounds_file_path, orthophoto_file, orthophoto_ti
|
||||||
generate_orthophoto_tiles(orthophoto_file, orthophoto_tiles_dir, args.max_concurrency, resolution)
|
generate_orthophoto_tiles(orthophoto_file, orthophoto_tiles_dir, args.max_concurrency, resolution)
|
||||||
|
|
||||||
if args.cog:
|
if args.cog:
|
||||||
convert_to_cogeo(orthophoto_file, max_workers=args.max_concurrency, compression=args.orthophoto_compression)
|
convert_to_cogeo(orthophoto_file, max_workers=args.max_concurrency, compression=args.orthophoto_compression, compact_overviews=args.compact_overviews)
|
||||||
|
|
||||||
generate_extent_polygon(orthophoto_file)
|
generate_extent_polygon(orthophoto_file)
|
||||||
generate_tfw(orthophoto_file)
|
generate_tfw(orthophoto_file)
|
||||||
|
|
|
||||||
Ładowanie…
Reference in New Issue