{{ message }}

Instantly share code, notes, and snippets.

# sschnug/halide.cpp

Last active Apr 17, 2018
 #include "Halide.h" #include "Halide/tools/halide_image_io.h" #include // This code calculates a block based mean on some a-priori known image-dimensions (1 uint8_t channel) // An example image to process: http://i.imgur.com/Eyo0Xvc.png // No customized scheduling within this code, but the SO-answer gives some recommendation! int main(int argc, char **argv) { Halide::Buffer input = Halide::Tools::load_image("TestImages/block_example.png"); // This is a simple example assumes an input of 64x128 std::cout << "dim 0: " << input.width() << std::endl; std::cout << "dim 1: " << input.height() << std::endl; // The "outer" (block) and "inner" (pixel) indices that describe a pixel in a tile. Halide::Var xo, yo, xi, yi, x, y; // The distance between the start of each tile in the input. int tile_stride_x = 32; int tile_stride_y = 64; int tile_size_x = 32; int tile_size_y = 64; Halide::Func tiled_f; tiled_f(xi, yi, xo, yo) = input(xo * tile_stride_x + xi, yo * tile_stride_y + yi); Halide::RDom tile_dom(0, tile_size_x, 0, tile_size_y); Halide::Func tile_means; tile_means(xo, yo) = sum(Halide::cast(tiled_f(tile_dom.x, tile_dom.y, xo, yo))) / (tile_size_x * tile_size_y); Halide::Func output; output(xo, yo) = Halide::cast(tile_means(xo, yo)); Halide::Buffer output_(2, 2); output.realize(output_); Halide::Tools::save_image(output_, "block_based_stuff.png"); }

### dsharletg commented Apr 18, 2017

 I think the problem in this code is actually just that the sum is overflowing, and the division is probably not helping either. Try changing line 27 to: ``````tile_means(xo, yo) = sum(cast(tiled_f(tile_dom.x, tile_dom.y, xo, yo))) / (tile_size_x * tile_size_y)); `````` (Note I also added parens around `tile_size_x * tile_size_y`, since it probably wasn't doing what you wanted before.) This will produce a uint16 sum instead of a uin8 sum. You'll need to change the output to uint16 as well, or cast the sum (after dividing by tile_size_x * tile_size_y) back to uint8.

### sschnug commented Apr 18, 2017 • edited

 @dsharletg Output is now row 0: 16, 0 row 1: 0, 16. Better, but still not what was expected (16, 64; 32, 48). I will have a look tomorrow about my block-constant logic. Thanks for the comment! (And casting before buffer-stuff results in a lot of compile-time errors while this worked for my other simple examples; `Halide/tools/halide_image_io.h:579:42: error: no matching function for call to ‘convert(std::enable_if::type, uint16_t&)’ Internal::convert(im(x, y, c), value);` which indicates some other problem before that)

### dsharletg commented Apr 18, 2017

 Sorry, I think it might still be overflowing. I did some boneheaded math when deciding uint16 was enough, but it's not: 32 * 64 > 256, which is the maximum number of pixels in a tile that you can have before overflowing a uint16 accumulator of uint8 values. You need to be accumulating into a uint32 result before dividing. The second error you mention I think is just happening probably because save_image doesn't support 16 bit buffers.

### sschnug commented Apr 18, 2017

 @dsharletg Amazing. Indeed the buffer should be uint8 before using Halide::Tools::save_image. And the cast-before-output is now working too (i don't know what went wrong before). Everything is fine now! Thanks for all your help! I will add this tiny example to my SO-question as edit based on your answer and mark it as accepted.