Search code examples
c++variablesrangehalide

Variable Domain Reduction in Halide


Right now I'm trying to write some Halide code that subsamples an image. Basically I want every 2 by 2 square of the image to be reduced to one pixel that contains the maximum. A simple example would be transforming

1 2 3 4
5 6 7 8
9 0 1 2
4 3 5 6

into

6 8
9 6

Right now I'm trying something along the lines of (I'm aware that this would give the sum instead of the maximum, but it's a toy example of the same process):

Halide::Image<uint8_t> input = load<uint8_t>("test.png");        
Halide::Image<uint8_t> output(input.width() / 2, input.height() / 2, input.channels());

 Halide::Func subsample;
 Halide::Var c;

 for (int i = 0; i < input.height(); i += 2) {
     for (int j = 0; j < input.width(); j += 2) {
         Halide::RDom r = Halide::RDom(i, 2, j, 2);
         subsample(i, j, c) += input(r.x, r.y, c);
     }
 }

 subsample.realize(output);
 save(output, "test.png");

However, this code runs infinitely. (I'm not sure why). I know I can use Halide::RDom to represent a reduce operation over some range. However, in no example I find can you pass a variable into a random domain object.

EDIT:

After playing around with Halide some more, I was able to construct this:

subsample(x, y, c) = Halide::max(input(2*x,2*y,c),input(2*x+1,2*y,c));
subsample(x, y, c) = Halide::max(subsample(x,y,c),input(2*x,2*y+1,c));
subsample(x, y, c) = Halide::max(subsample(x,y,c),input(2*x+1,2*y+1,c));

To get a 2x2 max reduction. However, when I put this in a loop, it won't call because it cannot be defined. Is there anyway to put this in terms of a domain reduction?


Solution

  • After looking more into Halide, I realized I could get what I wanted with this:

    Halide::Func subsample;
    Halide::Var x, y, c;
    
    Halide::RDom r(0, size, 0, size);
    
    subsample(x, y, c) = input(size * x, size * y, c);
    subsample(x, y, c) = Halide::max(input(size*x + r.x, size*y + r.y, c), 
        subsample(x,y,c));