1

我正在尝试将 2 遍、可分离的方法与基于积分图像的框过滤方法在 Halide 中的性能进行比较,以更好地理解 Halide 调度。我在 Halide 中找不到任何积分图像创建示例,其中积分图像函数用于后续函数的定义。

ImageParam input(type_of<uint8_t>(), 3, "image 1");

Var x("x"), y("y"), c("c"), xi("xi"), yi("yi");

Func ip("ip");

ip(x, y, c) = cast<float>(BoundaryConditions::repeat_edge(input)(x, y, c));

Param<int> radius("radius", 15, 1, 50);

RDom imageDomain(input);
RDom r(-radius, radius, -radius, radius);

// Make an integral image
Func integralImage = ip;
integralImage(x, imageDomain.y, c) += integralImage(x, imageDomain.y - 1, c);
integralImage(imageDomain.x, y, c) += integralImage(imageDomain.x - 1, y, c);

integralImage.compute_root(); // Come up with a better schedule for this

// Apply box filter to integral image
Func outputImage;

outputImage(x,y,c) = integralImage(x+radius,y+radius,c)
                + integralImage(x-radius,y-radius,c)
                - integralImage(x-radius,y+radius,c)
                - integralImage(x-radius,y+radius,c);

Expr normFactor = (2*radius+1) * (2*radius+1);
outputImage(x,y,c) = outputImage(x,y,c) / normFactor;
result(x,y,c) = cast<uint8_t>(outputImage(x,y,c));

result.parallel(y).vectorize(x,8)

我确实在测试中找到了以下代码:

https://github.com/halide/Halide/blob/master/test/correctness/multi_pass_reduction.cpp

但是这个例子使用realize将积分图像计算为一个固定域上的缓冲区,并且没有在后续函数的定义中消耗积分图像的定义作为函数。

当我运行这段代码时,我观察到:

  1. 积分图像的计算非常慢(将我的管道移动到 0 fps)
  2. 我得到一个不正确的答案。我觉得我一定是在某种程度上错误定义了我的整体形象

我还有一个相关的问题,在 Halide 的这种场景中,如何最好地安排积分图像的计算?

4

1 回答 1

1

我的问题在于我的积分图像的定义。如果我将实现更改为积分图像的标准单遍定义,我会得到预期的行为:

Func integralImage;
integralImage(x,y,c) = 0.0f; // Pure definition
integralImage(intImDom.x,intImDom.y,c) = ip(intImDom.x,intImDom.y,c)
                  + integralImage(intImDom.x-1,intImDom.y,c)
                  + integralImage(intImDom.x,intImDom.y-1,c)
                  - integralImage(intImDom.x-1,intImDom.y-1,c);

integralImage.compute_root();

关于在 Halide 中用于计算积分图像的最有效算法/时间表,我仍然有剩余的问题,但我将把它作为一个更具体的问题重新发布,因为我目前的帖子有点开放式。

顺便说一句,上面代码中的第二个问题是输入图像的填充没有正确处理。

于 2016-06-04T14:42:38.777 回答