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)


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 TIFF.

How can I 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))

  • You don't need to vectorise your ndvi2bio function. Numpy will run the calculation over the entire array already. You are just slowing your calculation down by a massive amount (in a quick timeit test on a 100x100 array, calling the function 1000 times took 0.008 sec, while the vectorised function took 2 sec)...
    – user2856
    Oct 9 '19 at 23:43

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

More introductory rasterio examples are in the quickstart section of the docs.

  • Thank you very much for that, I was confusing myself with the more complicated tutorials I was trying to follow elsewhere, I'll remember to go to the docs next time instead of google. Oct 9 '19 at 23:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.