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

88

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

Я не смог найти никакой документации по методам PIL, относящимся к TIFF. Я попытался разобраться, но получил только ошибки «плохой режим» или «тип файла не поддерживается».

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

Якоб
источник

Ответы:

107

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

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

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

>>> 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>
терраса
источник
4
у меня проблемы с типами данных. работает нормально для некоторых, например, если у меня есть числа numpy.int16 в моем массиве, но для numpy.uint16 image.fromarray дает: «TypeError: Невозможно обработать этот тип данных»
Якоб
4
Глядя на источник fromarray, не похоже, что он обрабатывает беззнаковые 16-битные массивы.
jterrace
@Jakob по состоянию на июнь 2020 года PIL не поддерживает цветные изображения с более чем 8 битами на цвет , вам придется использовать другую библиотеку (или внести функциональность самостоятельно).
Boris
Вот что у меня получилось, когда я попытался открыть изображение, слишком большое для PIL:DecompressionBombError: Image size (900815608 pixels) exceeds limit of 178956970 pixels, could be decompression bomb DOS attack.
devforfu
57

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

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

и Iбудет типаndarray .

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

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

Майкл Бреннан
источник
Это, безусловно, самый простой способ работы с TIFF! Пробовал дюжину способов и все это было билетом. Проголосуйте точно!
zachd1_618
как насчет просмотра?
Моника Хедднек
6
Похоже, что matplotlib изменил стратегию:ValueError: Only know how to handle extensions: ['png']; with Pillow installed matplotlib can handle more images
strpeter
18

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

Ссылка на предварительно скомпилированные двоичные файлы GDAL для Windows (при условии, что здесь 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()
Jzl5325
источник
приведенный выше код для одиночного или многостраничного TIF? Я хотел бы использовать gdal для загрузки 16-битных стеков tiff в nparrays.
user391339
Это должно читать либо тип входных данных, либо перемещать все в numpy float64. Вы можете добавить .astype(sometype)вызов в конец ReadAsArray()вызова для трансляции. Не уверен, что это делает копию (только не проверял).
Jzl5325 02
@Chikinn Из обзора: stackoverflow.com/review/suggested-edits/17962780 xrange - это не опечатка, xrangeэто версия для Python 2 range. Я принял это изменение, потому что python 3 все еще активно улучшается, а python 2 - нет.
abccd
14

PyLibTiff работал у меня лучше, чем PIL, который по состоянию на декабрь 2020 года все еще не поддерживает цветные изображения с более чем 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библиотека, но я не пробовал.

Борис
источник
3
Это очень хорошо. К настоящему моменту tifffile включен в scimage.external.tifffile SciKit, но его также можно импортировать как модуль, если вы загрузите tifffile.py от г-на Кристофа Гольке
lesolorzanov
8

В случае стеков изображений мне легче 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)
Клэр
источник
7

Вы также можете использовать 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, поэтому вы можете читать части больших изображений.

hnfl
источник
1
Эта функция как раз то, что мне нужно! (Возможность прочитать небольшой фрагмент большого файла). Однако, когда я пытаюсь установить его по
пипу,
Если вы создадите проблему с сообщением об ошибке, я посмотрю, смогу ли я выяснить проблему.
hnfl 03
Да, мне тоже интересно, но при попытке установить тоже возникла ошибка. Я сделал это с помощью pip - под Windows и под Ubuntu. Жалко, что не работает! Я создал здесь проблему: github.com/FZJ-INM1-BDA/pytiff/issues/15
Dobedani
невозможно установить
Садаф Шафи
0

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

import OpenImageIO as oiio
input = oiio.ImageInput.open ("/path/to/image.tif")
зено
источник
Borderline невозможно установить в Windows, если у вас еще нет компиляторов.
Джимми Картер
0

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

import cv2
image = cv2.imread(tiff_file.tif)
cv2.imshow('tif image',image)
жид
источник