【问题标题】:How to configure maxshape argument for H5 and append to file?如何为 H5 配置 maxshape 参数并附加到文件?
【发布时间】:2020-08-30 18:07:50
【问题描述】:

我正在尝试将图像数据集合并到 H5 文件中。到目前为止,我已经设法创建了该文件,但是当我附加到它时,它只会覆盖已经存在的内容。我查看了其他答案(例如Adding data to existing h5py file along new axis using h5py)并尝试了它们的变体但无济于事。

for i in range(len(files)):
    if i == 0:
        with h5py.File('input_images.h5', 'w') as f:
            img = np.array(Image.open(files[i]))
            f.create_dataset('/array', data = img, maxshape = (None), chunks = True, dtype = img.dtype)
    else:
        with h5py.File('input_images.h5', 'r+') as f:
            img = np.array(Image.open(files[i]))
            f.require_dataset('/array', data = img, shape = img.shape, dtype = img.dtype)
    print(i)

我尝试将 maxshape 设置为 (None, None, None),但这只会产生错误:ValueError: "maxshape" must have same rank as dataset shape

总共有 1000 张图片,每张图片的形状为 2048 到 2048。有人可以告诉我如何修复我的代码吗?

【问题讨论】:

  • 查看这个答案。第一步创建一个 HDF5 文件,其中包含与您类似的图像数据集。但是,它会一次性加载所有图像数据。我将尝试创建一个示例,稍后为您逐步完成它。 How get data from hdf5 file
  • 这里是另一个使用maxshape和resize的例子。 way to remove rows from a HDF5 dataset 添加或删除工作相同。这个例子比较简单:数据集和数组的维数相同。

标签: python image numpy h5py


【解决方案1】:

使用maxshape 参数可以修改数据集大小。请注意,maxshape 需要与您的图像数据集的尺寸相匹配。您输入了 1 个维度,但所有图像数据(1000、2048、2048)都需要 3 个维度。此外,代码中的初始数据集大小是根据 data=img 数组大小的大小设置的。它将具有形状(2048,2048)。数据集需要所有图像数据的第三维。
加载所有图像数据的方法有 3 种:
1. 将shape=(nfiles,a1,a2) 设置为所有图像的初始大小。除非您以后想添加更多图片,否则无需调整大小。
2. 初始设置shape=(1,a1,a2)(用于1张图片),然后在添加图片时使用.resize()增加尺寸。随着数据集的增长,此方法效率不高。
3.初始设置shape=(N,a1,a2)(N张图片),然后使用.resize() 当数据集已满时将大小增加 N。 (N 可以是任意数字。我在下面的示例中使用了 10,但您可能会在实际应用中使用 100 或 1000)。

所有 3 种方法都在下面的示例中,用于 30 张图像,图像尺寸较小。我为图像创建随机整数数据。将 np.random.randint() 替换为 np.array(Image.open(files[i])) 用于您的文件。

示例演示了该过程。请注意,方法 1 和 2 仅在您创建 HDF5 文件并填充图像数据时有效(因为数据集索引与图像计数器相同)。方法 3 展示了如何以增量方式添加数据。它使用一个属性来计算加载的图像数量。计数器设置添加新图像的位置。它还用于检查当前数据集的大小(并根据需要调整大小)。

在生产代码中,您需要额外检查图像大小和形状是否与数据集大小和形状匹配。

import h5py
import numpy as np
nfiles=30
a0 = nfiles  # for number of images
a1= 256 ; a2 = 256 # for image size

with h5py.File('input_images1.h5', 'w') as f:    
    for i in range(nfiles):
        img_arr = np.random.randint(0,254, (a1, a2), int)
        if i == 0:
            img_ds = f.create_dataset('/array', shape=(a0,a1,a2), 
                             maxshape = (None,a1,a2), chunks = True)
        f['/array'][i,:,:]=img_arr
        print(i)

with h5py.File('input_images2.h5', 'w') as f:    
    for i in range(nfiles):
        img_arr = np.random.randint(0,254, (a1, a2), int)
        if i == 0:
            img_ds = f.create_dataset('/array', shape=(1,a1,a2), 
                             maxshape = (None,a1,a2), chunks = True)
        else:
            f['/array'].resize(i+1,axis=0)
        f['/array'][i,:,:]=img_arr
        print(i)        

with h5py.File('input_images3.h5', 'a') as f:
    for i in range(nfiles):
        img_arr = np.random.randint(0,254, (a1, a2), int)
        if 'array' not in f.keys() :
            img_ds = f.create_dataset('/array', shape=(10,a1,a2), 
                             maxshape = (None,a1,a2), chunks = True)
            img_ds.attrs['n_images'] = 0
        else:
            img_ds = f['/array']

        n_images = img_ds.attrs['n_images']
        if n_images == img_ds.shape[0] :
            print ('adding 10 rows to /array')
            img_ds .resize(img_ds.shape[0]+10,axis=0)

        img_ds[n_images,:,:]=img_arr
        img_ds.attrs['n_images'] = n_images+1
        print(img_ds.attrs['n_images'])   

【讨论】:

  • 事后看来,我意识到这个答案有以下限制:1)它只有在一次添加所有图像文件时才有效。否则,行计数器 (i) 将在零处重新启动。 2)第二种方法一次添加一行(随着数据集的增长,这不是很有效)。我添加了第三种方法(我的首选方法)。它创建包含一些行的数据集,并使用属性来跟踪已添加的图像数量。计数器用于检查是否需要调整大小和位置以添加新图像。
猜你喜欢
  • 2021-05-08
  • 2014-05-23
  • 2015-05-12
  • 2018-10-03
  • 2020-02-04
  • 1970-01-01
  • 2021-03-29
  • 2020-01-30
  • 2018-09-17
相关资源
最近更新 更多