如何从 hdf5 保存/提取数据集并转换为 TiFF?

Posted

技术标签:

【中文标题】如何从 hdf5 保存/提取数据集并转换为 TiFF?【英文标题】:How to save/extract dataset from hdf5 and convert into TiFF? 【发布时间】:2022-01-15 22:32:43 【问题描述】:

我正在尝试将 CT 扫描数据导入 ImageJ/FIJI(ImageJ/Fiji 中有 HDF5 插件,但是同步加速器 CT 数据具有如此大的数据集......因此无法打开)。扫描数据(图像数据集)作为数据集保存到 hdf5 文件中。 所以我必须从 hdf5 文件中提取图像数据集,然后将其转换为 Tiff 文件。

HdF5 文件路径为“F:/New_ESRF/SNT_BTO4/SNT_BTO4_S1/SNT_BTO4_S1_1_1pag_db0005_vol.hdf5” 这里将'SNT_BTO4_S1_1_1pag_db0005_vol.hdf5'分成几个数据集,图片数据集在这里:/entry0000/reconstruction/results/data

目前,我使用 h5py 访问图像数据集。但是,在那之后,我不得不将数据集与 hdf5 文件分开提取/保存。

从 hdf5 文件中提取图像数据集需要哪些代码? 之后,我正在考虑使用from PIL to Image 然后将图像转换为Tiff 文件。我可以就这方面的代码获得任何建议吗?
import numpy as np
import h5py
filename = "F:/New_ESRF/SNT_BTO4/SNT_BTO4_S1/SNT_BTO4_S1_1_1pag_db0005_vol.hdf5"

with h5py.File(filename,'r') as hdf:
base_items = list (hdf.items())
print('#Items in the base directory:', base_items)
    
#entry0000
G1 = hdf.get ('entry0000')
G1_items = list (G1.items())
print('#Items in entry0000', G1_items)
    
#reconstruction 
G11 = G1.get ('/entry0000/reconstruction')
G11_items = list (G11.items())
print('#Items in reconstruction', G11_items)
    
#results_data
G12 = G11.get ('/entry0000/reconstruction/results')
G12_items = list (G12.items())
print('#Items in results', G12_items)

【问题讨论】:

这有什么不明白的,docs.h5py.org/en/stable/high/dataset.html#reading-writing-data 【参考方案1】:

从 HDF5 文件中提取图像数据并转换为图像是一个“相对简单”的两步过程:

    访问 HDF5 文件中的数据 使用 cv2(或 PIL)转换为图像

这里有一个简单的例子:How to extract individual JPEG images from a HDF5 file。

您可以将相同的过程应用于您的文件。这是一些伪代码。它不完整,因为您没有显示图像数据集的形状(并且形状会影响如何读取数据)。另外,您没有说数据集中有多少张图像/entry0000/reconstruction/results/data --- 它是单张图像还是多张图像。如果是多张图片,图片计数器是哪个轴?

import h5py
import cv2 ## for image conversion

filename = "F:/New_ESRF/SNT_BTO4/SNT_BTO4_S1/SNT_BTO4_S1_1_1pag_db0005_vol.hdf5"

with h5py.File(filename,'r') as hdf:     
    # get image dataset
    img_ds = hdf['/entry0000/reconstruction/results/data'] 
    print(f'Image Dataset info: Shape=img_ds.shape,Dtype=img_ds.dtype')
    ## following depends on dataset shape/schema 
    ## code below assumes images are along axis=0
    for i in range(img_ds.shape[0]):
        cv2.imwrite(f'test_img_i:03.tiff',img_ds[i,:]) # uses slice notation
        # alternately load to a numpy array first
        img_arr = img_ds[i,:]   # slice notation gets [i,:,:,:]
        cv2.imwrite(f'test_img_i:03.tiff',img_arr)

注意:您不需要使用.get() 来获取数据集。您可以简单地引用数据集路径。此外,当您使用组对象时,请使用从数据集到组的相对路径,而不是绝对路径。 (您应该修改您的代码以反映这些更改。)例如,以下是等效的

G1 = hdf['entry0000']  
## is the same as     G1 = hdf.get('entry0000')
G11 = hdf['entry0000/reconstruction']  
## is the same as     G11 = hdf.get('entry0000/reconstruction')
## OR referencing G1 group object:
G11 = G1['reconstruction']
## is the same as     G11 = G1.get('reconstruction')

【讨论】:

嗨@kcw78 谢谢你的回答!当我打印我的图像数据集时,我在 entry0000/reconstruction/results [('data', )] 中得到了#Items - 基本上,图像数据形状似乎与像素大小有关,因为我使用 2160 * 2560 像素的检测器获得了扫描数据! 好的,这是一个开始。没错,2560X2560 与图像尺寸相匹配。但是,一个典型的图像数组将具有形状 (2560,2560,3),其中第三个索引代表颜色(或灰度)通道所以,我不确定如何解释 2160。是图像的数量 - - 如果是这样,通道数据如何存储在哪里?此时,您需要调查该数据集是如何创建和存储的。一旦你有了它,你就可以重新创建图像。 感谢您的 cmets!我可以确认 2160 是图像数量。图像数据是灰度的(不像具有 3 个 RGB 通道的普通 jpg 文件......)。关于这一点,我无法解释如何找到存储通道数据的位置。但是,我刚刚意识到我也可以从您建议的代码中获得一些 tiff 图像!不过,jupyter 实验室需要更长的时间来运行此代码(可能是由于 2160 张图像......!)。 ##我可以快速问一下如果我们使用 i 或 ii 会有什么区别(在这段代码中你写的:for i in range(img_ds.shape[0]):) ## 是否要将变量i 重命名为ii?当然,你可以使用任何你喜欢的变量名,只要它在循环内是一致的。 (我经常使用cntimg_cnt b/c,它更具描述性。)

以上是关于如何从 hdf5 保存/提取数据集并转换为 TiFF?的主要内容,如果未能解决你的问题,请参考以下文章

测试 HDF5/c++ 中存在的数据集并处理错误

如何从 .hdf5 文件表中提取列名并根据指定的列名提取特定行数据?

如何从 HDF5 文件中提取单个 JPEG 图像

检查失败:如何在深层使用 hdf5 数据层?

Dask:定期更新已发布的数据集并从其他客户端提取数据

如何保存结果集并在 TableView 中显示所有数据