Exemple #1
0
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
Exemple #2
0
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
Exemple #4
0
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