如何用Halide的BoundaryConditions实现图像对称镜像扩展?
Halide实现图像四边镜像对称扩展的正确方式
问题根源
你之前的代码错误理解了BoundaryConditions::mirror_image的参数含义:该函数的第二个参数bounds是输入Func的有效像素区域,而非输出图像的区域。你传入了包含负起始的输出范围,导致输入被错误限定了有效区域,超出原始输入尺寸的部分(右侧、底部)因无有效像素返回黑边。
标准库实现方案(推荐)
完全可以通过Halide的BoundaryConditions::mirror_image实现需求,无需手动编写复杂逻辑。核心思路是:先用mirror_image包裹输入Func,让它支持对超出原始区域的坐标自动返回镜像像素;再定义输出Func,将输出坐标映射到输入的偏移坐标(抵消扩展的padding)。
示例代码:
int pad = 10; // 四边各扩展10像素 int input_w = input.width(); int input_h = input.height(); int output_w = input_w + 2 * pad; int output_h = input_h + 2 * pad; // 用mirror_image包裹输入,自动处理超出原始区域的镜像访问 Func mirrored_input = Halide::BoundaryConditions::mirror_image(input); // 定义输出Func,覆盖扩展后的完整区域 Func output; Var x, y, c; // 将输出坐标偏移pad,映射到输入的镜像扩展区域 output(x, y, c) = mirrored_input(x - pad, y - pad, c);
原理说明
- 当输出坐标
x=0时,x-pad=-10,mirror_image会自动将该坐标镜像到input_w - 1 - 9 = input_w -10(镜像从边界开始反转),实现左侧的对称扩展; - 当输出坐标
x=output_w-1时,x-pad=input_w + 10 -1 = input_w +9,mirror_image会镜像到input_w -1 -9 = input_w-10,实现右侧的对称扩展; - 上下方向的镜像逻辑同理。
手动实现方案(可选)
如果需要自定义镜像逻辑,也可以手动对坐标进行映射:
int pad = 10; int input_w = input.width(); int input_h = input.height(); int output_w = input_w + 2 * pad; int output_h = input_h + 2 * pad; Func output; Var x, y, c; // 计算x方向的镜像映射坐标 Expr input_x = x - pad; input_x = select( input_x < 0, -input_x - 1, input_x >= input_w, 2 * (input_w - 1) - input_x, input_x ); // 计算y方向的镜像映射坐标 Expr input_y = y - pad; input_y = select( input_y < 0, -input_y - 1, input_y >= input_h, 2 * (input_h - 1) - input_y, input_y ); output(x, y, c) = input(input_x, input_y, c);
内容的提问来源于stack exchange,提问作者Louis Child
相关产品推荐
相关产品推荐

