使用场景
在图像视觉预处理中,**双线性插值(Bilinear Interpolation)**常用于图像缩小、分辨率统一和数据预处理等场景。该算法通过对目标像素邻域的 4 个像素进行加权计算,实现平滑的几何缩放,相比最近邻插值能够有效降低锯齿和像素块效应。在目标检测、图像分类、OCR 以及 AI 推理等视觉系统中,常用于将不同分辨率的输入图像统一缩放到网络所需尺寸(如 224×224、640×640 等),为后续特征提取和模型推理提供标准化输入。虽然其缩小时的抗混叠能力不如 Area 插值,但由于计算量适中、硬件实现简单、适合流水线处理,因此被广泛应用于 FPGA、ISP 和边缘视觉设备的实时图像预处理环节。
原理

双线性插值是一种基于邻域 4 个像素点的加权平均算法。对于目标图像中的某个像素,先根据缩放比例反向映射到原图中的浮点坐标位置,然后找到其周围的 4 个相邻像素点 Q00、Q01、Q10、Q11。算法先在水平方向根据小数部分 fx 计算上、下两行的中间值,再在垂直方向根据 fy 对这两个中间值进行加权,最终得到目标像素值。相比最近邻插值,双线性插值能够让图像缩放结果更加平滑,因此常用于图像视觉预处理中的尺寸归一化、分辨率转换和 FPGA 实时图像缩放。
FPGA实现

在 FPGA 中,双线性插值通常采用流水线结构实现,以满足视频流的实时处理需求。对于输出图像中的每个像素,首先通过缩放比例反向映射得到原图中的浮点坐标 (src_x, src_y),然后取其周围的 4 个邻近像素 Q00、Q01、Q10、Q11。FPGA 利用行缓存(Line Buffer)保存图像数据,并根据坐标计算得到水平和垂直方向的小数权重 fx、fy。
计算过程一般分为两级流水:
第一级(水平方向插值)
top = (1-fx)·Q00 + fx·Q01
bot = (1-fx)·Q10 + fx·Q11
第二级(垂直方向插值)
P = (1-fy)·top + fy·bot
这样仅需访问 4 个像素点即可完成一个输出像素的计算,非常适合 FPGA 的并行乘加(DSP)资源实现。该方法计算复杂度低、硬件资源可控,广泛应用于图像视觉预处理、分辨率转换、视频缩放、目标检测和 AI 推理前的数据尺寸归一化等场景。对于实时视频系统(如 HDMI、MIPI Camera、工业相机等),双线性插值通常能够在图像质量和硬件资源之间取得良好的平衡。具体实现代码如下,接口为AXI4-streaming接口,可以实现任意比例的缩小。计算输出的模块如下,默认result和输入有2拍延时。
module calculate(
input clk,
input aresetn,
input [23:0] q00,
input [23:0] q01,
input [23:0] q10,
input [23:0] q11,
input [7:0] fx,
input [7:0] fy,
output [23:0] result
);
reg [15:0] top_r,bot_r,top_g,bot_g,top_b,bot_b;
reg [23:0] r_R,r_G,r_B;
always @(posedge clk or negedge aresetn) begin
if(~aresetn)begin
top_r <= 0;
bot_r <= 0;
top_g <= 0;
bot_g <= 0;
top_b <= 0;
bot_b <= 0;
end else begin
top_r <= (256 – fx)*q00[23:16] + fx * q01[23:16];
bot_r <= (256 – fx)*q10[23:16] + fx * q11[23:16];
top_g <= (256 – fx)*q00[15:8] + fx * q01[15:8];
bot_g <= (256 – fx)*q10[15:8] + fx * q11[15:8];
top_b <= (256 – fx)*q00[7:0] + fx * q01[7:0];
bot_b <= (256 – fx)*q10[7:0] + fx * q11[7:0];
end
end
always @(posedge clk or negedge aresetn) begin
if(~aresetn)begin
r_R <= 0;
r_G <= 0;
r_B <= 0;
end else begin
r_R <= (256 – fy)*top_r + fy * bot_r;
r_G <= (256 – fy)*top_g + fy * bot_g;
r_B <= (256 – fy)*top_b + fy * bot_b;
end
end
assign result = {r_R[23:16],r_G[23:16],r_B[23:16]};
endmodule
仿真结果
仿真的tb代码如下
@cocotb.test()
async def tb_inter(dut):
ori_img = load_img(IMG_PATH)
gold_ref = golden_ref(ori_img)
h, w, c = ori_img.shape
if channel == 3:
out_buf = np.zeros((64, 64, 3), dtype=np.uint8)
elif channel == 1:
out_buf = np.zeros((64, 64), dtype=np.uint8)
#sim begin
await init_sys(dut,10)
await Timer(200,units="ns")
#启动接收图像
cocotb.start_soon(maxis_switch(dut))
recv_task = cocotb.start_soon(recv_gray_task(dut, 64, 64, out_buf,channel))
await load_img_2_dut(dut,ori_img)
await recv_task
await Timer(20000,units="ns")
if COMPARE_RESULT_ON:
compare_result(gold_ref,out_buf)
else:
pass
512×512缩小为200×200的仿真的结果如下


本设计基于 Verilog 完成双线性插值硬件流水线实现,将 FPGA 并行插值运算输出图像与 OpenCV-Python cv2 标准双线性插值算法结果逐像素比对,二者像素数值高度吻合,图像整体纹理、边缘缩放过渡效果几乎无肉眼可见差异,验证了该硬件插值架构算法逻辑准确、计算精度与软件标准算法对齐,可满足实时图像缩放场景的精度需求。



