我必须从带有 C 语言时间戳的图像创建 HDF5 文件。我事先不知道我将获得多少对,因此固定大小的数据集不是一个选项。
我的数据样本是一个大型 (~ 12 x 10^6) uint8_t 数组,除了 uint64_t 时间戳之外,还包含图像的扁平版本。为了更好地理解,我添加了我的解决方案的 C 等效项。
我可以想到两种可能的解决方案,但我对这两种方案都有问题。我希望在这里得到一些指示:
版本1
我创建了一个初始大小为 0 的二维 uint8_t 数据集。我在每次迭代期间扩展数据集并将图像数据写入 HDF5 文件。在这里,我计划将时间戳放入数据集属性中相应的 uint64_t 数组中。问题是我发现无法随时随地扩展属性数组,因此我必须将所有时间戳保存在临时数组中,然后将其添加到属性中。这不仅消耗内存,而且在崩溃的情况下,我只剩下图像但没有时间戳。
uint8_t images[][IMG_BUF_SIZE];
(as attribute:)
uint64_t timestamps[];
版本2
我尝试使用复合数据类型,以便获得复合类型样本的一维数组。每个样本都包含 uint64_t 时间戳和大型 uint8_t 数组。我遇到的问题是,我在 HDF5 的文档中读到,在复合数据类型中,不建议使用“大数组”。
typedef struct
{
uint64_t timestamp;
uint8_t payload[IMG_BUF_SIZE];
} time_image_t;
time_image_t array[];
如何做到这一点?这些类型的数据集应该很常见,但我无法找到执行此操作的标准方法。
谢谢!
解决此用例的最佳方法是使用 HDF5 复合数据集(包含两个成员:
timestamp
和 payload
),就像上面版本 2 中所述。
此外,数据集必须是可扩展的,以便它可以根据您将获得的数据大小(事先未知)进行增长。为了避免覆盖数据集中已存储的数据,在将数据写入其中时,您需要使用选择(超板或点)。
解决您的用例的一种方法可以是通过在 C 中使用HDFql,如下所示(请注意,在本例中,我只是向数据集添加了两个“行” - 您可以有一个循环添加尽可能多的“行” “根据需要解决您的想法):
#include <stdio.h>
#include <stddef.h>
#include "HDFql.h"
#define IMG_BUF_SIZE 3
typedef struct
{
uint64_t timestamp;
uint8_t payload[IMG_BUF_SIZE];
}time_image_t;
int main(int argc, char *argv[])
{
// declare variables
char script[1024];
time_image_t data;
// create HDF5 file named 'data.h5' and use (i.e. open) it
hdfql_execute("create and use file data.h5");
// prepare script to create an extendable dataset named 'dset' of data type compound (containing two members named 'timestamp' and 'payload')
sprintf(script, "create dataset dset as compound(timestamp as unsigned bigint offset %d, payload as unsigned tinyint(%d) offset %d)(unlimited) size %d", offsetof(time_image_t, timestamp), IMG_BUF_SIZE, offsetof(time_image_t, payload), sizeof(time_image_t));
// execute script
hdfql_execute(script);
// register variable 'data' for subsequent usage (by HDFql)
hdfql_variable_register(&data);
// populate variable 'data' with some values
data.timestamp = 123;
data.payload[0] = 10;
data.payload[1] = 20;
data.payload[2] = 30;
// insert data into last row of dataset 'dset' thanks to a point selection
hdfql_execute("insert into dset[-1] values from memory 0");
// populate variable 'data' with more values
data.timestamp = 456;
data.payload[0] = 75;
data.payload[1] = 85;
data.payload[2] = 95;
// alter (i.e. change) dimension of dataset 'dset' to +1
hdfql_execute("alter dimension dset to +1");
// insert data into last row of dataset 'dset' thanks to a point selection
hdfql_execute("insert into dset[-1] values from memory 0");
// unregister variable 'data' as it is no longer used (by HDFql)
hdfql_variable_unregister(&data);
// close HDF5 file 'data.h5'
hdfql_execute("close file");
return 0;
}