Raster resampling refers to altering the raster resolution by changing raster grid. Upsampling refers to reducing pixel size and increasing resolution. And downsampling refers to increasing pixel size and reducing resolution.
The raster resampling or upscaling/downscaling is done when you want to convert 10 meter cell to 50 meter cell or vice versa. Even when you are reprojecting raster, resampling is done.
In this tutorial, we will discuss how to upscale/downscale or upsample/downsample raster in python.
Raster resampling is one of the common task in raster processing. In this tutorial, we will resample a raster in python using Rioxarray. Rioxarray is open source gis package that extends the functionality of xarray by rasterio.
Before upsampling/downsampling the raster data, we will set up conda environment and install required python GIS packages for this task. Make sure conda is installed on your system. Use following commands to create a conda environment and to install python libraries.
When you install geocube library using conda, it will automatically install related dependencies that includes gdal, shapely, rasterio, geopandas, xarray, rioxarray etc.
And we will also install pygeos library which is use to speed up the vectorized operations in GeoPandas and Shapely.
1 2 3 4 |
(base) geoknight@pop-os:~$conda create -n spatial-dev.guru python=3.10 (base) geoknight@pop-os:~$conda activate spatial-dev.guru (spatial-dev.guru) geoknight@pop-os:~$conda install -c conda-forge geocube (spatial-dev.guru) geoknight@pop-os:~$conda install -c conda-forge pygeos |
Raster Upsampling
In raster upsampling, we reduce the cell size and increase the raster grid. In the given example in below code, we are upscaling the raster by factor of 2. Meaning, we are dividing a pixel in 4 equal parts, thus reducing the cell size and increasing raster grid. In case of upsampling, the upscale_factor should be greater than 1. You can use any upscale factor like 3,4,5 etc according to your need.
We are upsampling using reproject method by passing crs, new height and width and resampling method.
In our example, we are using bilinear resampling method to upsample the raster.
After upsampling, cell size will reduced and raster grid size will be increased.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# Import libraries import rioxarray as riox from rasterio.enums import Resampling # Read raster raster = riox.open_rasterio('cal_census.tiff') upscale_factor = 2 # Caluculate new height and width using upscale_factor new_width = raster.rio.width * upscale_factor new_height = raster.rio.height * upscale_factor #upsample raster up_sampled = raster.rio.reproject(raster.rio.crs, shape=(int(new_height), int(new_width)), resampling=Resampling.bilinear) print(raster.rio.resolution(), up_sampled.rio.resolution()) # ((500.0, -500.0), (250.0, -250.0)) print(raster.shape, up_sampled.shape) # ((1, 2660, 2305), (1, 5320, 4610)) |
Raster Downsampling
In raster downsampling, we increase the cell size and reduce the raster grid. The process of raster downsampling is same as raster upsampling we discussed above. The only thing we change is scale factor. We have defined downscale_factor with 1/2 value. This means downsampling by half. Here, we are taking any adjacent 4 pixels and converting them into one pixel. Thus increasing the cell size and reducing the raster grid.
For downsmapling, the downscale_factor should be less than 1.The rest steps are same as we discussed in upsampling.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# Import libraries import rioxarray as riox from rasterio.enums import Resampling # Read Raster raster = riox.open_rasterio('cal_census.tiff') downscale_factor = 1/2 #Caluculate new height and width using downscale_factor new_width = raster.rio.width * downscale_factor new_height = raster.rio.height * downscale_factor #downsample raster down_sampled = raster.rio.reproject(raster.rio.crs, shape=(int(new_height), int(new_width)), resampling=Resampling.bilinear) print(raster.rio.resolution(), down_sampled.rio.resolution()) # ((500.0, -500.0), (1000.4340277777777, -1000.0)) print(raster.shape, down_sampled.shape) # ((1, 2660, 2305), (1, 1330, 1152)) |
I hope this tutorial will create a good foundation for you. If you want tutorials on another GIS topic or you have any queries, please send an email at contact@spatial-dev.guru.