TIFF文件
1. 什么是TIFF文件
TIFF (Tagged Image File Format) 标记图像文件格式,以tif或tiff为扩展名,通常由四部分组成,分别为:文件头信息区(IFH)、图像文件目录(IFD)、目录项(DE)和图像数据。
图像文件头信息区(IFH)
在每一个TIFF文件中第一个数据结构称为图像文件头或IFH (Image File Header),它是图像文件体系结构的最高层,位于文件的开始部分,这个位置是唯一的、固定的,包含着文件其他部分所需的必要信息。
图像文件目录(IFD)
IFD (Image File Directory)是TIFF文件的第2个数据结构,是一个名为标记 (tag) 的用于区分一个或多个可变长度数据块的表,tag中包含了有关图像的所有信息。
由于一个TIFF文件可以有多个图像,而一个IFD只标识一个图像的所有属性,故一个TIFF文件有几个图像就有几个IFD
IFD提供了一系列的指针,这些指针指向各种数据字段在文件中的起始位置,并给出每个字段的数据类型和长度,该方法允许数据字段定义在文件的任何地方,且可以为任意长度,因此文件格式十分灵活。
目录项(DE)
Byte 0-1: tag, 即该属性的标签编号,在文件目录中按升序排列
Byte 2-3: 数据类型
Byte 4-7: 数量,确定存储此tag的数据需要占据的字节数
Byte 8-11: 如果占用的字节数少于4,则数据直接存在此处,大于4则存放指向数据的指针
图像数据(Value)
根据IFD指向的地址,存储图像的具体信息。
TIFF的可扩展性很强,如jpeg、lossless jpeg以及任意数据宽度的原始无压缩数据都可以方便的嵌入到TIFF中去,对图像信息的存放灵活多变,能够使图像包含丰富的各类信息,所以在遥感、医学等数字影像领域都获得了广泛的应用。
2. Python与tiff
2.1 tiff文件的读取
tiff图像的编码格式为16bit, 使用python读取tiff图像通常有两种方法,一种是使用opencv进行读取,如下
import cv2 img = cv2.imread('img.tif', -1) # -1为保留图像原始格式读取,其余会将图像的编码格式转为8bit print(img.dtype) >> uint16
另一种方法为使用tifffile库进行读取,如下
import tifffile as tiff a = tiff.imread('img.tif')
# 或者
a = tiff.Tifffile(tiff_path).pages[level].asarray()
2.1 tiff文件的保存
可以使用tifffile库中TiffWriter将任意 numpy array保存为tiff文件
TiffWriter是一个将Numpy array转成tiff文件的类,初始化如下
from tifffile import TiffWriter import cv2 import numpy as np img = cv2.imread(img_path) writer = TiffWriter(file, bigtiff = False, byteorder = None, append = False, imagej = False, ome = None) file : 文件的保存路径 bigtiff : bool 当创建的文件大于4GB时使用True byteorder : {'<', '>', '=', '/'} 系统的字节顺序,默认就行 append : bool 如果设置为True并且file是一个现有的标准tiff文件,则会将 图片数据和tag添加到文件中 imagej : bool 理论上和下面那个我用不到,默认就完事了 ome : bool
初始化之后就可以将需要转化的图像使用write函数进行保存了
img_writer.write(data, photometric = 'rgb', compression = 'jpeg', planarconfig = 'CONTIG', tile = (256,256), subsampling = (1, 1), subfiletype = 9) # write里的参数实在是太多了,详见源码 data : numpy.ndarray photometric : {MINSBLACK, MINSWHITE, RGB, PALETTE, SEPARATED, CFA} compression : {str, (str, int), (str, int, dict)} 如果默认或None,数据写入不压缩 如果是一个str,可写为'JPEG'、'ZSTD' 如果是一个元组,str同上,第二项是压缩级别,第三项字典是传递给压缩编解码器的参数 planarconfig : {'CONTIG', 'SEPARATE'} CONTIG:最后一个维度包含的样本 SEPARATE:第三或第四个最后维度包含的样本 tile : tuple或int 要写入的图像块的形状,感觉应该是输入的图像块序列大小,然后拼 接成最终图像的感觉,长宽必须是16的倍数 subsampling : {(1, 1), (2, 1), (2, 2), (4, 1)} 二次采样 默认为(2, 2), 只是哦那个与RGB图像的JPEG压缩 subfiletype : int 如果图像是另一个图像的降低分辨率版本,则设置为0 如果图像是多页图像的一部分,则设置为1 如果图像是透明蒙版的另一个图像,则设置为2