Add quickpreview module, fix cutline polygons edge-case

pull/1350/head
Piero Toffanin 2021-09-21 21:44:52 +00:00
rodzic 1ed9087e4f
commit 0589483b9b
3 zmienionych plików z 159 dodań i 1 usunięć

Wyświetl plik

@ -0,0 +1,29 @@
# Merge Preview
Quickly projects drone images on a map by using georeferencing, camera angles and a global DTM. The images are then merged using ODM's split-merge algorithms.
Quality is obviously not good, works only for nadir-only images and requires the images to have gimbal/camera angle information (not all drones provide this information).
Usage:
```
# Install DDB (required for geoprojection)
curl -fsSL https://get.dronedb.app -o get-ddb.sh
sh get-ddb.sh
# Run
python3 mergepreview.py -i images/*.JPG --size 25%
```
## Example
![screen](https://user-images.githubusercontent.com/1951843/134249725-e178489a-e271-4244-abed-e624cd510b88.png)
[Sheffield Park](https://community.opendronemap.org/t/sheffield-park-1/58) images processed with this script.
## Disclaimer
This script is highly experimental. We welcome contributions to improve it.

Wyświetl plik

@ -0,0 +1,126 @@
import argparse
import sys
sys.path.append("../../")
import os
from opendm import orthophoto
from opendm.cutline import compute_cutline
import glob
from opendm.system import run
from opendm import log
import shutil
parser = argparse.ArgumentParser(description='Quick Merge Preview')
parser.add_argument('input',
metavar='<paths>',
nargs='+',
help='Path to input images or image folder')
parser.add_argument('--size', '-s',
metavar='<percentage>',
type=str,
help='Size in percentage terms',
default='25%')
parser.add_argument('--force', '-f',
action='store_true',
default=False,
help="Force remove existing directories")
args = parser.parse_args()
try:
log.ODM_INFO("Checking for DDB...")
run("ddb --version")
except:
log.ODM_ERROR("ddb is not installed. Install it first: https://docs.dronedb.app")
if len(args.input) == 1 and os.path.isdir(args.input[0]):
input_images = []
for ext in ["JPG", "JPEG", "TIF", "tiff", "tif", "TIFF"]:
input_images += glob.glob(os.path.join(args.input[0], "*.%s" % ext))
else:
input_images = args.input
log.ODM_INFO("Processing %s images" % len(input_images))
if len(input_images) == 0:
log.ODM_ERROR("No images")
exit(1)
cwd_path = os.path.dirname(input_images[0])
tmp_path = os.path.join(cwd_path, "tmp")
if os.path.isdir(tmp_path):
if args.force:
log.ODM_INFO("Removing previous directory %s" % tmp_path)
shutil.rmtree(tmp_path)
else:
log.ODM_ERROR("%s exists. Pass --force to override." % tmp_path)
exit(1)
os.makedirs(tmp_path)
for f in input_images:
name, _ = os.path.splitext(os.path.basename(f))
geojson = os.path.join(tmp_path, "%s.geojson" % name)
gpkg = os.path.join(tmp_path, "%s.gpkg" % name)
run("ddb geoproj \"%s\" \"%s\" -s \"%s\"" % (tmp_path, f, args.size))
# Bounds (GPKG)
run("ddb info --format geojson --geometry polygon \"%s\" > \"%s\"" % (f, geojson))
run("ogr2ogr \"%s\" \"%s\"" % (gpkg, geojson))
log.ODM_INFO("Computing cutlines")
projected_images = glob.glob(os.path.join(tmp_path, "*.tif"))
all_orthos_and_ortho_cuts = []
for f in projected_images:
name, _ = os.path.splitext(os.path.basename(f))
cutline_file = os.path.join(tmp_path, "%s_cutline.gpkg" % name)
bounds_file_path = os.path.join(tmp_path, "%s.gpkg" % name)
compute_cutline(f,
bounds_file_path,
cutline_file,
4,
scale=1)
cut_raster = os.path.join(tmp_path, "%s_cut.tif" % name)
orthophoto.compute_mask_raster(f, cutline_file,
cut_raster,
blend_distance=20, only_max_coords_feature=True)
feathered_raster = os.path.join(tmp_path, "%s_feathered.tif" % name)
orthophoto.feather_raster(f, feathered_raster,
blend_distance=20
)
all_orthos_and_ortho_cuts.append([feathered_raster, cut_raster])
log.ODM_INFO("Merging...")
if len(all_orthos_and_ortho_cuts) > 1:
# TODO: histogram matching via rasterio
# currently parts have different color tones
output_file = os.path.join(cwd_path, 'mergepreview.tif')
if os.path.isfile(output_file):
os.remove(output_file)
orthophoto.merge(all_orthos_and_ortho_cuts, output_file, {
'TILED': 'YES',
'COMPRESS': 'LZW',
'PREDICTOR': '2',
'BIGTIFF': 'IF_SAFER',
'BLOCKXSIZE': 512,
'BLOCKYSIZE': 512
})
log.ODM_INFO("Wrote %s" % output_file)
shutil.rmtree(tmp_path)
else:
log.ODM_ERROR("Error: no orthos found to merge")
exit(1)

Wyświetl plik

@ -145,9 +145,12 @@ def compute_cutline(orthophoto_file, crop_area_file, destination, max_concurrenc
if len(polygons) == 0:
log.ODM_WARNING("No polygons, cannot compute cutline")
return
log.ODM_INFO("Merging polygons")
cutline_polygons = unary_union(polygons)
if not hasattr(cutline_polygons, '__getitem__'):
cutline_polygons = [cutline_polygons]
largest_cutline = cutline_polygons[0]
max_area = largest_cutline.area
for p in cutline_polygons: