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、分子动力学 GEL、Aperio SVS、Leica SCN、Roche BIF、 PerkinElmer QPTIFF(QPI、PKI)、Hamamatsu NDPI、Argos AVS 和 Philips DP 格式的文件。
图像数据可以从条带、图块、页面 (IFD)、SubIFD、高阶系列和金字塔级别读取为 NumPy 数组或 Zarr 数组/组。
图像数据可以以多页、体积、金字塔、内存可映射、平铺、预测或压缩形式写入 TIFF、BigTIFF、OME-TIFF 和 ImageJ hyperstack 兼容文件。
imagecodecs 库支持许多压缩和预测方案,包括 LZW、PackBits、Deflate、PIXTIFF、LZMA、LERC、Zstd、JPEG(8 和 12 位,无损)、JPEG 2000、JPEG XR、JPEG XL、WebP、PNG 、EER、Jetraw、24 位浮点和水平差分。
Tifffile 还可用于检查 TIFF 结构、从多维文件序列读取图像数据、为 TIFF 文件和图像文件序列编写 fsspec ReferenceFileSystem、修补 TIFF 标记值以及解析许多专有元数据格式。
作者: | 克里斯托夫·戈尔克 |
---|---|
执照: | BSD 3 条款 |
版本: | 2024年9月20日 |
数字编号: | 10.5281/泽诺多.6795860 |
从 Python 包索引安装 tifffile 包和所有依赖项:
python -m pip install -U tifffile[全部]
Tifffile 也可在其他软件包存储库中使用,例如 Anaconda、Debian 和 MSYS2。
tifffile 库通过文档字符串进行类型注释和记录:
python -c“导入 tifffile;帮助(tifffile)”
Tifffile 可以用作控制台脚本来检查和预览 TIFF 文件:
python -m tifffile --帮助
请参阅使用编程接口的示例。
源代码和支持可在 GitHub 上获取。
image.sc 论坛上也提供支持。
此版本已根据以下要求和依赖项进行了测试(其他版本也可能有效):
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日
请参阅 CHANGES 文件了解旧版本。
TIFF(标记图像文件格式)由 Aldus Corporation 和 Adobe Systems Incorporated 创建。
Tifffile 支持 TIFF6 规范的子集,主要是 8、16、32 和 64 位整数、16、32 和 64 位浮点、灰度和多样本图像。具体来说,未实现 CCITT 和 OJPEG 压缩、无 JPEG 压缩的色度子采样、色彩空间转换、不同类型的样本或 IPTC、ICC 和 XMP 元数据。
除了经典 TIFF 之外,tifffile 还支持多种不严格遵守 TIFF6 规范的类 TIFF 格式。某些格式允许文件和数据大小超过经典 TIFF 的 4 GB 限制:
用于从 Python 读取、写入、检查或操作科学 TIFF 文件的其他库包括 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 和 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 参数将 3x3x3 NumPy 数组写入交错 RGB、平面 RGB 或 3 页灰度 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 参数指定如何解释额外组件,例如,对于具有不关联的 Alpha 通道的 RGBA 图像:
>> > data = numpy . random . randint ( 0 , 255 , ( 256 , 256 , 4 ), 'uint8' )
>> > imwrite ( 'temp.tif' , data , photometric = 'rgb' , extrasamples = [ 'unassalpha' ])
将 3 维 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 ()
检查 TIFF 文件第一页中的“XResolution”标记:
>> > 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 ))
...
使用 BigTIFF 格式、单独的颜色分量、平铺、Zlib 压缩级别 8、水平差分预测器和其他元数据编写 5 维浮点数组:
>> > 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' },
... )
将 xyz 体素大小为 2.6755x2.6755x3.9474 micron^3 的 10 fps 时间序列卷写入 ImageJ hyperstack 格式的 TIFF 文件:
>> > 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 hyperstack 文件中读取卷和元数据:
>> > 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 hyperstack 文件中的连续图像数据进行内存映射:
>> > 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。将并行编码限制为 2 个线程。将缩略图写入为单独的图像系列:
>> > 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
...
迭代并解码 TIFF 文件中的单个 JPEG 压缩图块: