def read_polygons_from_small_patch(in_shp, in_raster): '''read polygons and seperate to touch and not touch image edge groups''' print(datetime.now(), 'reading polygons to touch and not touch image edge group') polygons = vector_gpd.read_polygons_gpd(in_shp, b_fix_invalid_polygon=False) img_bound = raster_io.get_image_bound_box(in_raster) img_resx, img_resy = raster_io.get_xres_yres_file(in_raster) half_res = img_resx / 2.0 image_edge = vector_gpd.convert_image_bound_to_shapely_polygon(img_bound) polygons_buff = [item.buffer(half_res) for item in polygons] # buffer half pixel # polygons_touch_img_edge_index = [] polygon_no_touch = [] polygons_touch = [] for idx, (polybuff, poly) in enumerate(zip(polygons_buff, polygons)): if polybuff.within(image_edge): polygon_no_touch.append(poly) else: # polygons_touch_img_edge_index.append(idx) polygons_touch.append(poly) # return polygons,polygons_touch_img_edge_index return polygon_no_touch, polygons_touch
def main(options, args): img_dir = args[0] output = options.output if os.path.isdir(img_dir): img_pattern = options.image_pattern if output is None: output = os.path.basename(img_dir) + '_boxes.gpkg' img_list = io_function.get_file_list_by_pattern(img_dir, img_pattern) if len(img_list) < 1: raise ValueError('No images in %s with pattern: %s' % (img_dir, img_pattern)) else: # if it's a file img_list = [img_dir] if output is None: output = os.path.basename(img_dir) + '_bound.gpkg' print('Find %d rasters in %s' % (len(img_list), img_dir)) # check projections? prj4_1st = raster_io.get_projection(img_list[0], 'proj4') for idx in range(1, len(img_list)): prj4 = raster_io.get_projection(img_list[idx], 'proj4') if prj4_1st != prj4: raise ValueError('projection inconsistent between %s and %s ' % (img_list[0], img_list[idx])) img_boxes = [ raster_io.get_image_bound_box(img_path) for img_path in img_list ] img_box_polygons = [ vector_gpd.convert_image_bound_to_shapely_polygon(box) for box in img_boxes ] # save to file wkt = map_projection.get_raster_or_vector_srs_info_proj4(img_list[0]) save_pd = pd.DataFrame({'raster': img_list, 'Polygon': img_box_polygons}) vector_gpd.save_polygons_to_files(save_pd, 'Polygon', wkt, output, format='GPKG') print('save raster extents to %s' % output) return
def get_dem_tif_ext_polygons(dem_list): bounding_box_list = [ raster_io.get_image_bound_box(tif) for tif in dem_list ] ext_polys = [ vector_gpd.convert_image_bound_to_shapely_polygon(box) for box in bounding_box_list] return ext_polys
def zonal_stats_multiRasters(in_shp, raster_file_or_files, nodata=None, band=1, stats=None, prefix='', range=None, all_touched=True, process_num=1): ''' zonal statistic based on vectors, along multiple rasters (image tiles) Args: in_shp: input vector file raster_file_or_files: a raster file or multiple rasters nodata: band: band stats: like [mean, std, max, min] range: interested values [min, max], None means infinity all_touched: process_num: process number for calculation Returns: ''' io_function.is_file_exist(in_shp) if stats is None: basic.outputlogMessage('warning, No input stats, set to ["mean"])') stats = ['mean'] if isinstance(raster_file_or_files, str): io_function.is_file_exist(raster_file_or_files) image_tiles = [raster_file_or_files] elif isinstance(raster_file_or_files, list): image_tiles = raster_file_or_files else: raise ValueError('unsupport type for %s' % str(raster_file_or_files)) # check projection (assume we have the same projection), check them outside this function # get image box img_tile_boxes = [ raster_io.get_image_bound_box(tile) for tile in image_tiles ] img_tile_polygons = [ vector_gpd.convert_image_bound_to_shapely_polygon(box) for box in img_tile_boxes ] polygons = vector_gpd.read_polygons_gpd(in_shp) if len(polygons) < 1: basic.outputlogMessage('No polygons in %s' % in_shp) return False # polygons_json = [mapping(item) for item in polygons] # no need when use new verion of rasterio # process polygons one by one polygons and the corresponding image tiles (parallel and save memory) # also to avoid error: daemonic processes are not allowed to have children if process_num == 1: stats_res_list = [] for idx, polygon in enumerate(polygons): out_stats = zonal_stats_one_polygon(idx, polygon, image_tiles, img_tile_polygons, stats, nodata=nodata, range=range, band=band, all_touched=all_touched) stats_res_list.append(out_stats) elif process_num > 1: threadpool = Pool(process_num) para_list = [(idx, polygon, image_tiles, img_tile_polygons, stats, nodata, range, band, all_touched) for idx, polygon in enumerate(polygons)] stats_res_list = threadpool.starmap(zonal_stats_one_polygon, para_list) else: raise ValueError('Wrong process number: %s ' % str(process_num)) # save to shapefile add_attributes = {} new_key_list = [prefix + '_' + key for key in stats_res_list[0].keys()] for new_ley in new_key_list: add_attributes[new_ley] = [] for stats_result in stats_res_list: for key in stats_result.keys(): add_attributes[prefix + '_' + key].append(stats_result[key]) vector_gpd.add_attributes_to_shp(in_shp, add_attributes) pass
def zonal_stats_multiRasters(in_shp, raster_file_or_files, nodata=None, band = 1, stats = None, prefix='', range=None,buffer=None, all_touched=True, process_num=1): ''' zonal statistic based on vectors, along multiple rasters (image tiles) Args: in_shp: input vector file raster_file_or_files: a raster file or multiple rasters nodata: band: band stats: like [mean, std, max, min] range: interested values [min, max], None means infinity buffer: expand polygon with buffer (meter) before the statistic all_touched: process_num: process number for calculation Returns: ''' io_function.is_file_exist(in_shp) if stats is None: basic.outputlogMessage('warning, No input stats, set to ["mean"])') stats = ['mean'] stats_backup = stats.copy() if 'area' in stats: stats.remove('area') if 'count' not in stats: stats.append('count') if isinstance(raster_file_or_files,str): io_function.is_file_exist(raster_file_or_files) image_tiles = [raster_file_or_files] elif isinstance(raster_file_or_files,list): image_tiles = raster_file_or_files else: raise ValueError('unsupport type for %s'%str(raster_file_or_files)) # check projection (assume we have the same projection), check them outside this function # get image box img_tile_boxes = [raster_io.get_image_bound_box(tile) for tile in image_tiles] img_tile_polygons = [vector_gpd.convert_image_bound_to_shapely_polygon(box) for box in img_tile_boxes] polygons = vector_gpd.read_polygons_gpd(in_shp) if len(polygons) < 1: basic.outputlogMessage('No polygons in %s'%in_shp) return False # polygons_json = [mapping(item) for item in polygons] # no need when use new verion of rasterio if buffer is not None: polygons = [ poly.buffer(buffer) for poly in polygons] # process polygons one by one polygons and the corresponding image tiles (parallel and save memory) stats_res_list = [] for idx, polygon in enumerate(polygons): out_stats = zonal_stats_one_polygon(idx, polygon, image_tiles, img_tile_polygons, stats, nodata=nodata, range=range, band=band, all_touched=all_touched) stats_res_list.append(out_stats) # threadpool = Pool(process_num) # para_list = [ (idx, polygon, image_tiles, img_tile_polygons, stats, nodata, range,band, all_touched) # for idx, polygon in enumerate(polygons)] # stats_res_list = threadpool.starmap(zonal_stats_one_polygon,para_list) # save to shapefile add_attributes = {} new_key_list = [ prefix + '_' + key for key in stats_res_list[0].keys()] for new_ley in new_key_list: add_attributes[new_ley] = [] for stats_result in stats_res_list: for key in stats_result.keys(): add_attributes[prefix + '_' + key].append(stats_result[key]) if 'area' in stats_backup: dx, dy = raster_io.get_xres_yres_file(image_tiles[0]) add_attributes[prefix + '_' + 'area'] = [ count*dx*dy for count in add_attributes[prefix + '_' + 'count'] ] if 'count' not in stats_backup: del add_attributes[prefix + '_' + 'count'] vector_gpd.add_attributes_to_shp(in_shp,add_attributes) pass