I wish to load a .tif image into a numpy array, apply a formula and then spit the image back out with the same geo/nodata metadata information.
So far I have created this, which does the processing but loses all metadata in the process and also applies the formula to nodata values:
from PIL import Image import numpy as np img = Image.open('ndvi.tif') #import image array ndviArray = np.array(img) #convert to numpy array def ndvi2bio(x): #function to convert from ndvi to BIO return 400*(x)+680 vfunc = np.vectorize(ndvi2bio) #creating function function array...? bioArray = vfunc(ndviArray) #applying the bio array to the formula array to give results. #turn back into image... bioImg = Image.fromarray(bioArray) bioImg.save('BIOout.tif')
I've been reading into rasterio, I think I can replace the PIL image module with rasterio which will be more appropriate in this situation and allow me to keep my metadata from the tif.
Can anyone please help me achieve this? So far I am struggling to find a tutorial which does this, it seems most others use several other modules. Can it be done with just rasterio and numpy? (img(+meta) -> numpy array -> img(+meta from original data))
It's fairly easy. You open and read the input raster as a numpy array, run your calculation, open the output raster in 'w' write mode and use the georeferencing and other metadata (aka the profile) from the input raster.
import rasterio as rio import numpy as np def ndvi2bio(x): #function to convert from ndvi to BIO return 400*(x)+680 with rio.open('ndvi.tif') as src: # open raster dataset ndvi = src.read() # read as numpy array profile = src.profile bio = ndvi2bio(ndvi) #applying the bio array to the formula array to give results. with rio.open('BIOout.tif', 'w', **profile) as dst: # open raster dataset in 'w' write mode using the dst.write(bio) # georeferencing and other metadata from ndvi.tif
rasterio examples are in the quickstart section of the docs.