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

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

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

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


person Jakob    schedule 27.09.2011    source источник


Ответы (9)


Сначала я загрузил тестовое изображение 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>
person jterrace    schedule 27.09.2011
comment
у меня проблемы с типами данных. у некоторых работает нормально, например. если в моем массиве есть числа numpy.int16, но для numpy.uint16 image.fromarray дает: TypeError: не удается обработать этот тип данных - person Jakob; 28.09.2011
comment
Глядя на источник fromarray, не похоже, что он обрабатывает беззнаковые 16-битные массивы. - person jterrace; 28.09.2011
comment
@Jakob по состоянию на июнь 2020 г. PIL не поддерживает цветные изображения с более чем 8 битами на цвет., вам придется использовать другую библиотеку (или внести функциональность самостоятельно). - person Boris; 03.06.2020
comment
Вот что у меня получилось, когда я попытался открыть изображение, слишком большое для PIL: DecompressionBombError: Image size (900815608 pixels) exceeds limit of 178956970 pixels, could be decompression bomb DOS attack. - person devforfu; 18.11.2020
comment
мне imarray.shape дает (x, y, 3) ?? что мне не хватает ?? - person pippo1980; 20.01.2021
comment
@ pippo1980 У вас наверняка цветное изображение, отсюда и три канала RGB. - person nebroth; 03.06.2021
comment
да, конечно, думал о image.shape openCV и image.size подушки, не понимая, что это было о numpy.array (im) .shape. Спасибо @nebroth - person pippo1980; 03.06.2021

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

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

и I будет иметь тип ndarray.

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

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

person Michael Brennan    schedule 27.09.2011
comment
Это, безусловно, самый простой способ работы с TIFF! Пробовал дюжину способов и все это было билетом. Проголосуйте точно! - person zachd1_618; 29.10.2012
comment
как насчет просмотра? - person Monica Heddneck; 26.01.2018
comment
Похоже, что matplotlib изменил стратегию: ValueError: Only know how to handle extensions: ['png']; with Pillow installed matplotlib can handle more images - person strpeter; 08.02.2019

Вы также можете использовать для этого 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()
person Jzl5325    schedule 27.09.2011

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

from libtiff import TIFF

tif = TIFF.open('filename.tif') # open tiff file in read mode
# read an image in the current 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, но я ее не пробовал.

person Boris    schedule 05.07.2017
comment
Это очень хорошо. К настоящему времени tifffile включен в SciKit skimage.external.tifffile, но его также можно импортировать как модуль, если вы загрузите tifffile.py от г-на Кристофа Голке. - person lesolorzanov; 15.01.2018

В случае стеков изображений мне легче использовать 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)
person Claire    schedule 01.07.2018

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

person hnfl    schedule 17.11.2017
comment
Эта функция как раз то, что мне нужно! (Возможность прочитать небольшой фрагмент большого файла). Однако, когда я пытаюсь установить его, я получаю ошибку gcc - person Fractaly; 01.06.2019
comment
Если вы создадите проблему с сообщением об ошибке, я посмотрю, может разобраться в проблеме. - person hnfl; 03.06.2019
comment
Да, мне тоже интересно, но при попытке установить тоже возникла ошибка. Я сделал это с помощью pip - под Windows и под Ubuntu. Жалко, что не работает! Я создал здесь проблему: github.com/FZJ-INM1-BDA/pytiff / issues / 15 - person Dobedani; 03.09.2019
comment
невозможно установить - person Sadaf Shafi; 15.12.2020

Есть хороший пакет 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')

or

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

Подробнее об этом пакете можно узнать здесь.

person jd95    schedule 12.03.2021
comment
Только это решение сработало у меня, спасибо! - person Bernardo Costa; 04.06.2021

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

import OpenImageIO as oiio
input = oiio.ImageInput.open ("/path/to/image.tif")
person zeno    schedule 17.12.2018
comment
Borderline невозможно установить в Windows, если у вас еще нет компиляторов. - person Jimmy Carter; 17.07.2020

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

import cv2
image = cv2.imread(tiff_file.tif)
cv2.imshow('tif image',image)
person Kukesh    schedule 12.12.2020