Reputation: 307
I am a beginner at python and I am still getting familiar with its libraries, apologies if this is a novice question. I simply want to display an image of 4 bands (R,G,B,NIR). I want to remove NIR and keep the other 3. How can I do this? Since rasterio returns an object and not an image, I am unable to use the split function.
from rasterio.plot import show
from matplotlib import pyplot
dataset = rasterio.open('sample.tif')
show(dataset)
This of course shows an incorrect result (white and yellow colored image).
Edit, I tried the following:
img_combined = cv2.merge((dataset.read(1),dataset.read(2),dataset.read(3)))
%matplotlib qt
plt.imshow(img_combined)
plt.xticks([]), plt.yticks([])
plt.show()
but it still shows the image in yellow and white.
Upvotes: 2
Views: 8105
Reputation: 18968
Band order
The order of the bands matters, and they can be ordered differently depending on the TIFF. The data's documentation should outline what the band order is, and hopefully it can be read from the data itself (my experience is that is often not the case).
You could first try checking the band labels (though, you still want to refer to the docs).
>>>src.descriptions
(None, None, None, None)
If nothing is labeled there, you should refer to the data documentation.
Let's say there are 4 bands ordered as BGRN (as in NIR--near infrared); you would then want the first three bands but in reverse order.
data = src.read([3,2,1])
Normalizing and data types
If your bands are not in RGB order, it is likely that it is of 16bit integer datatype, and you would want 8bit for drawing via imshow
(or writing to another image encoding, e.g. PNG and JPEG). First normalize the data to 0-255, then cast from uint16
to uint8
. Note that by doing this you lose precision, so you want to do your analysis on the original data.
import numpy
def normalize(x, lower, upper):
"""Normalize an array to a given bound interval"""
x_max = numpy.max(x)
x_min = numpy.min(x)
m = (upper - lower) / (x_max - x_min)
x_norm = (m * (x - x_min)) + lower
return x_norm
# Normalize each band separately
data_norm = numpy.array([normalize(data[i,:,:], 0, 255) for i in range(data.shape[0])])
data_rgb = data_norm.astype("uint8")
Image libraries and data dimensions
If you use a library other than rasterio
, e.g. cv2
or PIL
, the order that the bands are read in from RGB(A) images can differ, as well as the order of the dimensions. If you need to change the order of the dimensions for your plotting method, you can do the following
# Make the first (band) dimension the last
plt.imshow(numpy.moveaxis(data, 0, -1))
Upvotes: 2
Reputation: 35
In order to display only the RGB bands (not alpha) or any particular band you need to use the read method along with the show method.
import rasterio
from rasterio.plot import show
#to display RGB
dataset = rasterio.open('sample.tif')
show(dataset.read([1,2,3]))
#to display just the red band:
show(dataset.read(1))
Upvotes: 3
Reputation: 322
Normally the dataset is an array, in which each element is the band you are looking for. Given your code, dataset[0] is the R band, dataset[1] the G band, and so on.
So,
show(dataset[0])
will show the R band.
Upvotes: 0