def test_potrace_minsize(self): """ Trace line with minsize smaller and larger than box """ geoimg = self.create_image_with_box() # check that minsize did not filter out box lines = vectorize.potrace(geoimg[0], minsize=100, geoloc=False) self.assertEqual(len(lines[0]), len(self.truth_coords)) # check that minsize does filter out box lines = vectorize.potrace(geoimg[0], minsize=200) self.assertEqual(len(lines), 0)
def test_save_shapefile(self): """ Save shapefile """ geoimg = self.create_image_with_box() lines = vectorize.potrace(geoimg[0]) fout = os.path.join(os.path.dirname(__file__), 'test-shapefile') vectorize.save_shapefile(lines, fout + '.shp') [os.remove(f) for f in glob.glob(fout + '.*')]
def test_potrace_empty_image(self): """ Trace image that is empty """ geoimg = create_image(empty=True) lines = vectorize.potrace(geoimg[0], geoloc=False) self.assertEqual(len(lines), 0) geoj = vectorize.to_geojson(lines) self.assertEqual(len(geoj['features']), 0)
def invoke(self): # Get inputs img = self.get_input_data_port('image') threshold = self.get_input_string_port('threshold') result_dir = self.get_output_data_port('result') os.makedirs(result_dir) # vectorize threshdolded (ie now binary) image all_lower = glob2.glob('%s/**/*.tif' % img) for img_file in all_lower: geoimg = gippy.GeoImage(img_file, True) coastline = bfvec.potrace(geoimg[0] > float(threshold), minsize=defaults['minsize'], close=defaults['close'], alphamax=defaults['smooth']) # convert coordinates to GeoJSON geojson = bfvec.to_geojson(coastline, source=geoimg.basename()) # write geojson output file with open(os.path.join(result_dir, 'result.geojson'), 'w') as f: f.write(json.dumps(geojson)) self.reason = 'Successfully traced raster'
def test_close_line_strings_real(self): """ Close line strings """ geoimg = download_image(self.test_url) geoimg.set_nodata(0) lines = vectorize.potrace(geoimg[0] > 9500, close=5) fout = os.path.splitext(os.path.join(os.path.dirname(__file__), os.path.basename(self.test_url)))[0] + '_closed.geojson' vectorize.save_geojson(lines, fout) print('\nPerform visual inspection on %s' % fout)
def test_potrace_box(self): """ Trace image of box """ geoimg = self.create_image_with_box() lines = vectorize.potrace(geoimg[0], geoloc=True) # check returned geometry self.assertEqual(len(lines[0]), len(self.truth_coords)) for c in lines[0]: self.assertTrue(c in self.truth_coords)
def test_potrace_image(self): """ Trace landsat using an arbitrary cutoff """ # get a complex test image (landsat) geoimg = download_image(self.test_url) geoimg.set_nodata(0) lines = vectorize.potrace(geoimg[0] > 9500, close=0) self.assertEqual(len(lines), 16551) fout = os.path.splitext(os.path.join(os.path.dirname(__file__), os.path.basename(self.test_url)))[0] + '.geojson' vectorize.save_geojson(lines, fout) print('\nPerform visual inspection on %s' % fout)
def _test_trace_line(self): """ Trace image of line """ geoimg = self.create_image_with_line() geojson = vectorize.potrace(geoimg[0], geoloc=False) # check returned geometry coords = geojson['features'][0]['geometry']['coordinates'] self.assertEqual(len(coords), len(self.truth_coords)) for c in coords: self.assertTrue(c in self.truth_coords)
def test_potrace_only_nodata(self): """ Trace image that has only nodata """ geoimg = create_image(empty=True) arr = geoimg.read() # make a nodata region arr[0:5, 0:5] = geoimg[0].nodata() geoimg[0].write(arr) lines = vectorize.potrace(geoimg[0], geoloc=False) self.assertEqual(len(lines), 0) geoj = vectorize.to_geojson(lines) self.assertEqual(len(geoj['features']), 0)
def test_save_geojson(self): """ Validate geojson returned from trace """ geoimg = create_image() lines = vectorize.potrace(geoimg[0]) fout = os.path.join(os.path.dirname(__file__), 'test.geojson') vectorize.save_geojson(lines, fout, source='test') with open(fout, 'r') as f: geojson = json.loads(f.read()) self.assertTrue('type' in geojson.keys()) self.assertEqual(geojson['type'], 'FeatureCollection') self.assertTrue('features' in geojson.keys()) self.assertEqual(len(geojson['features']), 0) os.remove(fout)
def test_potrace_nodata(self): """ Trace image with nodata present """ geoimg = self.create_image_with_box() arr = geoimg.read() # make a nodata region arr[0:10, 0:10] = geoimg[0].nodata() geoimg[0].write(arr) lines = vectorize.potrace(geoimg[0], latlon=False) self.assertEqual(len(lines), 1) self.assertEqual(len(lines[0]), 7) self.assertEqual( lines[0], [[0.65, 0.8], [0.8, 0.8], [0.8, 0.5], [0.8, 0.19999999999999996], [0.5, 0.19999999999999996], [0.2, 0.19999999999999996], [0.2, 0.35]])
def test_simplify(self): """ Simplify GeoJSON geometries """ geoimg = download_image(self.test_url) geoimg.set_nodata(0) lines = vectorize.potrace(geoimg[0] > 9500, close=0) fout = os.path.join(os.path.dirname(__file__), 'test.geojson') vectorize.save_geojson(lines, fout) # check file df = ogr.Open(fout) layer = df.GetLayer() self.assertEqual(layer.GetFeatureCount(), len(lines)) geom = json.loads(layer.GetNextFeature().ExportToJson()) self.assertEqual(len(geom['geometry']['coordinates']), len(lines[0])) df = None # simplify and check file vectorize.simplify(fout, tolerance=0.001) df = ogr.Open(fout) layer = df.GetLayer() geom = json.loads(layer.GetNextFeature().ExportToJson()) self.assertEqual(len(geom['geometry']['coordinates']), 22)
def process(geoimg, coastmask=defaults['coastmask'], minsize=defaults['minsize'], close=defaults['close'], simple=defaults['simple'], smooth=defaults['smooth'], outdir='', bname=None): """ Process data from indir to outdir """ if bname is None: bname = geoimg.basename() if outdir is None: outdir = tempfile.mkdtemp() prefix = os.path.join(outdir, bname) # calculate NWDI fout = prefix + '_ndwi.tif' logger.info('Saving NDWI to file %s' % fout, action='Save file', actee=fout, actor=__name__) imgout = alg.indices(geoimg, ['ndwi'], filename=fout) # mask with coastline if coastmask: # open coastline vector fname = os.path.join(os.path.dirname(__file__), 'coastmask.shp') fout_coast = prefix + '_coastmask.tif' try: imgout = bfmask.mask_with_vector(imgout, (fname, ''), filename=fout_coast) except Exception as e: if str(e) == 'No features after masking': logger.warning( 'Image does not intersect coastal mask. Generating empty geojson file. Error: %s/' % str(e)) geojson = {'type': 'FeatureCollection', 'features': []} fout = prefix + '.geojson' logger.info('Saving GeoJSON to file %s' % fout, action='Save file', actee=fout, actor=__name__) with open(fout, 'w') as f: f.write(json.dumps(geojson)) return geojson if str(e) == "'NoneType' object has no attribute 'ExportToJson'": logger.warning( 'Image does not intersect coastal mask. Generating empty geojson file. Error: %s/' % str(e)) geojson = {'type': 'FeatureCollection', 'features': []} fout = prefix + '.geojson' logger.info('Saving GeoJSON to file %s' % fout, action='Save file', actee=fout, actor=__name__) with open(fout, 'w') as f: f.write(json.dumps(geojson)) return geojson else: logger.warning('Error encountered during masking. Error : %s' % str(e)) raise RuntimeError(e) # calculate optimal threshold threshold = bfproc.otsu_threshold(imgout[0]) logger.debug("Otsu's threshold = %s" % threshold) #import pdb; pdb.set_trace() # save thresholded image #if False: #logger.level <= logging.DEBUG: fout = prefix + '_thresh.tif' logger.debug('Saving thresholded image as %s' % fout) logger.info('Saving threshold image to file %s' % fout, action='Save file', actee=fout, actor=__name__) imgout2 = gippy.GeoImage.create_from(imgout, filename=fout, dtype='byte') imgout2.set_nodata(255) #pdb.set_trace() (imgout[0] > threshold).save(imgout2[0]) imgout = imgout2 # vectorize threshdolded (ie now binary) image coastline = bfvec.potrace(imgout[0], minsize=minsize, close=close, alphamax=smooth) # convert coordinates to GeoJSON geojson = bfvec.to_geojson(coastline, source=geoimg.basename()) # write geojson output file fout = prefix + '.geojson' logger.info('Saving GeoJSON to file %s' % fout, action='Save file', actee=fout, actor=__name__) with open(fout, 'w') as f: f.write(json.dumps(geojson)) if simple is not None: fout = bfvec.simplify(fout, tolerance=simple) return geojson
def test_close_line_strings(self): """ Close line strings """ geoimg = self.create_image_with_box() lines = vectorize.potrace(geoimg[0], geoloc=True, close=6) self.assertEqual(len(lines[0]), 9)