halide / Halide

a language for fast, portable data-parallel computation
https://halide-lang.org
Other
5.9k stars 1.07k forks source link

Result image must has the same dimensions with the input image? (with repeat_edge condition) #2875

Open LoveDaisy opened 6 years ago

LoveDaisy commented 6 years ago

I'm not sure whether I am wrong, but when I simply try to reduce an image to 1/4 of its size, and I wrote my naive codes as follows:

class Reduction : public Halide::Generator<Reduction> {
public:
    Input<Buffer<uint8_t>>  input{"input", 3};
    Output<Buffer<uint8_t>> output{"output", 3};

    Var x, y, c;
    Func img1{"img1"};

    void generate() {
        Func imgRep = Halide::BoundaryConditions::repeat_edge(input,
            {{input.dim(0).min(), input.dim(0).extent()},
             {input.dim(1).min(), input.dim(1).extent()}});
        int hw = 4;
        output(x, y, c) = imgRep(x*hw, y*hw, c);
    }

    void schedule() {
        if (auto_schedule) {
            input.dim(0).set_bounds_estimate(0, 720);
            input.dim(1).set_bounds_estimate(0, 1280);
            input.dim(2).set_bounds_estimate(0, 3);

            output.estimate(x, 0, 180).estimate(y, 0, 320).estimate(c, 0, 3); 
        } else {
            // TODO Maybe I should make schedule manually?
        }
    }
};

What I expect is a small image whose dimensions are 1/4 of the original. However what I actually get is a SAME SIZE image, with a small thumbnail (what I want) at top-left corner and repeated edge color filling the rest area.

Well it is not a severe problem when the original image is small, but when image is large, it will cost too much memory and computation time, especially when there are successive complex computations on the small image.

Any suggestions for this? Is it a designed feature or just my mistake? The result image must has the same dimension with input image? Is there any solution for reducing image size?

LoveDaisy commented 6 years ago

Actually the thumbnail image is an internal result used in my complex processing, and my final processed image is the same size of input. i.e. large input image --> small internal image --> large final image. Somehow when I use codes like shown above, it crashes and says it needs too much memory.

abadams commented 6 years ago

The size of the output image isn't specified by the generator above - it depends on how you call it. Halide computes values to fill whatever buffer you pass in as the output. So you must be passing in a full size buffer.

LoveDaisy commented 6 years ago

@abadams Thanks for your reply. In my case, I want to divide image into tiles and match tiles between two images. I've worked out two ways dealing with it:

  1. point-wise matching

    RDom tile(-w, 2*w+1, -w, 2*w+1), search(-h, 2*h+1, -h, 2*h+1);
    diff(x, y, x1, y1) = sum(img1(x+tile.x, y+tile.y) - img2(x1+tile.x, y1+tile.y));
    output(x, y) = argmin(search, diff(x, y, x+search.x, y+search.y));  
    // output is the same size of img1 and img2
  2. tile-wise matching

    RDom tile(-w, 2*w+1, -w, 2*w+1), search(-h, 2*h+1, -h, 2*h+1);
    diff(x, y, x1, y1) = sum(img1(x+tile.x, y+tile.y) - img2(x1+tile.x, y1+tile.y));
    output(x, y) = argmin(search, diff(x*w, y*w, x*w+search.x, y*w+search.y));  
    // output has 1/w size of input image

But in my case, method 2 is a little slower than method 1, which is beyond my knowledge for I thought the computation of method 2 is much fewer than method 1. That's why I guess the internal buffer (like diff here) must have the same size of input, and thus computation can not be reduced.