Работа с TIFF (импорт, экспорт) в Python с использованием numpy

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

Я пытался найти что-то, но нет никакой документации по методам PIL относительно TIFF. Я пытался выяснить это, но только получил плохой режим / тип файла не поддерживается ошибки.

Что мне нужно использовать здесь?

12 ответов

Решение

Сначала я скачал тестовое изображение TIFF с этой страницы под названием a_image.tif, Затем я открыл с PIL, как это:

>>> from PIL import Image
>>> im = Image.open('a_image.tif')
>>> im.show()

Это показало изображение радуги. Чтобы преобразовать в простой массив, это так же просто, как:

>>> import numpy
>>> imarray = numpy.array(im)

Мы видим, что размер изображения и форма массива совпадают:

>>> imarray.shape
(44, 330)
>>> im.size
(330, 44)

И массив содержит uint8 ценности:

>>> imarray
array([[  0,   1,   2, ..., 244, 245, 246],
       [  0,   1,   2, ..., 244, 245, 246],
       [  0,   1,   2, ..., 244, 245, 246],
       ..., 
       [  0,   1,   2, ..., 244, 245, 246],
       [  0,   1,   2, ..., 244, 245, 246],
       [  0,   1,   2, ..., 244, 245, 246]], dtype=uint8)

Как только вы закончите модифицировать массив, вы можете превратить его обратно в изображение PIL следующим образом:

>>> Image.fromarray(imarray)
<Image.Image image mode=L size=330x44 at 0x2786518>

Я использую matplotlib для чтения файлов TIFF:

import matplotlib.pyplot as plt
I = plt.imread(tiff_file)

а также I будет иметь тип ndarray,

Согласно документации, хотя на самом деле это PIL, который работает за кулисами при обработке TIFF, поскольку matplotlib только читает PNG изначально, но для меня это работало нормально.

Там также есть plt.imsave функция для сохранения.

Pylibtiff работал лучше для меня, чем PIL, который не поддерживает цветные изображения с более чем 8 битами на цвет.

from libtiff import TIFF

tif = TIFF.open('filename.tif') # open tiff file in read mode
# read an image in the currect TIFF directory as a numpy array
image = tif.read_image()

# read all images in a TIFF file:
for image in tif.iter_images(): 
    pass

tif = TIFF.open('filename.tif', mode='w')
tif.write_image(image)

Вы можете установить Pylibtiff с

pip3 install numpy libtiff

В файле readme для pylibtiff также упоминается tifffile.py, но я не пробовал.

Вы также можете использовать GDAL для этого. Я понимаю, что это геопространственный инструментарий, но ничто не требует от вас картографического продукта.

Ссылка на предварительно скомпилированные бинарные файлы GDAL для Windows (если окна здесь) http://www.gisinternals.com/sdk/

Чтобы получить доступ к массиву:

from osgeo import gdal

dataset = gdal.Open("path/to/dataset.tiff", gdal.GA_ReadOnly)
for x in range(1, dataset.RasterCount + 1):
    band = dataset.GetRasterBand(x)
    array = band.ReadAsArray()

В случае стеков изображений мне легче пользоваться scikit-image читать и matplotlib показать или сохранить. Я обработал 16-битные стеки изображений TIFF с помощью следующего кода.

from skimage import io
import matplotlib.pyplot as plt

# read the image stack
img = io.imread('a_image.tif')
# show the image
plt.imshow(mol,cmap='gray')
plt.axis('off')
# save the image
plt.savefig('output.tif', transparent=True, dpi=300, bbox_inches="tight", pad_inches=0.0)

Есть хороший пакет под названием tifffile что упрощает работу с файлами .tif или .tiff.

Установить пакет с помощью pip

      pip install tifffile

Теперь, чтобы прочитать файл .tif / .tiff в формате массива numpy:

      from tifffile import tifffile
image = tifffile.imread('path/to/your/image')
# type(image) = numpy.ndarray

Если вы хотите сохранить массив numpy как файл .tif / .tiff:

      tifffile.imwrite('my_image.tif', my_numpy_data, photometric='rgb')

или же

      tifffile.imsave('my_image.tif', my_numpy_data)

Вы можете узнать больше об этом пакете здесь .

Вы также можете использовать pytiff, автором которого я являюсь.

    import pytiff

    with pytiff.Tiff("filename.tif") as handle:
        part = handle[100:200, 200:400]

    # multipage tif
    with pytiff.Tiff("multipage.tif") as handle:
        for page in handle:
            part = page[100:200, 200:400]

Это довольно маленький модуль, и он может иметь не так много функций, как другие модули, но он поддерживает мозаичные tiff и bigtiff, поэтому вы можете читать части больших изображений.

Использование cv2

      import cv2
image = cv2.imread(tiff_file.tif)
cv2.imshow('tif image',image)

если вы хотите сохранить кодировку tiff с помощью geoTiff. Вы можете использовать rasterioупаковка

простой код:

      import rasterio

out = np.random.randint(low=10, high=20, size=(360, 720)).astype('float64')
new_dataset = rasterio.open('test.tiff', 'w', driver='GTiff',
                            height=out.shape[0], width=out.shape[1],
                            count=1, dtype=str(out.dtype),
                            )
new_dataset.write(out, 1)
new_dataset.close()

для более подробной информации о numpy 2 GEOTiff. вы можете нажать на это: https://gis.stackexchange.com/questions/279953/numpy-array-to-gtiff-using-rasterio-without-source-raster

Другой метод чтения tiff-файлов — использование tensorflow api.

      import tensorflow_io as tfio
image = tf.io.read_file(image_path)
tf_image = tfio.experimental.image.decode_tiff(image)
print(tf_image.shape)

Выход:

      (512, 512, 4)

документацию по тензорному потоку можно найти здесь

Чтобы этот модуль работал, должен быть установлен пакет python под названием tensorflow-io.

Хотя я не мог найти способ посмотреть на выходной тензор (после преобразования в nd.array), так как выходное изображение имело 4 канала. Я пытался преобразовать с помощью cv2.cvtcolor()с флагом cv2.COLOR_BGRA2BGRпосле просмотра этого сообщения , но все еще не смог просмотреть изображение.

Я рекомендую использовать привязки Python к OpenImageIO, это стандарт для работы с различными форматами изображений в мире vfx. Я нашел его более надежным при чтении различных типов сжатия по сравнению с PIL.

import OpenImageIO as oiio
input = oiio.ImageInput.open ("/path/to/image.tif")

никакие ответы на этот вопрос не работали для меня. поэтому я нашел другой способ просмотра файлов tif/tiff:

      import rasterio
from matplotlib import pyplot as plt
src = rasterio.open("ch4.tif")
plt.imshow(src.read(1), cmap='gray')

приведенный выше код поможет вам просмотреть файлы tif. также проверьте ниже, чтобы убедиться:

      type(src.read(1)) #see that src.read(1) is a numpy array

      src.read(1) #prints the matrix
Другие вопросы по тегам