2016-04-24 4 views
0

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

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

Любой может помочь или иметь такую ​​же проблему и знать ответ?

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

Наконец-то получилось! Мне нужно установить шаг на входном и выходном буфере в генераторе. Thx все за помощь :-)

Edit:

Я попробовал два способа:

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 * host to float_t * host, но я не думаю, что это хорошая идея.

Edit:

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

поколение функции АОТ:

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; 
} 

, к сожалению, Я получил сбой с сообщением:

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

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

+0

Привет и добро пожаловать! Не могли бы вы показать нам код, который вы пробовали? – rhughes

+0

Я пытался использовать buffer_t и normal Halide :: Image, но оба они используют uint8 not float data: int halideOperations (float data [], int size, int x, int y) { \t \t buffer_t input_buf = {0 }; \t \t input_buf.host = & data [0]; } или: \t \t Halide :: Image (Halide :: Type :: Float, x, y, 0, 0, data); –

+0

Спасибо. Не могли бы вы изменить свой вопрос, чтобы показать нам свой код? – rhughes

ответ

1

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

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

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

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

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 и просто нуждаетесь в типе cast для назначения хоста. Также не забудьте установить для поля 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); 

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

0

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

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; 
} 

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