Tifffile — это библиотека Python для
Изображения и метаданные можно считывать из TIFF, BigTIFF, OME-TIFF, GeoTIFF, Adobe DNG, ZIF (формат файла масштабируемого изображения), MetaMorph STK, Zeiss LSM, ImageJ Hyperstack, Micro-Manager MMStack и NDTiff, SGI, NIHImage, Olympus FluoView. и SIS, ScanImage, Molecular Dynamics GEL, Aperio SVS, Leica SCN, Roche Файлы в формате BIF, PerkinElmer QPTIFF (QPI, PKI), Hamamatsu NDPI, Argos AVS и Philips DP.
Данные изображения можно считывать как массивы NumPy или массивы/группы Zarr из полос, плиток, страниц (IFD), SubIFD, серий более высокого порядка и пирамидальных уровней.
Данные изображения можно записывать в файлы TIFF, BigTIFF, OME-TIFF и ImageJ, совместимые с гиперстеком, в многостраничной, объемной, пирамидальной, отображаемой в памяти, мозаичной, прогнозируемой или сжатой форме.
Библиотека кодеков изображений поддерживает множество схем сжатия и прогнозирования, включая LZW, PackBits, Deflate, PIXTIFF, LZMA, LERC, Zstd, JPEG (8 и 12-битный, без потерь), JPEG 2000, JPEG XR, JPEG XL, WebP, PNG , EER, Jetraw, 24-битные операции с плавающей запятой и горизонтальное дифференцирование.
Tifffile также можно использовать для проверки структур TIFF, чтения данных изображения из многомерных последовательностей файлов, записи fsspec ReferenceFileSystem для файлов TIFF и последовательностей файлов изображений, исправления значений тегов TIFF и анализа многих собственных форматов метаданных.
Автор: | Кристоф Гольке |
---|---|
Лицензия: | BSD 3-пункт |
Версия: | 20.09.2024 |
ДОИ: | 10.5281/зенодо.6795860 |
Установите пакет tifffile и все зависимости из индекса пакетов Python:
python -m pip install -U tifffile[все]
Tifffile также доступен в других репозиториях пакетов, таких как Anaconda, Debian и MSYS2.
Библиотека tifffile аннотирована по типу и документирована с помощью строк документации:
python -c "импортировать файл tiff; помощь (файл tiff)"
Tifffile можно использовать в качестве консольного сценария для проверки и предварительного просмотра файлов TIFF:
python -m tifffile --help
См. Примеры использования интерфейса программирования.
Исходный код и поддержка доступны на GitHub.
Поддержка также предоставляется на форуме image.sc.
Эта версия была протестирована со следующими требованиями и зависимостями (другие версии могут работать):
20.09.2024
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
Более старые версии см. в файле CHANGES.
TIFF, формат файлов изображений с тегами, был создан корпорациями Aldus и Adobe Systems Incorporated.
Tifffile поддерживает подмножество спецификации TIFF6, в основном 8, 16, 32 и 64-битные целочисленные, 16, 32 и 64-битные изображения с плавающей запятой, изображения в оттенках серого и изображения с несколькими выборками. В частности, не поддерживаются сжатие CCITT и OJPEG, подвыборка цветности без сжатия JPEG, преобразования цветового пространства, выборки разных типов или метаданные IPTC, ICC и XMP.
Помимо классического TIFF, tifffile поддерживает несколько форматов, подобных TIFF, которые не строго соответствуют спецификации TIFF6. Некоторые форматы позволяют размерам файлов и данных превышать предел классического TIFF в 4 ГБ:
Другими библиотеками для чтения, записи, проверки или управления научными файлами TIFF из Python являются aicsimageio, apeer-ometiff-library, bigtiff, fabio.TiffIO, GDAL, imread, big_image, openslide-python, opentile, pylibtiff, pylsm, pymimage, python. -биоформаты, pytiff, scanimagetiffreader-python, SimpleITK, слайдио, tiffslide, tifftools, tyf, xtiff и ndtiff.
Запишите массив NumPy в одностраничный файл RGB TIFF:
>> > data = numpy . random . randint ( 0 , 255 , ( 256 , 256 , 3 ), 'uint8' )
>> > imwrite ( 'temp.tif' , data , photometric = 'rgb' )
Считайте изображение из файла TIFF как массив NumPy:
>> > image = imread ( 'temp.tif' )
>> > image . shape
( 256 , 256 , 3 )
Используйте аргументы photometric и planarconfig для записи массива NumPy 3x3x3 в чередующийся RGB, плоский RGB или трехстраничный TIFF в оттенках серого:
>> > 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' )
Используйте аргумент extrasamples, чтобы указать, как интерпретируются дополнительные компоненты, например, для изображения RGBA с несвязанным альфа-каналом:
>> > data = numpy . random . randint ( 0 , 255 , ( 256 , 256 , 4 ), 'uint8' )
>> > imwrite ( 'temp.tif' , data , photometric = 'rgb' , extrasamples = [ 'unassalpha' ])
Запишите трехмерный массив NumPy в многостраничный 16-битный файл TIFF в оттенках серого:
>> > data = numpy . random . randint ( 0 , 2 ** 12 , ( 64 , 301 , 219 ), 'uint16' )
>> > imwrite ( 'temp.tif' , data , photometric = 'minisblack' )
Считайте весь стек изображений из многостраничного файла TIFF как массив NumPy:
>> > image_stack = imread ( 'temp.tif' )
>> > image_stack . shape
( 64 , 301 , 219 )
>> > image_stack . dtype
dtype ( 'uint16' )
Прочитайте изображение с первой страницы файла TIFF как массив NumPy:
>> > image = imread ( 'temp.tif' , key = 0 )
>> > image . shape
( 301 , 219 )
Чтение изображений из выбранного диапазона страниц:
>> > images = imread ( 'temp.tif' , key = range ( 4 , 40 , 2 ))
>> > images . shape
( 18 , 301 , 219 )
Перебрать все страницы файла TIFF и последовательно прочитать изображения:
>> > with TiffFile ( 'temp.tif' ) as tif :
... for page in tif . pages :
... image = page . asarray ()
...
Получите информацию о стеке изображений в файле TIFF, не читая никаких данных изображения:
>> > 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 ()
Проверьте тег «XResolution» на первой странице файла 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 >
Перебрать все теги в файле 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
...
Перезапишите значение существующего тега, например XResolution:
>> > with TiffFile ( 'temp.tif' , mode = 'r+' ) as tif :
... _ = tif . pages [ 0 ]. tags [ 'XResolution' ]. overwrite (( 96000 , 1000 ))
...
Запишите 5-мерный массив с плавающей запятой, используя формат BigTIFF, отдельные цветовые компоненты, мозаику, уровень сжатия Zlib 8, предиктор горизонтального дифференцирования и дополнительные метаданные:
>> > 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' },
... )
Запишите временной ряд объемов со скоростью 10 кадров в секунду и размером воксела xyz 2,6755x2,6755x3,9474 микрона^3 в файл TIFF в формате ImageJ Hyperstack:
>> > 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 ,
... },
... )
Прочитайте том и метаданные из файла гиперстека 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
Отобразите в памяти данные непрерывного изображения в файле гиперстека ImageJ:
>> > memmap_volume = memmap ( 'temp.tif' )
>> > memmap_volume . shape
( 6 , 57 , 256 , 256 )
>> > del memmap_volume
Создайте файл TIFF, содержащий пустое изображение, и запишите его в отображенный в память массив NumPy (примечание: это не работает со сжатием или мозаикой):
>> > 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
Запишите два массива NumPy в многосерийный файл TIFF (примечание: другие программы чтения TIFF не распознают эти две серии; для лучшей совместимости используйте формат OME-TIFF):
>> > 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' )
...
Прочтите вторую серию изображений из файла TIFF:
>> > series1 = imread ( 'temp.tif' , series = 1 )
>> > series1 . shape
( 4 , 256 , 256 )
Последовательно запишите кадры одной непрерывной серии в файл 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 )
...
Добавьте серию изображений к существующему файлу TIFF (примечание: это не работает с файлами ImageJ Hyperstack или OME-TIFF):
>> > data = numpy . random . randint ( 0 , 255 , ( 301 , 219 , 3 ), 'uint8' )
>> > imwrite ( 'temp.tif' , data , photometric = 'rgb' , append = True )
Создайте файл TIFF из генератора тайлов:
>> > 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' ,
... )
Напишите многомерный файл OME-TIFF с несколькими разрешениями (пирамидальный) с несколькими сериями и дополнительными метаданными. Изображения с меньшим разрешением записываются в SubIFD. Ограничьте параллельное кодирование двумя потоками. Запишите миниатюру изображения как отдельную серию изображений:
>> > 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' })
...
Получите доступ к уровням изображения в пирамидальном файле 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
...
Перебирайте и декодируйте отдельные фрагменты, сжатые в формате JPEG, в файле TIFF: