diff --git a/opendm/grass/generate_cutlines.grass b/opendm/grass/generate_cutlines.grass index 36c5f856..0f32b3e3 100644 --- a/opendm/grass/generate_cutlines.grass +++ b/opendm/grass/generate_cutlines.grass @@ -2,7 +2,7 @@ # max_concurrency: maximum number of parallel processes to use # memory: maximum MB of memory to use # ------ -# output: If successful, prints the full path to the contours file. Otherwise it prints "error" +# output: If successful, prints the full path to the cutlines file. Otherwise it prints "error" # Split string using ',' separator IFS=',' read -ra DST <<< "${orthophoto_files}" @@ -10,14 +10,40 @@ ORTHOPHOTO_FILES=("$${DST[@]}") i=0 existing_cutlines="" +current_rasters="" + for orthophoto_file in "$${ORTHOPHOTO_FILES[@]}"; do - # Import orthophoto - r.external input=$$orthophoto_file output=ortho$$i --overwrite + # Import orthophoto (green band only) + r.external band=2 input="$$orthophoto_file" output=ortho$$i --overwrite - # Generate cutlines - i.cutlines --overwrite input=ortho$$i output=cutline$$i number_lines=4 edge_detection=zc processes=${max_concurrency} memory=${memory} + # Generate polygon area + gdal_polygonize.py -b 4 -f GeoPKG + # Set nodata + r.null map=ortho$$i setnull=0 + + current_rasters="ortho$$i,$$current_rasters" + g.region raster="$$current_rasters" + + # Generate cutlines + i.cutlines.py --overwrite input=ortho$$i output=cutline$$i number_lines=4 edge_detection=zc existing_cutlines=$$existing_cutlines processes=${max_concurrency} memory=${memory} + + # TODO: use below for values (canny, etc.) + #i.cutlines.py --overwrite input=ortho2.blue@PERMANENT output=cutline number_lines=16 edge_detection=canny no_edge_friction=10 lane_border_multiplier=100 processes=1 memory=300 + + + # TODO select only polygons within safe area + #v.select ainput=cutline -binput=area -output=result operator=within + + # TODO add these too + # GRASS commands for dissolve don't seem to work as expected + #ogr2ogr -f GPKG -overwrite -explodecollections -dialect SQLite -sql "SELECT ST_Union(geom) FROM result" -nln dissolved dissolved.gpkg result.gpkg + #ogr2ogr -f GPKG -overwrite -dialect SQLITE -sql "SELECT * FROM dissolved ORDER BY ST_AREA(geom) DESC LIMIT 1" -nln cutline cutline.gpkg dissolved.gpkg + + # Export + v.out.ogr input="cutline$$i" output="cutline$$i.gpkg" format=GPKG + # Prepend cutline to list of cutlines existing_cutlines="cutline$$i,$$existing_cutlines" @@ -25,13 +51,8 @@ for orthophoto_file in "$${ORTHOPHOTO_FILES[@]}"; do i=$$[i+1] done -last_cutline="cutline$$[i-1]" - -# Export -v.out.ogr input="$$last_cutline" output="cutline.gpkg" format=GPKG - -if [ -e "cutline.gpkg" ]; then - echo "$$(pwd)/cutline.gpkg" +if [ -e "cutline0.gpkg" ]; then + echo "$$(pwd)/cutline0.gpkg" else echo "error" fi diff --git a/opendm/grass_engine.py b/opendm/grass_engine.py index 95a20744..29389a8e 100644 --- a/opendm/grass_engine.py +++ b/opendm/grass_engine.py @@ -2,6 +2,8 @@ import shutil import tempfile import subprocess import os +import sys +import time from opendm import log from opendm import system @@ -88,20 +90,29 @@ class GrassContext: f.write(tmpl.substitute(self.template_args)) # Execute it - log.ODM_INFO("Executing grass script from {}: {} -c {} location --exec sh script.sh".format(self.get_cwd(), self.grass_binary, self.location)) + log.ODM_INFO("Executing grass script from {}: {} --tmp-location {} --exec bash script.sh".format(self.get_cwd(), self.grass_binary, self.location)) env = os.environ.copy() - env["GRASS_ADDON_PATH"] = env.get("GRASS_ADDON_PATH", "") + ":" + os.path.abspath(os.path.join("scripts/grass_addons")) - p = subprocess.Popen([self.grass_binary, '-c', self.location, 'location', '--exec', 'sh', 'script.sh'], - cwd=self.get_cwd(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) - out, err = p.communicate() + env["GRASS_ADDON_PATH"] = env.get("GRASS_ADDON_PATH", "") + os.path.abspath(os.path.join("scripts/grass_addons")) + + filename = os.path.join(self.get_cwd(), 'output.log') + with open(filename, 'wb') as writer, open(filename, 'rb', 1) as reader: + p = subprocess.Popen([self.grass_binary, '--tmp-location', self.location, '--exec', 'bash', 'script.sh'], + cwd=self.get_cwd(), stdout=subprocess.PIPE, stderr=writer, env=env) + + while p.poll() is None: + sys.stdout.write(reader.read()) + time.sleep(0.5) + + # Read the remaining + sys.stdout.write(reader.read()) - out = out.decode('utf-8').strip() - err = err.decode('utf-8').strip() + out, err = p.communicate() + out = out.decode('utf-8').strip() - if p.returncode == 0: - return out - else: - raise GrassEngineException("Could not execute GRASS script {} from {}: {}".format(script, self.get_cwd(), err)) + if p.returncode == 0: + return out + else: + raise GrassEngineException("Could not execute GRASS script {} from {}: {}".format(script, self.get_cwd(), err)) def serialize(self): return { diff --git a/run.py b/run.py index 86326dfc..39a51a66 100755 --- a/run.py +++ b/run.py @@ -43,7 +43,7 @@ if __name__ == '__main__': app.execute() # Do not show ASCII art for local submodels runs - if not "submodels/submodel_" in args.project_path: + if False and not "submodels/submodel_" in args.project_path: log.ODM_INFO('MMMMMMMMMMMNNNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNNNMMMMMMMMMMM') log.ODM_INFO('MMMMMMdo:..---../sNMMMMMMMMMMMMMMMMMMMMMMMMMMNs/..---..:odMMMMMM') log.ODM_INFO('MMMMy-.odNMMMMMNy/`/mMMMMMMMMMMMMMMMMMMMMMMm/`/hNMMMMMNdo.-yMMMM') diff --git a/scripts/grass_addons/i.cutlines.py b/scripts/grass_addons/i.cutlines.py old mode 100644 new mode 100755 diff --git a/scripts/splitmerge.py b/scripts/splitmerge.py index dd3c58ca..a661ee6b 100644 --- a/scripts/splitmerge.py +++ b/scripts/splitmerge.py @@ -136,13 +136,17 @@ class ODMMergeStage(types.ODM_Stage): if len(all_orthophotos) > 1: gctx = grass.create_context({'auto_cleanup' : False}) - gctx.add_param('orthophoto_files', ",".join(map(quote, all_orthophotos))) + gctx.add_param('orthophoto_files', ",".join(all_orthophotos)) gctx.add_param('max_concurrency', args.max_concurrency) - gctx.add_param('memory', concurrency.get_max_memory_mb(300)) + gctx.add_param('memory', int(concurrency.get_max_memory_mb(300))) gctx.set_location(all_orthophotos[0]) cutline_file = gctx.execute(os.path.join("opendm", "grass", "generate_cutlines.grass")) - + if cutline_file != 'error': + log.ODM_INFO("YAY") + log.ODM_INFO(cutline_file) + else: + log.ODM_WARNING("Could not generate orthophoto cutlines. An error occured when running GRASS. No orthophoto will be generated.") elif len(all_orthophotos) == 1: # Simply copy log.ODM_WARNING("A single orthophoto was found between all submodels.")