-
-
Save sschnug/c8eeaf5cd81eb1ec04220fb36bb202c7 to your computer and use it in GitHub Desktop.
#include "Halide.h" | |
#include "Halide/tools/halide_image_io.h" | |
#include <iostream> | |
// 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<uint8_t> 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<uint32_t>(tiled_f(tile_dom.x, tile_dom.y, xo, yo))) / (tile_size_x * tile_size_y); | |
Halide::Func output; | |
output(xo, yo) = Halide::cast<uint8_t>(tile_means(xo, yo)); | |
Halide::Buffer<uint8_t> output_(2, 2); | |
output.realize(output_); | |
Halide::Tools::save_image(output_, "block_based_stuff.png"); | |
} |
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.
@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.
@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<true, Halide::FuncRef>::type, uint16_t&)’ Internal::convert(im(x, y, c), value);
which indicates some other problem before that)