如何最好地保存tif图像元数据?

14

作为研究生,我的工作是捕捉显微镜图像并使用Python将它们保存为原始的tif格式。我想添加元数据,例如我所使用的显微镜名称、放大倍数和成像激光波长等信息。这些详细信息对于我后处理图像非常重要。

我应该可以在tif文件中添加这些信息,对吗?因为它有一个头文件?

我已经成功地在一个PIL图像中添加了附加信息:

im.info['microscope'] = 'george'

但是,当我保存并加载该图像时,我添加的信息就消失了。

我愿意听取任何建议。如果必要的话,我会保存一个带有元数据的单独的 .txt 文件,但将其嵌入图像中会更好。

4个回答

14

Tifffile 是在 Python 中保存带有大量元数据的显微图像的一种选择。

它没有很多外部文档,但是 docstings 很好,所以您可以通过在 Python 中键入 help(tifffile) 或查看源代码来获取很多信息。

您可以在源代码(第750行)中查看 TiffWriter.save 函数,以获取可用于编写元数据的不同关键字参数。

其中一个选项是使用 description,它接受一个字符串。当您读取图像时,它将显示为标签 "ImageDescription"。

另一个选项是使用 extratags 参数,它接受一个元组列表。这允许您编写任何存在于TIFF.TAGS()中的标记名称。最简单的方法之一是将它们编写为字符串,因为那样就不必指定长度。

您还可以使用 ijmetadata 编写 ImageJ 元数据,其可接受的类型在此处列出。

例如,如果您编写以下内容:

import json
import numpy as np
import tifffile

im = np.random.randint(0, 255, size=(150, 100), dtype=np.uint8)
# Description
description = "This is my description"
# Extratags
metadata_tag = json.dumps({"ChannelIndex": 1, "Slice": 5})
extra_tags = [("MicroManagerMetadata", 's', 0, metadata_tag, True),
              ("ProcessingSoftware", 's', 0, "my_spaghetti_code", True)]
# ImageJ metadata. 'Info' tag needs to be a string
ijinfo = {"InitialPositionList": [{"Label": "Pos1"}, {"Label": "Pos3"}]}
ijmetadata = {"Info": json.dumps(ijinfo)}
# Write file
tifffile.imsave(
    save_name,
    im,
    ijmetadata=ijmetadata,
    description=description,
    extratags=extra_tags,
)

阅读图片时,您可以看到以下标签:

frames = tifffile.TiffFile(save_name)
page = frames.pages[0]
print(page.tags["ImageDescription"].value)

输出:'这是我的描述'

print(page.tags["MicroManagerMetadata"].value)

输出结果: {'ChannelIndex': 1, 'Slice': 5}

print(page.tags["ProcessingSoftware"].value)

输出:我的面条式代码


8
尝试将元数据保存为JSON格式,并存储在TIFF ImageDescription标签中,以供内部使用,例如:
from __future__ import print_function, unicode_literals

import json
import numpy
import tifffile  # http://www.lfd.uci.edu/~gohlke/code/tifffile.py.html

data = numpy.arange(256).reshape((16, 16)).astype('u1')
metadata = dict(microscope='george', shape=data.shape, dtype=data.dtype.str)
print(data.shape, data.dtype, metadata['microscope'])

metadata = json.dumps(metadata)
tifffile.imsave('microscope.tif', data, description=metadata)

with tifffile.TiffFile('microscope.tif') as tif:
    data = tif.asarray()
    metadata = tif[0].image_description
metadata = json.loads(metadata.decode('utf-8'))
print(data.shape, data.dtype, metadata['microscope'])

请注意,JSON使用Unicode字符串。
为了与其他显微镜软件兼容,考虑保存OME-TIFF文件,这些文件将定义的元数据作为XML存储在ImageDescription标签中。

已经提到了OME-TIFF开放标准 - 谢谢。毫不怀疑,它是您数据存储的完美选择。Openmicroscopy已经在OME-TIFF的模型中拥有这样的元数据。您可以轻松使用Python语法在Jython与FIJI交互,这将让您编写出OME-TIFFs。 - Kenny
事实上,截至今天,你可以直接在Python中使用bioformats!http://lists.openmicroscopy.org.uk/pipermail/ome-devel/2014-March/002691.html - Kenny

8
我应该能用tif格式来做这个,对吧?因为它有一个头文件?
不行。
首先,你的前提是错误的,但那是一个红色的诱饵。TIFF确实有一个头文件,但它不允许你在其中存储任意元数据。
但是TIFF是一个标记文件格式,由不同类型的块组成,所以头文件在这里并不重要。而且你总是可以创建自己的私有块(任何ID>32767),并在其中存储任何你想要的内容。
问题是,除了你自己的代码之外,没有任何东西会知道你在那里存储了什么。所以,你可能想要存储EXIF或XMP或其他一些标准化格式,以扩展TIFF与元数据。但即使在那里,EXIF或你选择的任何东西都不会有一个"显微镜"的标签,所以最终你将不得不在某个字符串字段中存储像"显微镜=乔治\n垃圾邮件=鸡蛋\n"这样的东西,然后自己解析它。
但真正的问题是,PIL/Pillow没有给你一个简单的方法来存储EXIF或XMP或其他任何类似的东西。

首先,Image.info 并不适用于任意的额外数据。在保存时,它通常会被忽略。

如果您查看 TIFF 的 PIL 文档,您将看到它将附加数据读入到一个特殊属性 Image.tag 中,并可以通过向 Image.save 方法传递 tiffinfo 关键字参数来保存数据。但是,这些附加数据是从 TIFF 标签 ID 映射到二进制数据块的映射。您可以从未记录的 PIL.ExifTags.TAGS 字典(或自己在线查找)中获取 Exif 标签 ID,但这就是 PIL 将为您提供的全部支持。

此外,请注意访问tag和首先使用tiffinfo需要一个相当新的Pillow版本;旧版本和经典PIL不支持它。(具有讽刺意味的是,它们对JPG文件具有部分EXIF支持,但从未完成并已被剥离...)此外,尽管似乎没有记录,如果您构建了没有libtiff的Pillow,则似乎会忽略tiffinfo
因此,最终您可能想要做的是:
  • 选择您想要的元数据格式。
  • 使用与PIL / Pillow不同的库来读取和写入该元数据。 (例如,您可以使用GExiv2pyexif进行EXIF。)

2
你可以尝试在TIFF图像的标签属性中设置标签。这是一个对象。请参见。
或者,如果你安装了,你可以使用模块调用tiffset命令,在保存文件后设置头部中的字段。有在线参考资料可用的标签。
根据此页面
如果需要超过10个私有标签,TIFF规范建议不要使用大量的私有标签,而是应该分配一个单独的私有标签,将其定义为数据类型IFD,并用它指向所谓的“私有IFD”。在该私有IFD中,可以使用任何想要的标签。这些私有IFD标签不需要与Adobe进行正确注册,它们存在于自己的命名空间中,专门针对特定类型的IFD。

不确定PIL是否支持此功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接