Извлечение RGB из 4-полосного изображения (растерио)

Я новичок в Python и до сих пор знакомлюсь с его библиотеками, извиняюсь, если это вопрос новичка. Я просто хочу отобразить изображение из 4 полос (R,G,B,NIR). Я хочу удалить NIR и оставить другой 3. Как я могу это сделать? Поскольку растерио возвращает объект, а не изображение, я не могу использовать функцию разделения.

from rasterio.plot import show
from matplotlib import pyplot
dataset = rasterio.open('sample.tif')
show(dataset)

Это, конечно, показывает неверный результат (изображение белого и желтого цвета).

Редактировать, я попробовал следующее:

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()

но это все еще показывает изображение в желтом и белом.

2 ответа

Чтобы отобразить только полосы RGB (не альфа) или какую-либо конкретную полосу, вам нужно использовать метод read вместе с методом show.

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))

Заказ группы

Порядок полос имеет значение, и их можно заказать по-разному в зависимости от TIFF. В документации к данным должен быть указан порядок полос, и, надеюсь, его можно будет прочитать из самих данных (мой опыт показывает, что это часто не так).

Вы можете сначала попробовать проверить метки групп (хотя вы все равно хотите обратиться к документации).

>>>src.descriptions
(None, None, None, None)

Если там ничего не помечено, обратитесь к документации по данным.

Допустим, есть 4 диапазона, заказанные как BGRN (как в NIR- ближний инфракрасный); тогда вам понадобятся первые три полосы, но в обратном порядке.

data = src.read([3,2,1])

Нормализация и типы данных

Если ваши полосы не в порядке RGB, вполне вероятно, что это 16-битный целочисленный тип данных, и вам понадобится 8-битный для рисования через imshow(или запись в другую кодировку изображения, например PNG и JPEG). Сначала нормализуйте данные до 0-255, затем выполните приведение изuint16 к uint8. Обратите внимание, что, делая это, вы теряете точность, поэтому вы хотите провести анализ исходных данных.

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")

Библиотеки изображений и размеры данных

Если вы используете библиотеку, отличную от rasterio, например cv2 или PIL, порядок, в котором полосы считываются из изображений RGB(A), может отличаться, как и порядок размеров. Если вам нужно изменить порядок размеров для вашего метода построения графика, вы можете сделать следующее

# Make the first (band) dimension the last
plt.imshow(numpy.moveaxis(data, 0, -1))

Обычно набор данных представляет собой массив, в котором каждый элемент является полосой, которую вы ищете. Учитывая ваш код, набор данных [0] - это R-полоса, набор данных [1] - G-полоса и так далее.

Так,

show(dataset[0])

покажет R группу.

Другие вопросы по тегам