(六)FPGA-二次线性插值缩小

📅 2026/7/13 21:34:24
(六)FPGA-二次线性插值缩小
使用场景在图像视觉预处理中**双线性插值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·Q01bot (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), dtypenp.uint8) elif channel 1: out_buf np.zeros((64, 64), dtypenp.uint8) #sim begin await init_sys(dut,10) await Timer(200,unitsns) #启动接收图像 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,unitsns) if COMPARE_RESULT_ON: compare_result(gold_ref,out_buf) else: pass512x512缩小为200x200的仿真的结果如下上板验证下图1080P转1024x512实测效果。本设计基于 Verilog 完成双线性插值硬件流水线实现将 FPGA 并行插值运算输出图像与 OpenCV-Python cv2 标准双线性插值算法结果逐像素比对二者像素数值高度吻合图像整体纹理、边缘缩放过渡效果几乎无肉眼可见差异验证了该硬件插值架构算法逻辑准确、计算精度与软件标准算法对齐可满足实时图像缩放场景的精度需求。