Thursday, 3 September 2015

python - How to split multiband image into image tiles using Rasterio?


I have been using this answer on GIS SE to split 3-band (RGB) imagery into 256x256 3-band image tiles:


import os, gdal

in_path = '/path/to/indata/'
input_filename = 'dtm_5.tif'

out_path = '/path/to/output_folder/'

output_filename = 'tile_'

tile_size_x = 256
tile_size_y = 256

ds = gdal.Open(in_path + input_filename)
band = ds.GetRasterBand(1)
xsize = band.XSize
ysize = band.YSize


for i in range(0, xsize, tile_size_x):
for j in range(0, ysize, tile_size_y):
com_string = "gdal_translate -of GTIFF -srcwin " + str(i)+ ", " + str(j) + ", " + str(tile_size_x) + ", " + str(tile_size_y) + " " + str(in_path) + str(input_filename) + " " + str(out_path) + str(output_filename) + str(i) + "_" + str(j) + ".tif"
os.system(com_string)

Is there a comparable Rasterio or numpy approach?



Answer



Below is a simple example (rasterio 1.0.0 or later, won't work in 0.3.6). There might be better/simpler ways (and there is an easier way if your raster is internally tiled and the tile block sizes match your desired output tile size).


The rasterio docs have some examples of concurrent processing if you want to go down that road.


import os

from itertools import product
import rasterio as rio
from rasterio import windows

in_path = '/path/to/indata/'
input_filename = 'dtm_5.tif'

out_path = '/path/to/output_folder/'
output_filename = 'tile_{}-{}.tif'


def get_tiles(ds, width=256, height=256):
nols, nrows = ds.meta['width'], ds.meta['height']
offsets = product(range(0, nols, width), range(0, nrows, height))
big_window = windows.Window(col_off=0, row_off=0, width=nols, height=nrows)
for col_off, row_off in offsets:
window =windows.Window(col_off=col_off, row_off=row_off, width=width, height=height).intersection(big_window)
transform = windows.transform(window, ds.transform)
yield window, transform



with rio.open(os.path.join(in_path, input_filename)) as inds:
tile_width, tile_height = 256, 256

meta = inds.meta.copy()

for window, transform in get_tiles(inds):
print(window)
meta['transform'] = transform
meta['width'], meta['height'] = window.width, window.height
outpath = os.path.join(out_path,output_filename.format(int(window.col_off), int(window.row_off)))

with rio.open(outpath, 'w', **meta) as outds:
outds.write(inds.read(window=window))

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...