Tifffile est une bibliothèque Python pour
L'image et les métadonnées peuvent être lues à partir de TIFF, BigTIFF, OME-TIFF, GeoTIFF, Adobe DNG, ZIF (Zoomable Image File Format), MetaMorph STK, Zeiss LSM, ImageJ hyperstack, Micro-Manager MMStack et NDTiff, SGI, NIHImage, Olympus FluoView. et SIS, ScanImage, Molecular Dynamics GEL, Aperio SVS, Leica SCN, Roche BIF, PerkinElmer Fichiers au format QPTIFF (QPI, PKI), Hamamatsu NDPI, Argos AVS et Philips DP.
Les données d'image peuvent être lues sous forme de tableaux NumPy ou de tableaux/groupes Zarr à partir de bandes, de tuiles, de pages (IFD), de SubIFD, de séries d'ordre supérieur et de niveaux pyramidaux.
Les données d'image peuvent être écrites dans des fichiers compatibles TIFF, BigTIFF, OME-TIFF et ImageJ hyperstack sous forme multipage, volumétrique, pyramidale, mappable en mémoire, en mosaïque, prédite ou compressée.
De nombreux schémas de compression et de prédicteurs sont pris en charge via la bibliothèque d'imagecodecs, notamment LZW, PackBits, Deflate, PIXTIFF, LZMA, LERC, Zstd, JPEG (8 et 12 bits, sans perte), JPEG 2000, JPEG XR, JPEG XL, WebP, PNG. , EER, Jetraw, virgule flottante 24 bits et différenciation horizontale.
Tifffile peut également être utilisé pour inspecter les structures TIFF, lire des données d'image à partir de séquences de fichiers multidimensionnels, écrire fsspec ReferenceFileSystem pour les fichiers TIFF et les séquences de fichiers image, corriger les valeurs de balises TIFF et analyser de nombreux formats de métadonnées propriétaires.
Auteur: | Christoph Gohlke |
---|---|
Licence: | Clause BSD 3 |
Version: | 2024.9.20 |
DOÏ : | 10.5281/zenodo.6795860 |
Installez le package tifffile et toutes les dépendances à partir de l'index du package Python :
python -m pip install -U fichier tiff[tous]
Tifffile est également disponible dans d'autres référentiels de packages tels que Anaconda, Debian et MSYS2.
La bibliothèque tifffile est annotée et documentée via docstrings :
python -c "importer un fichier tiff ; aide (fichier tiff)"
Tifffile peut être utilisé comme script de console pour inspecter et prévisualiser les fichiers TIFF :
python -m fichier tiff --help
Voir Exemples d'utilisation de l'interface de programmation.
Le code source et le support sont disponibles sur GitHub.
Une assistance est également assurée sur le forum image.sc.
Cette révision a été testée avec les exigences et dépendances suivantes (d'autres versions peuvent fonctionner) :
2024.9.20
2024.8.30
2024.8.28
2024.8.24
2024.8.10
2024.7.24
2024.7.21
2024.7.2
2024.6.18
2024.5.22
2024.5.10
2024.5.3
2024.4.24
2024.4.18
2024.2.12
2024.1.30
2023.12.9
2023.9.26
2023.9.18
2023.8.30
2023.8.25
2023.8.12
2023.7.18
Reportez-vous au fichier CHANGES pour les anciennes révisions.
TIFF, Tagged Image File Format, a été créé par Aldus Corporation et Adobe Systems Incorporated.
Tifffile prend en charge un sous-ensemble de la spécification TIFF6, principalement des images entières de 8, 16, 32 et 64 bits, flottantes de 16, 32 et 64 bits, en niveaux de gris et à échantillons multiples. Plus précisément, la compression CCITT et OJPEG, le sous-échantillonnage de chrominance sans compression JPEG, les transformations de l'espace colorimétrique, les échantillons de types différents ou les métadonnées IPTC, ICC et XMP ne sont pas implémentés.
Outre le TIFF classique, tifffile prend en charge plusieurs formats de type TIFF qui ne respectent pas strictement la spécification TIFF6. Certains formats permettent que la taille des fichiers et des données dépasse la limite de 4 Go du TIFF classique :
Les autres bibliothèques permettant de lire, d'écrire, d'inspecter ou de manipuler des fichiers TIFF scientifiques à partir de Python sont aicsimageio, apeer-ometiff-library, bigtiff, fabio.TiffIO, GDAL, imread, large_image, openslide-python, opentile, pylibtiff, pylsm, pymimage, python. -bioformats, pytiff, scanimagetiffreader-python, SimpleITK, slideio, tiffslide, tifftools, tyf, xtiff et ndtiff.
Écrivez un tableau NumPy dans un fichier TIFF RVB d'une seule page :
>> > data = numpy . random . randint ( 0 , 255 , ( 256 , 256 , 3 ), 'uint8' )
>> > imwrite ( 'temp.tif' , data , photometric = 'rgb' )
Lisez l'image du fichier TIFF sous forme de tableau NumPy :
>> > image = imread ( 'temp.tif' )
>> > image . shape
( 256 , 256 , 3 )
Utilisez les arguments photométriques et planarconfig pour écrire un tableau NumPy 3x3x3 dans un RVB entrelacé, un RVB planaire ou un TIFF en niveaux de gris de 3 pages :
>> > data = numpy . random . randint ( 0 , 255 , ( 3 , 3 , 3 ), 'uint8' )
>> > imwrite ( 'temp.tif' , data , photometric = 'rgb' )
>> > imwrite ( 'temp.tif' , data , photometric = 'rgb' , planarconfig = 'separate' )
>> > imwrite ( 'temp.tif' , data , photometric = 'minisblack' )
Utilisez l'argument extrasamples pour spécifier comment les composants supplémentaires sont interprétés, par exemple pour une image RGBA avec un canal alpha non associé :
>> > data = numpy . random . randint ( 0 , 255 , ( 256 , 256 , 4 ), 'uint8' )
>> > imwrite ( 'temp.tif' , data , photometric = 'rgb' , extrasamples = [ 'unassalpha' ])
Écrivez un tableau NumPy en 3 dimensions dans un fichier TIFF multipage en niveaux de gris de 16 bits :
>> > data = numpy . random . randint ( 0 , 2 ** 12 , ( 64 , 301 , 219 ), 'uint16' )
>> > imwrite ( 'temp.tif' , data , photometric = 'minisblack' )
Lisez l'intégralité de la pile d'images à partir du fichier TIFF multipage sous forme de tableau NumPy :
>> > image_stack = imread ( 'temp.tif' )
>> > image_stack . shape
( 64 , 301 , 219 )
>> > image_stack . dtype
dtype ( 'uint16' )
Lisez l'image de la première page du fichier TIFF sous forme de tableau NumPy :
>> > image = imread ( 'temp.tif' , key = 0 )
>> > image . shape
( 301 , 219 )
Lisez des images à partir d’une plage de pages sélectionnée :
>> > images = imread ( 'temp.tif' , key = range ( 4 , 40 , 2 ))
>> > images . shape
( 18 , 301 , 219 )
Parcourez toutes les pages du fichier TIFF et lisez successivement les images :
>> > with TiffFile ( 'temp.tif' ) as tif :
... for page in tif . pages :
... image = page . asarray ()
...
Obtenez des informations sur la pile d'images dans le fichier TIFF sans lire aucune donnée d'image :
>> > tif = TiffFile ( 'temp.tif' )
>> > len ( tif . pages ) # number of pages in the file
64
>> > page = tif . pages [ 0 ] # get shape and dtype of image in first page
>> > page . shape
( 301 , 219 )
>> > page . dtype
dtype ( 'uint16' )
>> > page . axes
'YX'
>> > series = tif . series [ 0 ] # get shape and dtype of first image series
>> > series . shape
( 64 , 301 , 219 )
>> > series . dtype
dtype ( 'uint16' )
>> > series . axes
'QYX'
>> > tif . close ()
Inspectez la balise « XResolution » de la première page du fichier TIFF :
>> > with TiffFile ( 'temp.tif' ) as tif :
... tag = tif . pages [ 0 ]. tags [ 'XResolution' ]
...
>> > tag . value
( 1 , 1 )
>> > tag . name
'XResolution'
>> > tag . code
282
>> > tag . count
1
>> > tag . dtype
< DATATYPE . RATIONAL : 5 >
Parcourez toutes les balises du fichier TIFF :
>> > with TiffFile ( 'temp.tif' ) as tif :
... for page in tif . pages :
... for tag in page . tags :
... tag_name , tag_value = tag . name , tag . value
...
Remplacez la valeur d'une balise existante, par exemple XResolution :
>> > with TiffFile ( 'temp.tif' , mode = 'r+' ) as tif :
... _ = tif . pages [ 0 ]. tags [ 'XResolution' ]. overwrite (( 96000 , 1000 ))
...
Écrivez un tableau à virgule flottante à 5 dimensions en utilisant le format BigTIFF, des composants de couleur séparés, une mosaïque, un niveau de compression Zlib 8, un prédicteur de différenciation horizontale et des métadonnées supplémentaires :
>> > data = numpy . random . rand ( 2 , 5 , 3 , 301 , 219 ). astype ( 'float32' )
>> > imwrite (
... 'temp.tif' ,
... data ,
... bigtiff = True ,
... photometric = 'rgb' ,
... planarconfig = 'separate' ,
... tile = ( 32 , 32 ),
... compression = 'zlib' ,
... compressionargs = { 'level' : 8 },
... predictor = True ,
... metadata = { 'axes' : 'TZCYX' },
... )
Écrivez une série temporelle de volumes à 10 ips avec une taille de voxel xyz de 2,6755 x 2,6755 x 3,9474 microns ^ 3 dans un fichier TIFF au format hyperstack ImageJ :
>> > volume = numpy . random . randn ( 6 , 57 , 256 , 256 ). astype ( 'float32' )
>> > image_labels = [ f' { i } ' for i in range ( volume . shape [ 0 ] * volume . shape [ 1 ])]
>> > imwrite (
... 'temp.tif' ,
... volume ,
... imagej = True ,
... resolution = ( 1.0 / 2.6755 , 1.0 / 2.6755 ),
... metadata = {
... 'spacing' : 3.947368 ,
... 'unit' : 'um' ,
... 'finterval' : 1 / 10 ,
... 'fps' : 10.0 ,
... 'axes' : 'TZYX' ,
... 'Labels' : image_labels ,
... },
... )
Lisez le volume et les métadonnées du fichier hyperstack ImageJ :
>> > with TiffFile ( 'temp.tif' ) as tif :
... volume = tif . asarray ()
... axes = tif . series [ 0 ]. axes
... imagej_metadata = tif . imagej_metadata
...
>> > volume . shape
( 6 , 57 , 256 , 256 )
>> > axes
'TZYX'
>> > imagej_metadata [ 'slices' ]
57
>> > imagej_metadata [ 'frames' ]
6
Mapper en mémoire les données d'image contiguës dans le fichier hyperstack ImageJ :
>> > memmap_volume = memmap ( 'temp.tif' )
>> > memmap_volume . shape
( 6 , 57 , 256 , 256 )
>> > del memmap_volume
Créez un fichier TIFF contenant une image vide et écrivez dans le tableau NumPy mappé en mémoire (remarque : cela ne fonctionne pas avec la compression ou la mosaïque) :
>> > memmap_image = memmap (
... 'temp.tif' , shape = ( 256 , 256 , 3 ), dtype = 'float32' , photometric = 'rgb'
... )
>> > type ( memmap_image )
< class 'numpy.memmap' >
>> > memmap_image [ 255 , 255 , 1 ] = 1.0
>> > memmap_image . flush ()
>> > del memmap_image
Écrivez deux tableaux NumPy dans un fichier TIFF multi-séries (remarque : les autres lecteurs TIFF ne reconnaîtront pas les deux séries ; utilisez le format OME-TIFF pour une meilleure interopérabilité) :
>> > series0 = numpy . random . randint ( 0 , 255 , ( 32 , 32 , 3 ), 'uint8' )
>> > series1 = numpy . random . randint ( 0 , 255 , ( 4 , 256 , 256 ), 'uint16' )
>> > with TiffWriter ( 'temp.tif' ) as tif :
... tif . write ( series0 , photometric = 'rgb' )
... tif . write ( series1 , photometric = 'minisblack' )
...
Lisez la deuxième série d'images du fichier TIFF :
>> > series1 = imread ( 'temp.tif' , series = 1 )
>> > series1 . shape
( 4 , 256 , 256 )
Écrivez successivement les images d'une série contiguë dans un fichier TIFF :
>> > data = numpy . random . randint ( 0 , 255 , ( 30 , 301 , 219 ), 'uint8' )
>> > with TiffWriter ( 'temp.tif' ) as tif :
... for frame in data :
... tif . write ( frame , contiguous = True )
...
Ajoutez une série d'images au fichier TIFF existant (remarque : cela ne fonctionne pas avec l'hyperstack ImageJ ou les fichiers OME-TIFF) :
>> > data = numpy . random . randint ( 0 , 255 , ( 301 , 219 , 3 ), 'uint8' )
>> > imwrite ( 'temp.tif' , data , photometric = 'rgb' , append = True )
Créez un fichier TIFF à partir d'un générateur de tuiles :
>> > data = numpy . random . randint ( 0 , 2 ** 12 , ( 31 , 33 , 3 ), 'uint16' )
>> > def tiles ( data , tileshape ):
... for y in range ( 0 , data . shape [ 0 ], tileshape [ 0 ]):
... for x in range ( 0 , data . shape [ 1 ], tileshape [ 1 ]):
... yield data [ y : y + tileshape [ 0 ], x : x + tileshape [ 1 ]]
...
>> > imwrite (
... 'temp.tif' ,
... tiles ( data , ( 16 , 16 )),
... tile = ( 16 , 16 ),
... shape = data . shape ,
... dtype = data . dtype ,
... photometric = 'rgb' ,
... )
Écrivez un fichier OME-TIFF multidimensionnel, multi-résolution (pyramidal) et multi-séries avec des métadonnées facultatives. Les images en sous-résolution sont écrites sur les SubIFD. Limitez le codage parallèle à 2 threads. Écrivez une image miniature sous forme de série d'images distincte :
>> > data = numpy . random . randint ( 0 , 255 , ( 8 , 2 , 512 , 512 , 3 ), 'uint8' )
>> > subresolutions = 2
>> > pixelsize = 0.29 # micrometer
>> > with TiffWriter ( 'temp.ome.tif' , bigtiff = True ) as tif :
... metadata = {
... 'axes' : 'TCYXS' ,
... 'SignificantBits' : 8 ,
... 'TimeIncrement' : 0.1 ,
... 'TimeIncrementUnit' : 's' ,
... 'PhysicalSizeX' : pixelsize ,
... 'PhysicalSizeXUnit' : 'µm' ,
... 'PhysicalSizeY' : pixelsize ,
... 'PhysicalSizeYUnit' : 'µm' ,
... 'Channel' : { 'Name' : [ 'Channel 1' , 'Channel 2' ]},
... 'Plane' : { 'PositionX' : [ 0.0 ] * 16 , 'PositionXUnit' : [ 'µm' ] * 16 },
... 'Description' : 'A multi-dimensional, multi-resolution image' ,
... 'MapAnnotation' : { # for OMERO
... 'Namespace' : 'openmicroscopy.org/PyramidResolution' ,
... '1' : '256 256' ,
... '2' : '128 128' ,
... },
... }
... options = dict (
... photometric = 'rgb' ,
... tile = ( 128 , 128 ),
... compression = 'jpeg' ,
... resolutionunit = 'CENTIMETER' ,
... maxworkers = 2 ,
... )
... tif . write (
... data ,
... subifds = subresolutions ,
... resolution = ( 1e4 / pixelsize , 1e4 / pixelsize ),
... metadata = metadata ,
... ** options ,
... )
... # write pyramid levels to the two subifds
... # in production use resampling to generate sub-resolution images
... for level in range ( subresolutions ):
... mag = 2 ** ( level + 1 )
... tif . write (
... data [..., :: mag , :: mag , :],
... subfiletype = 1 ,
... resolution = ( 1e4 / mag / pixelsize , 1e4 / mag / pixelsize ),
... ** options ,
... )
... # add a thumbnail image as a separate series
... # it is recognized by QuPath as an associated image
... thumbnail = ( data [ 0 , 0 , :: 8 , :: 8 ] >> 2 ). astype ( 'uint8' )
... tif . write ( thumbnail , metadata = { 'Name' : 'thumbnail' })
...
Accédez aux niveaux d'image dans le fichier pyramidal OME-TIFF :
>> > baseimage = imread ( 'temp.ome.tif' )
>> > second_level = imread ( 'temp.ome.tif' , series = 0 , level = 1 )
>> > with TiffFile ( 'temp.ome.tif' ) as tif :
... baseimage = tif . series [ 0 ]. asarray ()
... second_level = tif . series [ 0 ]. levels [ 1 ]. asarray ()
... number_levels = len ( tif . series [ 0 ]. levels ) # includes base level
...
Parcourez et décodez les tuiles compressées JPEG uniques dans le fichier TIFF :