Использование галогенидов с изображениями HDR, представленными в виде массива с плавающей запятой

это мой первый пост, извините, если я что-то не так делаю :). Я постараюсь сделать все возможное.

В настоящее время я работаю над своей программой обработки изображений HDR, и я собираюсь внедрить некоторые базовые TMO, используя Halide. Проблема в том, что все мои изображения представлены в виде массива с плавающей точкой (в следующем порядке: b1, g1, r1, a1, b2, g2, r2, a2, …). Использование Halide для обработки изображения требует класса Halide :: Image. Проблема в том, что я не знаю, как передать эти данные туда.

Кто-нибудь может помочь, или есть такая же проблема и знать ответ?

Редактировать:

Наконец то понял! Мне нужно установить шаг на входе и выходе буфера в генераторе. Спасибо всем за помощь 🙂

Редактировать:

Я пробовал два разных способа:

int halideOperations( float data[] , int size, int width,int heighy )
{
buffer_t input_buf = { 0 };
input_buf.host = &data[0];
}

или же:

int halideOperations( float data[] , int size, int width,int heighy )
{
Halide::Image(Halide::Type::Float, x, y, 0, 0, data);
}

Я думал о редактировании файла Halide.h и изменении хоста uint8_t * на хост float_t *, но я не думаю, что это хорошая идея.

Редактировать:

Я попытался использовать код ниже с моим плавающим изображением (RGBA):

Генерация функции AOT:

int main(int arg, char ** argv)
{
Halide::ImageParam img(Halide::type_of<float>(), 3);
Halide::Func f;
Halide::Var x, y, c;
f(x, y, c) = Halide::pow(img(x,y,c), 2.f);

std::vector<Halide::Argument> arguments = { img };
f.compile_to_file("function", arguments);
return 0;
}

Правильный код вызова:

int halideOperations(float data[], int size, int width, int height)
{
buffer_t  output_buf = { 0 };
buffer_t buf = { 0 };
buf.host = (uint8_t *)data;
float * output = new float[width * height * 4];
output_buf.host = (uint8_t*)(output);
output_buf.extent[0] = buf.extent[0] = width;
output_buf.extent[1] = buf.extent[1] = height;
output_buf.extent[2] = buf.extent[2] = 4;
output_buf.stride[0] = buf.stride[0] = 4;
output_buf.stride[1] = buf.stride[1] = width * 4;
output_buf.elem_size = buf.elem_size = sizeof(float);

function(&buf, &output_buf);

delete output;
return 1;
}

к сожалению, я получил сбой с MSG:

 Error: Constraint violated: f0.stride.0 (4) == 1 (1)

Я думаю, что-то не так с этой строкой: output_buf.stride [0] = buf.stride [0] = 4, но я не уверен, что я должен изменить. Какие-нибудь советы?

0

Решение

Если вы используете buffer_t напрямую, вы должны привести указатель, присвоенный хосту, к uint8_t *:

buf.host = (uint8_t *)&data[0]; // Often, can be just "(uint8_t *)data"

Это то, что вы хотите сделать, если вы используете компиляцию Ahead-Of-Time (AOT) и данные не выделяются как часть кода, который напрямую вызывает Halide. (Другие методы, обсуждаемые ниже, управляют распределением памяти, поэтому они не могут получить указатель, который им передается.)

Если вы используете либо Halide :: Image, либо Halide :: Tools :: Image, тогда приведение типов выполняется внутренне. Использованный выше конструктор для Halide :: Image не существует, поскольку Halide :: Image является классом шаблона, где базовый тип данных является параметром шаблона:

Halide::Image<float> image_storage(width, height, channels);

Обратите внимание, что это будет хранить данные в планарной компоновке. Halide :: Tools :: Image похож, но имеет возможность сделать чередующийся макет. (Лично я стараюсь не использовать ни одну из этих программ за пределами небольших тестовых программ. Существует долгосрочный план рационализации всего этого, который будет продолжаться после объединения ветки buffer_t произвольного измерения. Обратите внимание также на Halide :: Image требует libHalide.a быть связанными там, где Halide :: Tools :: Image не имеет и является заголовочным файлом только с помощью common / halide_image.h.)

Существует также класс Halide :: Buffer, который является оберткой для buffer_t, который полезен при компиляции Just-In-Time (JIT). Ссылка может быть передана в хранилище и не является шаблонной. Однако я предполагаю, что вы хотите использовать buffer_t напрямую и просто нуждаетесь в приведении типа для назначения хоста. Также убедитесь, что для поля elem_size buffer_t установлено значение «sizeof (float)».

Для чередующегося плавающего буфера вы получите что-то вроде:

buffer_t buf = {0};
buf.host = (uint8_t *)float_data; // Might also need const_cast
// If the buffer doesn't start at (0, 0), then assign mins
buf.extent[0] = width; // In elements, not bytes
buf.extent[1] = height; // In elements, not bytes
buf.extent[2] = 3; // Assuming RGB
// No need to assign additional extents as they were init'ed to zero above
buf.stride[0] = 3; // RGB interleaved
buf.stride[1] = width * 3; // Assuming no line padding
buf.stride[2] = 1; // Channel interleaved
buf.elem_size = sizeof(float);

Вам также нужно будет обратить внимание на границы в самом коде Halide. Вероятно, лучше всего посмотреть на set_stride и связанные вызовы в tutorial / lesson_16_rgb_generate.cpp для получения информации об этом.

1

Другие решения

В дополнение к ответу Залмана выше, вы также должны указать шаги для входов и выходов при определении вашей функции Halide, как показано ниже:

int main(int arg, char ** argv)
{
Halide::ImageParam img(Halide::type_of<float>(), 3);
Halide::Func f;
Halide::Var x, y, c;
f(x, y, c) = Halide::pow(img(x,y,c), 2.f);

// You need the following
f.set_stride(0, f.output_buffer().extent(2));
f.set_stride(1, f.output_buffer().extent(0) * f.output_buffer().extent(2));
img.set_stride(0, img.extent(2));
img.set_stride(1, img.extent(2) *img.extent(0));
// <- up to here

std::vector<Halide::Argument> arguments = { img };
f.compile_to_file("function", arguments);
return 0;
}

тогда ваш код должен работать.

0

По вопросам рекламы [email protected]