web-dev-qa-db-fra.com

Travailler avec des TIFF (importation, exportation) en Python avec numpy

J'ai besoin d'une routine python capable d'ouvrir et d'importer des images TIFF dans des tableaux numpy afin de pouvoir analyser et modifier les données contenues, puis de les enregistrer à nouveau au format TIFF. (Ce sont essentiellement des cartes d'intensité lumineuse en niveaux de gris, représentant les valeurs respectives par pixel)

J'ai essayé de trouver quelque chose, mais il n'y a pas de documentation sur les méthodes de LIP concernant le format TIFF. J'ai essayé de le comprendre, mais je n'ai eu que des erreurs de type/fichier non pris en charge.

Que dois-je utiliser ici?

53
Jakob

Premièrement, j'ai téléchargé une image test TIFF depuis cette page appelée a_image.tif. Puis j'ai ouvert avec PIL comme ceci:

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

Cela a montré l'image d'arc-en-ciel. Pour convertir en un tableau numpy, il suffit de:

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

Nous pouvons voir que la taille de l'image et la forme du tableau correspondent:

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

Et le tableau contient uint8 valeurs:

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

Une fois que vous avez fini de modifier le tableau, vous pouvez le reconvertir en une image PIL comme ceci:

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

J'utilise matplotlib pour lire les fichiers TIFF:

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

et I sera de type ndarray.

Selon la documentation, c’est en réalité la PIL qui travaille en coulisse lorsqu’il traite des TIFF, car matplotlib ne lit que les fichiers PNG en mode natif, mais cela fonctionne très bien pour moi.

Il existe également une fonction plt.imsave pour la sauvegarde.

40
Michael Brennan

Vous pouvez également utiliser GDAL pour cela. Je me rends compte que c'est une boîte à outils géospatiale, mais rien ne vous oblige à avoir un produit cartographique.

Lien vers les fichiers binaires GDAL précompilés pour Windows (en supposant que Windows est ici) http://www.gisinternals.com/sdk/

Pour accéder au tableau:

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

pylibtiff a mieux fonctionné pour moi que PIL, qui ne prend pas en charge les images couleur de plus de 8 bits par couleur .

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)

Vous pouvez installer pylibtiff avec 

pip3 install numpy libtiff

Le readme de pylibtiff mentionne également tifffile.py , mais je ne l’ai pas essayé.

4
Boris

Vous pouvez également utiliser pytiff dont je suis l'auteur. 

    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]

C'est un module assez petit et peut ne pas avoir autant de fonctionnalités que d'autres modules, mais il supporte les tiffs en mosaïque et le bigtiff, vous permettant ainsi de lire des parties de grandes images. 

2
hnfl

Dans le cas de piles d'images, je trouve plus facile d'utiliser scikit-image pour lire et matplotlib pour afficher ou enregistrer. J'ai traité des piles d'images TIFF 16 bits avec le code suivant.

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

Je recommande d’utiliser les liaisons python à OpenImageIO, c’est le standard pour traiter avec divers formats d’image dans le monde vfx. Je l’ai trouvé plus fiable en lisant différents types de compression que le PIL.

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