从时间戳图像对创建 HDF5 数据集的最佳方法是啥?
Posted
技术标签:
【中文标题】从时间戳图像对创建 HDF5 数据集的最佳方法是啥?【英文标题】:What is the best way to create a HDF5 dataset from timestamp-image-pairs?从时间戳图像对创建 HDF5 数据集的最佳方法是什么? 【发布时间】:2021-04-20 15:13:50 【问题描述】:我必须从带有 C 时间戳的图像创建 HDF5 文件。我事先不知道我会得到多少对,所以固定大小的数据集不是一个选项。
我的数据样本是一个大型 (~ 12 x 10^6) uint8_t 数组,其中包含图像的扁平化版本以及 uint64_t 时间戳。为了更好地理解,我添加了我的解决方案的 C 等效项。
我可以为此想到 2 种可能的解决方案,但我对这两个都有问题。我会很感激这里的一些指示:
版本 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 用户指南 属性一章中的“特殊问题”部分。它说:“我们认为属性的最大大小为 64K 字节”。所以,如果你的时间图数组是 64K 字节的属性:1)在密集的属性存储中,或 2)在单独的数据集中。用户指南中有这两种技术的示例。请参阅 1.10 版指南中的第 306-308 页。 【参考方案1】:解决此用例的最佳方法是使用 HDF5 复合数据集(包含两个成员:timestamp
和 payload
),就像上面第 2 版中所述。
此外,数据集必须是可扩展的,以便它可以根据您将获得的数据大小(事先未知)而增长。为避免覆盖数据集中已存储的数据,您需要在向其中写入数据时使用选择(hyperslab 或点)。
解决用例的一种方法是在 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;
【讨论】:
以上是关于从时间戳图像对创建 HDF5 数据集的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
用于创建 HDF5 数据集的 4 维 c++ 数组的动态内存分配