gpt4 book ai didi

c++ - Halide:转换 RGB 图像和平行化模糊

转载 作者:行者123 更新时间:2023-11-30 03:44:36 27 4
gpt4 key购买 nike

以下代码改编自 Halide 教程。

Func blurX(Func continuation)
{ Var x("x"), y("y"), c("c");
Func input_16("input_16");
input_16(x, y, c) = cast<uint16_t>(continuation(x, y, c));
Func blur_x("blur_x");
blur_x(x, y, c) = (input_16(x-1, y, c) +
2 * input_16(x, y, c) +
input_16(x+1, y, c)) / 4;
Func output("outputBlurX");
output(x, y, c) = cast<uint8_t>(blur_x(x, y, c));
return output;
}

int main()
{ Var x("x"), y("y"), c("c");
Image<uint8_t> input = load_image("input.png");
Func clamped("clamped");
clamped = BoundaryConditions::repeat_edge(input);
Func img1Fun("img1Fun");
Func img2Fun = blurX(clamped);
Func outputFun("outputFun");
/* carry on */
}

我有三个问题:

  1. Casting 是 Actor cast<uint16_t>(clamped(x, y, c))将每个 (x,y) 位置的 8 位 R G 和 B 值转换为 16 位整数,即转换返回的是可以索引的 RGB 图像,例如 img1Fun(x, y, 0) 以访问其 R 值?或者这是将图像中的每个 RGB 像素转换到每个 (x,y) 位置的 RGB 像素的 [0..1] 之间的亮度值,即 r*0.3 + g*0.59 + b*0.11 ?

  2. 重载 RGB 模糊是对 (x,y,c) 的算术运算所有索引重载?例如

(input_16(x-1, y, c) + 2 * input_16(x, y, c) + input_16(x+1, y, c)) / 4; 

这是一个重载:

(input_16(x-1, y, 0) + 2 * input_16(x, y, 0) + input_16(x+1, y, 0)) / 4;
(input_16(x-1, y, 1) + 2 * input_16(x, y, 1) + input_16(x+1, y, 1)) / 4;
(input_16(x-1, y, 2) + 2 * input_16(x, y, 2) + input_16(x+1, y, 2)) / 4;
  1. 并行化 我如何并行化 blurX ?基于brighten.cpp来自 CVPR'15 的示例 here , 我可以使用 blur_x.vectorize(x, 4).parallel(y);在 X 方向逐行矢量化,在 Y 方向平行化线程……像这样吗?
Func blurX(Func continuation)
{ Var x("x"), y("y"), c("c");
Func input_16("input_16");
input_16(x, y, c) = cast<uint16_t>(continuation(x, y, c));
Func blur_x("blur_x");
blur_x(x, y, c) = (input_16(x-1, y, c) +
2 * input_16(x, y, c) +
input_16(x+1, y, c)) / 4;
blur_x.vectorize(x, 4).parallel(y);
Func output("outputBlurX");
output(x, y, c) = cast<uint8_t>(blur_x(x, y, c));
return output;
}

最佳答案

问题 1:Func 定义了从一组坐标到 Expr 的抽象映射,它是这些坐标的数学函数。一般来说,运算符是直接的,没有任何成像特定行为,如将颜色元组转换为光度标量。 (要完成这样的转换,必须编写代码,因为系数取决于所使用的颜色空间。)

因此声明:

img1Fun(x, y, c) = cast<uint16_t>(clamped(x, y, c));

input_16 定义为具有与 clamped 相同的 channel 数,但为 16 位类型而不是 8 位类型。 Halide 中的算术与其最大操作数保持相同的位宽,并且与 C 不同,它不会隐式转换为标准 int 大小。这是因为对于矢量化,保持对 channel 大小的明确控制很重要。在这种情况下,需要使用 16 位中间类型以避免在对 8 位值求和时溢出。

除法后有相应的转换回 8 位类型。模糊结果保证适合 8 位类型,因为计算是标准化的(给定颜色 channel 在整个图像上的平均值不应改变)。上面的代码在两个地方同时进行了向上转型和向下转型,这是多余的。它可能不会对性能产生任何影响,因为编译器应该足够聪明,可以识别出外部转换集是 nop,但它不会产生特别可读的代码。

问题 2:实际上是相同的答案。我不会在这里使用术语“重载”,但该定义适用于所有坐标。 Var "c"在左手边和右手边提到,并且每个都有相同的值。 (我们有一个速记下划线 ('_') 表示法表示“零个或多个坐标”以允许通过参数列表,但除此之外这些定义没有什么特别之处。)

问题 3:为此进行矢量化和并行化安排的最简单方法是使用平面布局(所有 R 值彼此相邻存储,然后是所有 G 等)并将矢量化为 16 的适当大小-位数学。 (例如,“vectorize(x, natural_vector_size())”id 在生成器内部工作。)沿行的线程并行性——“.parallel(y)”。根据行的长度,您可能希望向并行指令添加拆分参数。

此时间表也适用于半平面表示(一行 R、一行 G 和一行 B)。

当在实际管道的上下文中使用 blurX 或者需要非平面存储布局时,还有其他方法可能更有意义。

关于c++ - Halide:转换 RGB 图像和平行化模糊,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35352279/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com