Каков наилучший способ создать набор данных HDF5 из пар временных меток-изображений?

#arrays #c #file #append #hdf5

#массивы #c #файл #добавить #hdf5

Вопрос:

Мне нужно создать файлы HDF5 из изображений, которые поставляются с меткой времени в C. Я НЕ знаю заранее, сколько из этих пар я получу, поэтому набор данных фиксированного размера — это не вариант.

Образец моих данных представлен в виде большого (~ 12 x 10 ^ 6) массива uint8_t, содержащего уменьшенную версию изображения в дополнение к метке времени uint64_t. Я добавил эквиваленты своих решений на языке Си для лучшего понимания.

Я мог бы придумать 2 возможных решения для этого, но у меня есть свои проблемы с обоими. Я был бы признателен за некоторые указания здесь:

ВЕРСИЯ 1

Я создаю 2-D набор данных uint8_t с начальным размером 0. На ходу я расширяю набор данных во время каждой итерации и записываю данные изображения в файл HDF5. Здесь я планировал поместить временные метки в соответствующий массив uint64_t в атрибутах dataset. Проблема в том, что я не нашел способа расширить массив атрибутов на ходу, поэтому мне пришлось бы сохранить все временные метки во временном массиве и добавить его к атрибутам позже. Это не только отнимает много памяти, но и в случае сбоя у меня остаются изображения, но без временных меток.

 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[];
 

Как это можно сделать? Наборы данных этих типов должны быть довольно распространенными, но я не смог найти стандартный способ сделать это.

Спасибо!

Комментарии:

1. Я советую прочитать раздел «Особые вопросы» в главе «Атрибуты» Руководства пользователя HDF5 . В нем говорится: «Мы считаем, что максимальный размер атрибута составляет 64 тысячи байт» . Итак, если ваш массив временной карты составляет <64 КБ, все будет в порядке. Если нет, есть два способа сохранить атрибуты> 64 Тыс. байт: 1) в плотном хранилище атрибутов или 2) в отдельном наборе данных. В Руководстве пользователя приведены примеры обоих методов. См. pgs 306-308 в Руководстве для выпуска 1.10.

Ответ №1:

Лучший способ решить эту проблему — использовать составной набор данных HDF5 (содержащий два элемента: timestamp и payload ), как описано в версии 2 выше.

Кроме того, набор данных должен быть расширяемым, чтобы он мог увеличиваться в соответствии с размером данных, которые вы получите (что заранее неизвестно). Чтобы избежать перезаписи уже сохраненных данных в наборе данных, вам нужно будет работать с выделениями (гиперслав или точка) при записи в него данных.

Одним из способов решения вашего варианта использования может быть использование HDFql на C следующим образом (обратите внимание, что в этом примере я просто добавляю две «строки» в набор данных — у вас может быть цикл, добавляющий столько «строк», сколько необходимо для решения того, что вы имеете в виду):

 #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(amp;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(amp;data);

    // close HDF5 file 'data.h5'
    hdfql_execute("close file");

    return 0;

}