Praca z plikami TIFF (import, eksport) w Pythonie przy użyciu numpy


88

Potrzebuję metody Pythona do otwierania i importowania obrazów TIFF do tablic numpy, aby móc analizować i modyfikować dane pikseli, a następnie ponownie zapisywać je jako TIFF. (Są to w zasadzie mapy natężenia światła w skali szarości, przedstawiające odpowiednie wartości na piksel)

Nie mogłem znaleźć żadnej dokumentacji na temat metod PIL dotyczących TIFF. Próbowałem to rozgryźć, ale otrzymałem tylko błędy „zły tryb” lub „nieobsługiwany typ pliku”.

Czego potrzebuję tutaj?

Odpowiedzi:


107

Najpierw pobrałem testowy obraz TIFF z tej strony o nazwie a_image.tif. Następnie otworzyłem z PIL w ten sposób:

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

To pokazało obraz tęczy. Aby przekonwertować na tablicę numpy, jest to tak proste, jak:

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

Widzimy, że rozmiar obrazu i kształt tablicy pasują do siebie:

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

A tablica zawiera uint8wartości:

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

Gdy skończysz modyfikować tablicę, możesz zmienić ją z powrotem w obraz PIL w następujący sposób:

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

4
mam problemy z typami danych. dla niektórych działa dobrze, na przykład jeśli mam numery numpy.int16 w mojej tablicy, ale dla numpy.uint16 image.fromarray daje: "TypeError: Nie można obsłużyć tego typu danych"
Jakob

4
Patrząc na źródło fromarray, nie wygląda na to, że obsługuje on 16-bitowe tablice bez znaku.
jterrace

@Jakob od czerwca 2020 r.PIL nie obsługuje kolorowych obrazów z więcej niż 8 bitami na kolor , będziesz musiał użyć innej biblioteki (lub samodzielnie udostępnić tę funkcjonalność).
Boris

Oto, co otrzymałem, gdy próbowałem otworzyć obraz zbyt duży dla PIL:DecompressionBombError: Image size (900815608 pixels) exceeds limit of 178956970 pixels, could be decompression bomb DOS attack.
devforfu

57

Używam matplotlib do czytania plików TIFF:

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

i Ibędzie typowyndarray .

Zgodnie z dokumentacją, w rzeczywistości to PIL działa za kulisami podczas obsługi plików TIFF, ponieważ matplotlib czyta natywnie tylko pliki PNG, ale dla mnie działa dobrze.

Jest też plt.imsavefunkcja zapisywania.


To zdecydowanie najłatwiejszy sposób pracy z plikami TIFF! Próbowałem na kilkanaście sposobów i to wszystko było biletem. Głosuj za na pewno!
zachd1_618

a co z częścią widokową?
Monica Heddneck

6
Wygląda na to, że matplotlib zmienił strategię:ValueError: Only know how to handle extensions: ['png']; with Pillow installed matplotlib can handle more images
strpeter

18

Możesz również użyć do tego GDAL. Zdaję sobie sprawę, że jest to zestaw narzędzi geoprzestrzennych, ale nic nie wymaga posiadania produktu kartograficznego.

Link do prekompilowanych plików binarnych GDAL dla Windows (zakładając okna tutaj) http://www.gisinternals.com/sdk/

Aby uzyskać dostęp do tablicy:

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

czy powyższy kod dotyczy pojedynczego czy wielostronicowego pliku TIF? Chciałbym użyć gdal do załadowania 16-bitowych stosów tiff do nparrayów.
user391339

Powinno to wczytać typ danych wejściowych lub przenieść wszystko do float64 numpy. Możesz dodać .astype(sometype)połączenie na końcu ReadAsArray()połączenia, aby je przesłać. Nie jestem pewien, czy to tworzy kopię (po prostu nie testowałem).
Jzl5325

@Chikinn From Review: stackoverflow.com/review/suggested-edits/17962780 xrange to żadna literówka, xrangeto wersja Pythona 2 range. Zaakceptowałem tę edycję, ponieważ Python 3 jest nadal aktywnie ulepszany, podczas gdy Python 2 nie.
abccd

14

PyLibTiff działał lepiej dla mnie niż PIL, który od grudnia 2020 roku nadal nie obsługuje kolorowych obrazów z więcej niż 8 bitami na kolor .

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)

Możesz zainstalować PyLibTiff z

pip3 install numpy libtiff

Plik Readme PyLibTiff również wspomina o tifffilebibliotece, ale nie próbowałem jej.


3
To jest bardzo dobre. Obecnie plik tifffile jest zawarty w SciKit skimage.external.tifffile, ale można go również zaimportować jako moduł, jeśli pobierzesz tifffile.py od pana Christopha Gohlke
lesolorzanov

8

W przypadku stosów obrazów łatwiej jest mi scikit-imageje czytać, matplotlibwyświetlać lub zapisywać. Obsługiwałem 16-bitowe stosy obrazów TIFF za pomocą następującego kodu.

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

Możesz też użyć pytiff, którego jestem autorem.

    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]

Jest to dość mały moduł i może nie mieć tylu funkcji, co inne moduły, ale obsługuje kafelki tiffs i bigtiff, dzięki czemu można czytać części dużych obrazów.


1
Ta funkcja jest dokładnie tym, czego potrzebuję! (Możliwość odczytania małego fragmentu dużego pliku). Jednak kiedy próbuję zainstalować pip, pojawia się błąd gcc
Fractaly

Jeśli utworzysz problem z komunikatem o błędzie, zobaczę, czy uda mi się go rozwiązać.
hnfl

Tak, też jestem zainteresowany, ale przy próbie instalacji również wystąpił błąd. Zrobiłem to za pomocą pip - pod Windows i pod Ubuntu. Szkoda, że ​​to nie działa! Utworzyłem numer tutaj: github.com/FZJ-INM1-BDA/pytiff/issues/15
Dobedani

nie można zainstalować
Sadaf Shafi

0

Polecam używanie powiązań Pythona z OpenImageIO, to standard radzenia sobie z różnymi formatami obrazu w świecie vfx. Odkryłem, że jest bardziej niezawodny w czytaniu różnych typów kompresji w porównaniu do PIL.

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

Nie można zainstalować w systemie Windows, chyba że masz już kompilatory.
Jimmy Carter,

0

Korzystanie z cv2

import cv2
image = cv2.imread(tiff_file.tif)
cv2.imshow('tif image',image)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.