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?
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>
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.
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()
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é.
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.
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)
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")