def save_tile_by_grid(self): # query condition: zone of utm + bbox of wgs84 raster = rasterio.open(self.raster_file, 'r') utm_zone = raster.crs['init'][-2:] bbox = raster.bounds utm_extent = [[bbox.left, bbox.top], [bbox.left, bbox.bottom], [bbox.right, bbox.bottom], [bbox.right, bbox.top], [bbox.left, bbox.top]] utm2wgs = GeomTrans(str(raster.crs.wkt), 'EPSG:4326') wgs_extent = utm2wgs.transform_points(utm_extent) wgs_boundary = {'coordinates': [wgs_extent], 'type': 'Polygon'} grid_dicts = self.search_grids(grid_index_name, utm_zone, wgs_boundary) for grid in grid_dicts: gridid = grid['_source']['gridid'] utm_geometry = grid['_source']['utm_geometry'] tile_file = self._get_tile(self.dataid, gridid) tile_path = os.path.dirname(tile_file) if not os.path.exists(tile_path): os.makedirs(tile_path) self.mask_image_by_geometry(utm_geometry, raster, tile_file) utm_zone = grid['_source']['zone'] wgs_crs = grid['_source']['wgs_crs'] utm_crs = grid['_source']['utm_crs'] wgs_grid = grid['_source']['wgs_geometry'] utm_grid = grid['_source']['utm_geometry'] self.metadb.insert_tilemeta(tile_index_name, "landsat45_tiles", self.dataid, self.bandid, self.ctime, self.sensor, tile_file, gridid, utm_zone, wgs_crs, utm_crs, wgs_grid, utm_grid)
def main(file): # dataid for metadata items = file.split("/") dataid = items[-1].split(".")[0] # query condition: zone of utm + bbox of wgs84 raster = rasterio.open(file, 'r') utm_zone = raster.crs['init'][-2:] bbox = raster.bounds utm_extent = [[bbox.left, bbox.top], [bbox.left, bbox.bottom], [bbox.right, bbox.bottom], [bbox.right, bbox.top], [bbox.left, bbox.top]] utm2wgs = GeomTrans(str(raster.crs.wkt), 'EPSG:4326') wgs_extent = utm2wgs.transform_points(utm_extent) wgs_boundary = {'coordinates': [wgs_extent], 'type': 'Polygon'} grid_dicts = query_grids(utm_zone, wgs_boundary) for grid in grid_dicts: print(grid['_source']['gridid']) utm_geometry = grid['_source']['utm_geometry'] tile_path = os.path.join( '/tmp', dataid + '_' + grid['_source']['gridid'] + '.tif') mask_image_by_geometry(utm_geometry, raster, tile_path)
def __init__(self, geomjson=None, geomproj=None, rsimage=None): self.geomjson = geomjson self.geomproj = geomproj self.raster = rsimage transform = GeomTrans(str(self.geomproj), str(self.raster.crs.wkt)) if geomjson['type'] == 'Polygon': geojson_crs_transformed = transform.transform_points( self.geomjson['coordinates'][0]) elif geomjson['type'] == 'LineString': geojson_crs_transformed = transform.transform_points( self.geomjson['coordinates']) print(geojson_crs_transformed) geometry = shape({ 'coordinates': [geojson_crs_transformed], 'type': 'Polygon' }) self.geometry = geometry
def main(file): # dataid for metadata items = file.split("/") dataid = items[-1].split(".")[0] bandname = 'B0'+dataid[-1:] time = dataid[14:22] sensor = dataid[:2] row = int(dataid[6:9]) path = int(dataid[10:13]) year = int(time[:4]) # query condition: zone of utm + bbox of wgs84 raster = rasterio.open(file, 'r') utm_zone = raster.crs['init'][-2:] bbox = raster.bounds utm_extent = [[bbox.left, bbox.top], [bbox.left, bbox.bottom], [bbox.right, bbox.bottom], [bbox.right, bbox.top], [bbox.left, bbox.top]] utm2wgs = GeomTrans(str(raster.crs.wkt), 'EPSG:4326') wgs_extent = utm2wgs.transform_points(utm_extent) wgs_boundary = {'coordinates': [wgs_extent], 'type': 'Polygon'} grid_dicts = query_grids(utm_zone, wgs_boundary) for grid in grid_dicts: print(grid['_source']['gridid']) utm_geometry = grid['_source']['utm_geometry'] # tile_path = os.path.join("/tmp", dataid + '_' + grid['_source']['gridid'] + '.tif') tile_path = "/LANDSAT/L45TM/%s/%s/%s/%s/%s" % (row, path, year, time, grid['_source']['gridid']) tile_file = os.path.join(tile_path, dataid + '_' + grid['_source']['gridid'] + '.tif') mask_image_by_geometry(utm_geometry, raster, tile_file) # metadata for the tile clipped from landsat by a grid geojson_l = {} geojson_l['dataid']=dataid geojson_l['bandid']=bandname geojson_l["date_acquired"] = time geojson_l["sensor"] = sensor geojson_l['tile_path']=tile_path geojson_l['gridid'] = grid['_source']['gridid'] geojson_l['zone'] = grid['_source']['zone'] geojson_l['wgs_crs'] = grid['_source']['wgs_crs'] geojson_l['utm_crs'] = grid['_source']['utm_crs'] geojson_l['wgs_grid'] = grid['_source']['wgs_geometry'] print(geojson_l['wgs_grid']) geojson_l['utm_grid'] = grid['_source']['utm_geometry'] # print(geojson_l) es.index(index=index_name, doc_type="landsat45_tiles", body=geojson_l)
utm_layerDefn = utm_lyr.GetLayerDefn() # 5 create a field idField = ogr.FieldDefn('GridID', ogr.OFTString) # geomField = ogr.GeomFieldDefn('the_geom', ogr.wkbPolygon) wgs_lyr.CreateField(idField) # wgs_lyr.CreateGeomField(geomField) # wgs_lyr.CreateField(geomField) utm_lyr.CreateField(idField) # for each grid cell id = 0 for geo_json in json_list: corner_points = geo_json['geometry']['coordinates'][0] # utm to wgs corner_points_wgs = utm2wgs.transform_points(corner_points) # delete those grids not between 80S to 84N points_array = np.array(corner_points_wgs) max_lat = np.max(points_array[:, 1]) min_lat = np.min(points_array[:, 1]) if max_lat > 84 or min_lat < -80: continue corner_points_moved = [] for point in corner_points_wgs: # wgs move degree x = point[0] + mv_degree y = point[1] corner_points_moved.append((x, y))
def mask_image_by_geometry(geomjson, geomproj, raster, tag, name): print('the %s geometry' % name) transform = GeomTrans(str(geomproj), str(raster.crs.wkt)) geojson_crs_transformed = transform.transform_points( geomjson['coordinates'][0]) geometry = shape({ 'coordinates': [geojson_crs_transformed], 'type': 'Polygon' }) bbox = raster.bounds extent = [[bbox.left, bbox.top], [bbox.left, bbox.bottom], [bbox.right, bbox.bottom], [bbox.right, bbox.top]] raster_boundary = shape({'coordinates': [extent], 'type': 'Polygon'}) if not geometry.intersects(raster_boundary): return # get pixel coordinates of the geometry's bounding box, ll = raster.index( *geometry.bounds[0:2]) # lowerleft bounds[0:2] xmin, ymin ur = raster.index( *geometry.bounds[2:4]) # upperright bounds[2:4] xmax, ymax # # create an affine transform for the subset data # t = raster.transform # shifted_affine = Affine(t.a, t.b, t.c + ll[1] * t.a, t.d, t.e, t.f + ur[0] * t.e) # # # read the subset of the data into a numpy array # window = ((ur[0], ll[0] + 1), (ll[1], ur[1] + 1)) # when the shapefile polygon is larger than the raster row_begin = ur[0] if ur[0] > 0 else 0 row_end = ll[0] + 1 if ll[0] > -1 else 0 col_begin = ll[1] if ll[1] > 0 else 0 col_end = ur[1] + 1 if ur[1] > -1 else 0 window = ((row_begin, row_end), (col_begin, col_end)) # create an affine transform for the subset data t = raster.transform shifted_affine = Affine(t.a, t.b, t.c + col_begin * t.a, t.d, t.e, t.f + row_begin * t.e) out_data = raster.read(window=window) # check whether the numpy array is empty or not? if out_data.size == 0 or np.all(out_data == raster.nodata): print('the grid does not intersect with the raster') return # if len(out_data)==0: # print('the grid does not intersect with the raster') # return with rasterio.open("/tmp/mask_%s.tif" % name, 'w', driver='GTiff', width=out_data.shape[2], height=out_data.shape[1], crs=raster.crs, transform=shifted_affine, dtype=np.uint16, nodata=256, count=raster.count, indexes=raster.indexes) as dst: # Write the src array into indexed bands of the dataset. If `indexes` is a list, the src must be a 3D array of matching shape. If an int, the src must be a 2D array. dst.write(out_data.astype(rasterio.uint16), indexes=raster.indexes) # bands_num = raster.count # multi_bands_data = [] # for i in range(bands_num): # # band_name = raster.indexes[i] # data = raster.read(i + 1, window=window) # # rasterize the geometry # mask = rasterio.features.rasterize([(geometry, 0)], out_shape=data.shape, transform=shifted_affine, fill=1, # all_touched=True, dtype=np.uint8) # # # create a masked numpy array # masked_data = np.ma.array(data=data, mask=mask.astype(bool), dtype=np.float32) # masked_data.data[masked_data.mask] = np.nan # raster.profile nodata is 256 # out_image = masked_data.data # multi_bands_data.append(out_image) # out_data = np.array(multi_bands_data) # with rasterio.open("/tmp/mask_%s.tif" % name, 'w', driver='GTiff', width=out_data.shape[2], # height=out_data.shape[1], crs=raster.crs, transform=shifted_affine, dtype=np.uint16, nodata=256, # count=bands_num, indexes=raster.indexes) as dst: # dst.write(out_image.astype(rasterio.uint16), 1) # create a masked label numpy array out_shape = ((window[0][1] - window[0][0]), (window[1][1] - window[1][0])) mask = rasterio.features.rasterize([(geometry, 0)], out_shape=out_shape, transform=shifted_affine, fill=1, all_touched=True, dtype=np.uint8) label_array = np.empty(out_shape) label_array[mask == 0] = tag with rasterio.open("/tmp/label_%s.tif" % name, 'w', driver='GTiff', width=out_shape[1], height=out_shape[0], crs=raster.crs, transform=shifted_affine, dtype=np.uint16, nodata=256, count=1) as dst: dst.write(label_array.astype(rasterio.uint16), 1)
def mask_image_by_geojson_polygon(geojson_polygon, geoproj, raster): ''' :param geojson_polygon: the geojson format of a polygon :param geoproj: the projection coordinate system of the input polygon :param raster: the raster data after executing the raster = rasterio.open(raster_image_file, 'r') :return: the data cut out from the raster by the polygon, and its geotransformation ''' transform = GeomTrans(str(geoproj), str(raster.crs.wkt)) geojson_crs_transformed = transform.transform_points( geojson_polygon['coordinates'][0]) geometry = shape({ 'coordinates': [geojson_crs_transformed], 'type': 'Polygon' }) bbox = raster.bounds extent = [[bbox.left, bbox.top], [bbox.left, bbox.bottom], [bbox.right, bbox.bottom], [bbox.right, bbox.top]] raster_boundary = shape({'coordinates': [extent], 'type': 'Polygon'}) # if not geometry.intersects(raster_boundary): # return if not geometry.within(raster_boundary): print('the geometry is not within the raster image') return # get pixel coordinates of the geometry's bounding box, ll = raster.index( *geometry.bounds[0:2]) # lowerleft bounds[0:2] xmin, ymin ur = raster.index( *geometry.bounds[2:4]) # upperright bounds[2:4] xmax, ymax # create an affine transform for the subset data t = raster.transform shifted_affine = Affine(t.a, t.b, t.c + ll[1] * t.a, t.d, t.e, t.f + ur[0] * t.e) # read the subset of the data into a numpy array window = ((ur[0], ll[0] + 1), (ll[1], ur[1] + 1)) bands_num = raster.count multi_bands_data = [] for i in range(bands_num): # band_name = raster.indexes[i] data = raster.read(i + 1, window=window) # rasterize the geometry mask = rasterio.features.rasterize([(geometry, 0)], out_shape=data.shape, transform=shifted_affine, fill=1, all_touched=True, dtype=np.uint8) # create a masked numpy array masked_data = np.ma.array(data=data, mask=mask.astype(bool), dtype=np.float32) masked_data.data[ masked_data.mask] = np.nan # raster.profile nodata is 256 out_image = masked_data.data multi_bands_data.append(out_image) out_data = np.array(multi_bands_data) return out_data, shifted_affine
def mask_image(geomjson, geomproj, raster, tag, name, size=(128, 128)): print('the %s geometry' % name) transform = GeomTrans(str(geomproj), str(raster.crs.wkt)) geojson_crs_transformed = transform.transform_points( geomjson['coordinates'][0]) geometry = shape({ 'coordinates': [geojson_crs_transformed], 'type': 'Polygon' }) bbox = raster.bounds extent = [[bbox.left, bbox.top], [bbox.left, bbox.bottom], [bbox.right, bbox.bottom], [bbox.right, bbox.top]] raster_boundary = shape({'coordinates': [extent], 'type': 'Polygon'}) if not geometry.intersects(raster_boundary): return # get pixel coordinates of the geometry's bounding box, ll = raster.index( *geometry.bounds[0:2]) # lowerleft bounds[0:2] xmin, ymin ur = raster.index( *geometry.bounds[2:4]) # upperright bounds[2:4] xmax, ymax # create an affine transform for the subset data t = raster.transform shifted_affine = Affine(t.a, t.b, t.c + ll[1] * t.a, t.d, t.e, t.f + ur[0] * t.e) # read the subset of the data into a numpy array window = ((ur[0], ll[0] + 1), (ll[1], ur[1] + 1) ) # rows, cols of ((xmax, xmin+1),(ymin, ymax+1)) window_shape = ( (window[0][1] - window[0][0]), (window[1][1] - window[1][0]) ) # or data = raster.read(1,window=window); out_shape = data.shape; # to generate 512*512 size mask if window_shape[0] <= size[0] and window_shape[1] <= size[1]: mask = rasterio.features.rasterize([(geometry, 0)], out_shape=window_shape, transform=shifted_affine, fill=1, all_touched=True, dtype=np.uint8) out_shape = np.zeros((size[0], size[1])) # expand the window of rasterized polygon into specified size mask_expanded = np.pad(mask, ((0, size[0] - window_shape[0]), (0, size[1] - window_shape[1])), mode='constant', constant_values=1) # generate label array label_array = np.empty_like(mask_expanded, dtype=np.float) label_array[mask_expanded == 0] = tag with rasterio.open("/tmp/label_%s.tif" % name, 'w', driver='GTiff', width=size[1], height=size[0], crs=raster.crs, transform=shifted_affine, dtype=np.uint16, nodata=256, count=1) as dst: dst.write(label_array.astype(rasterio.uint16), 1) # read the original rs image into specified size window_expanded = ((window[0][0], window[0][0] + size[0]), (window[1][0], window[1][0] + size[1])) out_data = raster.read(window=window_expanded) with rasterio.open("/tmp/mask_%s2.tif" % name, 'w', driver='GTiff', width=size[1], height=size[0], crs=raster.crs, transform=shifted_affine, dtype=np.uint16, nodata=256, count=raster.count, indexes=raster.indexes) as dst: # Write the src array into indexed bands of the dataset. If `indexes` is a list, the src must be a 3D array of matching shape. If an int, the src must be a 2D array. dst.write(out_data.astype(rasterio.uint16), indexes=raster.indexes)