Tifffile ist eine Python-Bibliothek für
Bild- und Metadaten können aus TIFF, BigTIFF, OME-TIFF, GeoTIFF, Adobe DNG, ZIF (Zoomable Image File Format), MetaMorph STK, Zeiss LSM, ImageJ Hyperstack, Micro-Manager MMStack und NDTiff, SGI, NIHImage und Olympus FluoView gelesen werden und SIS, ScanImage, Molecular Dynamics GEL, Aperio SVS, Leica SCN, Roche BIF, PerkinElmer QPTIFF (QPI, PKI), Hamamatsu NDPI, Argos AVS und Philips DP-formatierte Dateien.
Bilddaten können als NumPy-Arrays oder Zarr-Arrays/Gruppen aus Streifen, Kacheln, Seiten (IFDs), SubIFDs, Reihen höherer Ordnung und Pyramidenebenen gelesen werden.
Bilddaten können in TIFF-, BigTIFF-, OME-TIFF- und ImageJ-Hyperstack-kompatible Dateien in mehrseitiger, volumetrischer, pyramidenförmiger, speicherzuordnungsfähiger, gekachelter, vorhergesagter oder komprimierter Form geschrieben werden.
Viele Komprimierungs- und Vorhersageschemata werden über die Imagecodecs-Bibliothek unterstützt, darunter LZW, PackBits, Deflate, PIXTIFF, LZMA, LERC, Zstd, JPEG (8 und 12 Bit, verlustfrei), JPEG 2000, JPEG XR, JPEG XL, WebP, PNG , EER, Jetraw, 24-Bit-Gleitkomma und horizontale Differenzierung.
Tifffile kann auch verwendet werden, um TIFF-Strukturen zu überprüfen, Bilddaten aus mehrdimensionalen Dateisequenzen zu lesen, fsspec ReferenceFileSystem für TIFF-Dateien und Bilddateisequenzen zu schreiben, TIFF-Tag-Werte zu patchen und viele proprietäre Metadatenformate zu analysieren.
Autor: | Christoph Gohlke |
---|---|
Lizenz: | BSD 3-Klausel |
Version: | 2024.9.20 |
DOI: | 10.5281/zenodo.6795860 |
Installieren Sie das Tifffile-Paket und alle Abhängigkeiten aus dem Python-Paketindex:
python -m pip install -U tifffile[alle]
Tifffile ist auch in anderen Paket-Repositories wie Anaconda, Debian und MSYS2 verfügbar.
Die Tifffile-Bibliothek ist mit Typkommentaren versehen und über Dokumentzeichenfolgen dokumentiert:
python -c "tifffile importieren; help(tifffile)"
Tifffile kann als Konsolenskript zur Prüfung und Vorschau von TIFF-Dateien verwendet werden:
python -m tifffile --help
Siehe Beispiele für die Verwendung der Programmierschnittstelle.
Quellcode und Support sind auf GitHub verfügbar.
Support gibt es auch im image.sc-Forum.
Diese Revision wurde mit den folgenden Anforderungen und Abhängigkeiten getestet (andere Versionen funktionieren möglicherweise):
2024.9.20
2024.8.30
28.8.2024
24.8.2024
2024.8.10
24.7.2024
21.07.2024
2024.7.2
2024.6.18
2024.5.22
2024.5.10
2024.5.3
24.4.2024
2024.4.18
2024.2.12
2024.1.30
2023.12.9
26.9.2023
2023.9.18
2023.8.30
25.8.2023
2023.8.12
2023.7.18
Ältere Versionen finden Sie in der CHANGES-Datei.
TIFF, das Tagged Image File Format, wurde von der Aldus Corporation und Adobe Systems Incorporated erstellt.
Tifffile unterstützt eine Teilmenge der TIFF6-Spezifikation, hauptsächlich 8-, 16-, 32- und 64-Bit-Integer-, 16-, 32- und 64-Bit-Float-, Graustufen- und Multi-Sample-Bilder. Insbesondere sind CCITT- und OJPEG-Komprimierung, Chroma-Unterabtastung ohne JPEG-Komprimierung, Farbraumtransformationen, Samples mit unterschiedlichen Typen oder IPTC-, ICC- und XMP-Metadaten nicht implementiert.
Neben dem klassischen TIFF unterstützt tifffile mehrere TIFF-ähnliche Formate, die nicht strikt der TIFF6-Spezifikation entsprechen. Bei einigen Formaten können Datei- und Datengrößen die 4-GB-Grenze des klassischen TIFF überschreiten:
Andere Bibliotheken zum Lesen, Schreiben, Überprüfen oder Bearbeiten wissenschaftlicher TIFF-Dateien aus Python sind aicsimageio, apeer-ometiff-library, bigtiff, fabio.TiffIO, GDAL, imread, large_image, openlide-python, opentile, pylibtiff, pylsm, pymimage, python -Bioformate, Pytiff, Scanimagetiffreader-python, SimpleITK, slideio, tiffslide, tifftools, tyf, xtiff und ndtiff.
Schreiben Sie ein NumPy-Array in eine einseitige RGB-TIFF-Datei:
>> > data = numpy . random . randint ( 0 , 255 , ( 256 , 256 , 3 ), 'uint8' )
>> > imwrite ( 'temp.tif' , data , photometric = 'rgb' )
Lesen Sie das Bild aus der TIFF-Datei als NumPy-Array:
>> > image = imread ( 'temp.tif' )
>> > image . shape
( 256 , 256 , 3 )
Verwenden Sie die Argumente photometric und planarconfig, um ein 3x3x3 NumPy-Array in ein verschachteltes RGB, ein planares RGB oder ein 3-seitiges Graustufen-TIFF zu schreiben:
>> > 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' )
Verwenden Sie das Argument extrasamples, um anzugeben, wie zusätzliche Komponenten interpretiert werden, beispielsweise für ein RGBA-Bild mit nicht zugeordnetem Alphakanal:
>> > data = numpy . random . randint ( 0 , 255 , ( 256 , 256 , 4 ), 'uint8' )
>> > imwrite ( 'temp.tif' , data , photometric = 'rgb' , extrasamples = [ 'unassalpha' ])
Schreiben Sie ein dreidimensionales NumPy-Array in eine mehrseitige 16-Bit-Graustufen-TIFF-Datei:
>> > data = numpy . random . randint ( 0 , 2 ** 12 , ( 64 , 301 , 219 ), 'uint16' )
>> > imwrite ( 'temp.tif' , data , photometric = 'minisblack' )
Lesen Sie den gesamten Bildstapel aus der mehrseitigen TIFF-Datei als NumPy-Array:
>> > image_stack = imread ( 'temp.tif' )
>> > image_stack . shape
( 64 , 301 , 219 )
>> > image_stack . dtype
dtype ( 'uint16' )
Lesen Sie das Bild von der ersten Seite in der TIFF-Datei als NumPy-Array:
>> > image = imread ( 'temp.tif' , key = 0 )
>> > image . shape
( 301 , 219 )
Lesen Sie Bilder aus einem ausgewählten Seitenbereich:
>> > images = imread ( 'temp.tif' , key = range ( 4 , 40 , 2 ))
>> > images . shape
( 18 , 301 , 219 )
Durchlaufen Sie alle Seiten in der TIFF-Datei und lesen Sie nacheinander Bilder:
>> > with TiffFile ( 'temp.tif' ) as tif :
... for page in tif . pages :
... image = page . asarray ()
...
Erhalten Sie Informationen über den Bildstapel in der TIFF-Datei, ohne Bilddaten zu lesen:
>> > 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 ()
Überprüfen Sie das Tag „XResolution“ auf der ersten Seite in der TIFF-Datei:
>> > 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 >
Durchlaufen Sie alle Tags in der TIFF-Datei:
>> > with TiffFile ( 'temp.tif' ) as tif :
... for page in tif . pages :
... for tag in page . tags :
... tag_name , tag_value = tag . name , tag . value
...
Überschreiben Sie den Wert eines vorhandenen Tags, zum Beispiel XResolution:
>> > with TiffFile ( 'temp.tif' , mode = 'r+' ) as tif :
... _ = tif . pages [ 0 ]. tags [ 'XResolution' ]. overwrite (( 96000 , 1000 ))
...
Schreiben Sie ein 5-dimensionales Gleitkomma-Array im BigTIFF-Format, mit separaten Farbkomponenten, Kacheln, Zlib-Komprimierungsstufe 8, horizontalem Differenzierungsprädiktor und zusätzlichen Metadaten:
>> > 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' },
... )
Schreiben Sie eine 10-fps-Zeitreihe von Volumina mit der xyz-Voxelgröße 2,6755 x 2,6755 x 3,9474 Mikrometer^3 in eine ImageJ-Hyperstack-formatierte TIFF-Datei:
>> > 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 ,
... },
... )
Lesen Sie das Volume und die Metadaten aus der ImageJ-Hyperstack-Datei:
>> > 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
Speicherzuordnung der zusammenhängenden Bilddaten in der ImageJ-Hyperstack-Datei:
>> > memmap_volume = memmap ( 'temp.tif' )
>> > memmap_volume . shape
( 6 , 57 , 256 , 256 )
>> > del memmap_volume
Erstellen Sie eine TIFF-Datei mit einem leeren Bild und schreiben Sie in das speicherzugeordnete NumPy-Array (Hinweis: Dies funktioniert nicht mit Komprimierung oder Kachelung):
>> > 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
Schreiben Sie zwei NumPy-Arrays in eine TIFF-Datei mit mehreren Serien (Hinweis: Andere TIFF-Reader erkennen die beiden Serien nicht; verwenden Sie das OME-TIFF-Format für eine bessere Interoperabilität):
>> > 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' )
...
Lesen Sie die zweite Bildserie aus der TIFF-Datei:
>> > series1 = imread ( 'temp.tif' , series = 1 )
>> > series1 . shape
( 4 , 256 , 256 )
Schreiben Sie nacheinander die Bilder einer zusammenhängenden Serie in eine TIFF-Datei:
>> > 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 )
...
Hängen Sie eine Bildserie an die vorhandene TIFF-Datei an (Hinweis: Dies funktioniert nicht mit ImageJ-Hyperstack- oder OME-TIFF-Dateien):
>> > data = numpy . random . randint ( 0 , 255 , ( 301 , 219 , 3 ), 'uint8' )
>> > imwrite ( 'temp.tif' , data , photometric = 'rgb' , append = True )
Erstellen Sie eine TIFF-Datei aus einem Kachelgenerator:
>> > 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' ,
... )
Schreiben Sie eine mehrdimensionale OME-TIFF-Datei mit mehreren Auflösungen (Pyramidenform) und mehreren Serien mit optionalen Metadaten. Bilder mit niedriger Auflösung werden in SubIFDs geschrieben. Beschränken Sie die parallele Codierung auf 2 Threads. Schreiben Sie ein Miniaturbild als separate Bildserie:
>> > 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' })
...
Greifen Sie auf die Bildebenen in der pyramidenförmigen OME-TIFF-Datei zu:
>> > 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
...
Durchlaufen und Dekodieren einzelner JPEG-komprimierter Kacheln in der TIFF-Datei: