Робота з TIFF (імпорт, експорт) у Python за допомогою numpy


84

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

Я не зміг знайти жодної документації щодо методів PIL щодо TIFF. Я спробував це зрозуміти, але отримав лише помилки "поганий режим" або "тип файлу не підтримується".

Що мені тут потрібно використовувати?

Відповіді:


103

Спочатку я завантажив тестове зображення 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 бітами на колір , тобі доведеться використовувати іншу бібліотеку (або внести функціонал самостійно).
Борис

56

Я використовую matplotlib для читання файлів TIFF:

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

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

Згідно з документацією, хоча насправді саме PIL працює за лаштунками при обробці TIFF, оскільки matplotlib лише зчитує PNG, але це добре працює для мене.

Також є plt.imsaveфункція збереження.


Це найпростіший спосіб роботи з TIFF! Перепробував десяток способів і все це був квиток. Голосуйте точно!
zachd1_618

як щодо частини перегляду?
Моніка Хеднек

5
Здається, matplotlib змінив стратегію:ValueError: Only know how to handle extensions: ['png']; with Pillow installed matplotlib can handle more images
strpeter

17

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

Посилання на попередньо скомпільовані двійкові файли GDAL для вікон (якщо вікна передбачаються тут) 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()

це наведений вище код для одного TIF або багатосторінкового TIF? Я хотів би використовувати gdal для завантаження 16-бітових стеків tiff в nparrays.
user391339

Це повинно читати або тип вхідних даних, або переміщувати все до numpy's float64. Ви можете додати .astype(sometype)дзвінок до кінця ReadAsArray()дзвінка для трансляції. Не впевнений, що це робить копію (просто не тестували).
Jzl5325,

@Chikinn З огляду: stackoverflow.com/review/suggested-edits/17962780 xrange не помилка, xrangeце версія пітона 2 range. Я прийняв це редагування, оскільки python 3 все ще активно вдосконалюється, тоді як python 2 - ні.
abccd

12

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, але я його не пробував, і хоча він нібито з відкритим кодом, я не думаю, що код більше ніде доступний (крім того, щоб витягти його вручну з пакета PyPI).


2
Це дуже добре. На даний момент tifffile включено до SciKit skimage.external.tifffile, але його також можна імпортувати як модуль, якщо ви завантажите tifffile.py від пана Крістофа Гольке
lesolorzanov

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]

Це досить маленький модуль, і він може мати не так багато функцій, як інші модулі, але він підтримує черепичні тіфи та бігтіф, тому ви можете читати частини великих зображень.


Ця функція - саме те, що мені потрібно! (Можливість прочитати невеликий шматок великого файлу). Однак, коли я намагаюся встановити його, я отримую помилку gcc
Fractaly

Якщо ви створили проблему із повідомленням про помилку, я подивлюсь, чи зможу я зрозуміти проблему.
hnfl

Так, я також зацікавлений, але також отримав помилку, коли намагався його встановити. Я зробив це за допомогою pip - під Windows та під Ubuntu. Шкода, що це не працює! Я створив тут випуск: github.com/FZJ-INM1-BDA/pytiff/issues/15
Добедані,

6

У випадку стеків зображень мені зручніше користуватися як 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)

0

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

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

Прикордонний неможливо встановити в Windows, якщо у вас вже немає компіляторів.
Джиммі Картер,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.