FPGA实现图像的二值形态学滤波:边界提取
轮廓是对物体形状的有力描述,对图像分析和识别十分有用。通过边界提取算法可以得到物体的边界轮廓。
二值图像的边界提取主要基于黑白区域的边界查找,和许多边界查找算法相比它适合于二值图像。
边界提取的算法比较简单,以黑色 0 作为背景,白色 1 作为提取。以 3x3 模板为例,9 个像素都为 0 或 1 时输出为 0,否则为 1 。如图所示:
一、FPGA实现
算法比较简单,直接上代码吧。
1 module Boundary 2 //========================< 端口 >========================================== 3 ( 4 input wire clk , 5 input wire rst_n , 6 //input --------------------------------------------- 7 input wire RGB_de , 8 input wire RGB_hsync , 9 input wire RGB_vsync , 10 input wire [15:0] RGB_data , 11 //output -------------------------------------------- 12 output wire boundary_de , 13 output wire boundary_hsync , 14 output wire boundary_vsync , 15 output reg [15:0] boundary_data 16 ); 17 //========================< 信号 >========================================== 18 //matrix_3x3 ---------------------------------------- 19 wire [15:0] matrix_11 ; 20 wire [15:0] matrix_12 ; 21 wire [15:0] matrix_13 ; 22 wire [15:0] matrix_21 ; 23 wire [15:0] matrix_22 ; 24 wire [15:0] matrix_23 ; 25 wire [15:0] matrix_31 ; 26 wire [15:0] matrix_32 ; 27 wire [15:0] matrix_33 ; 28 //同步 ---------------------------------------------- 29 reg [ 1:0] RGB_de_r ; 30 reg [ 1:0] RGB_hsync_r ; 31 reg [ 1:0] RGB_vsync_r ; 32 //========================================================================== 33 //== matrix_3x3,生成3x3矩阵,输入和使能需对齐,耗费1clk 34 //========================================================================== 35 //--------------------------------------------------- 矩阵顺序 36 // {matrix_11, matrix_12, matrix_13} 37 // {matrix_21, matrix_22, matrix_23} 38 // {matrix_31, matrix_32, matrix_33} 39 //--------------------------------------------------- 模块例化 40 matrix_3x3_16bit 41 #( 42 .COL (480 ), 43 .ROW (272 ) 44 ) 45 u_matrix_3x3_16bit 46 ( 47 .clk (clk ), 48 .rst_n (rst_n ), 49 .din_vld (RGB_de ), 50 .din (RGB_data ), 51 .matrix_11 (matrix_11 ), 52 .matrix_12 (matrix_12 ), 53 .matrix_13 (matrix_13 ), 54 .matrix_21 (matrix_21 ), 55 .matrix_22 (matrix_22 ), 56 .matrix_23 (matrix_23 ), 57 .matrix_31 (matrix_31 ), 58 .matrix_32 (matrix_32 ), 59 .matrix_33 (matrix_33 ) 60 ); 61 //========================================================================== 62 //== 边缘提取,耗费1clk 63 //========================================================================== 64 always @ (posedge clk or negedge rst_n)begin 65 if(!rst_n)begin 66 boundary_data <= 16'h0000; 67 end 68 else if((matrix_11 == 16'h0000) && (matrix_12 == 16'h0000) && (matrix_13 == 16'h0000) && 69 (matrix_21 == 16'h0000) && (matrix_22 == 16'h0000) && (matrix_23 == 16'h0000) && 70 (matrix_31 == 16'h0000) && (matrix_32 == 16'h0000) && (matrix_33 == 16'h0000) 71 ) begin 72 boundary_data <= 16'hffff; 73 end 74 else if((matrix_11 == 16'hffff) && (matrix_12 == 16'hffff) && (matrix_13 == 16'hffff) && 75 (matrix_21 == 16'hffff) && (matrix_22 == 16'hffff) && (matrix_23 == 16'hffff) && 76 (matrix_31 == 16'hffff) && (matrix_32 == 16'hffff) && (matrix_33 == 16'hffff) 77 ) begin 78 boundary_data <= 16'hffff; 79 end 80 else begin 81 boundary_data <= 16'h0000; 82 end 83 end 84 //========================================================================== 85 //== 信号同步 86 //========================================================================== 87 always @(posedge clk or negedge rst_n) begin 88 if(!rst_n) begin 89 RGB_de_r <= 2'b0; 90 RGB_hsync_r <= 2'b0; 91 RGB_vsync_r <= 2'b0; 92 end 93 else begin 94 RGB_de_r <= {RGB_de_r[0], RGB_de}; 95 RGB_hsync_r <= {RGB_hsync_r[0], RGB_hsync}; 96 RGB_vsync_r <= {RGB_vsync_r[0], RGB_vsync}; 97 end 98 end 99 100 assign boundary_de = RGB_de_r[1]; 101 assign boundary_hsync = RGB_hsync_r[1]; 102 assign boundary_vsync = RGB_vsync_r[1]; 103 104 105 106 endmodule
二、上板验证
输入找了张二值图片,如果没有二值图片,可以在边界提取前自己写一下阈值判断即可。
二值原图:
边界提取后:
由实验结果可知,边界提取成功,外部的白色和内部的黑色都变为了白色,只有边界处是黑色。
参考资料:[1] Opens Lee:FPGA开源工作室(公众号)