Sobel边缘检测-FPGA
Sobel边缘检测
// sobel 算法 `timescale 1ns/1ns module sobel_top( clk , rst_n , pre_vs , pre_hs , pre_en , pre_img_Y , post_vs , post_hs , post_en , post_img_Y ); /************************** input and output ******************/ input clk ; input rst_n ; input pre_vs ; input pre_hs ; input pre_en ; input [7:0] pre_img_Y ; output post_vs ; output post_hs ; output post_en ; output [7:0] post_img_Y ; /************************* main code **************************/ wire [7:0] matrixp11 ; wire [7:0] matrixp12 ; wire [7:0] matrixp13 ; wire [7:0] matrixp21 ; wire [7:0] matrixp22 ; wire [7:0] matrixp23 ; wire [7:0] matrixp31 ; wire [7:0] matrixp32 ; wire [7:0] matrixp33 ; wire matrix_vs ; wire matrix_hs ; wire matrix_en ; Generate_Matrix_3x3_8bit Generate_Matrix_3x3_8bit( //system .clk (clk ), //鍍忕礌鏃堕挓鐨勫悓姝ワ紝coms_clk , vga_clk .rst_n (rst_n ), //澶嶄綅淇″彿 //coms or vga .pre_vs (pre_vs ), //鍓嶈鍚屾 .pre_hs (pre_hs ), //鍓嶅満鍚屾 .pre_en (pre_en ), //鍓嶆暟鎹湁鏁 .pre_img_Y (pre_img_Y ), //鏁版嵁鐏板害鍥惧儚 .matrixp11 (matrixp11 ), .matrixp12 (matrixp12 ), .matrixp13 (matrixp13 ), .matrixp21 (matrixp21 ), .matrixp22 (matrixp22 ), .matrixp23 (matrixp23 ), .matrixp31 (matrixp31 ), .matrixp32 (matrixp32 ), .matrixp33 (matrixp33 ), .matrix_vs (matrix_vs ), .matrix_hs (matrix_hs ), .matrix_en (matrix_en ) ); //消耗4个时钟 wire [7:0] sobel_data; sobel sobel( .clk (clk ), .rst_n (rst_n ), .Soble_Threshold(8'd15 ), .matrixp11 (matrixp11 ), .matrixp12 (matrixp12 ), .matrixp13 (matrixp13 ), .matrixp21 (matrixp21 ), .matrixp22 (matrixp22 ), .matrixp23 (matrixp23 ), .matrixp31 (matrixp31 ), .matrixp32 (matrixp32 ), .matrixp33 (matrixp33 ), .sobel_data (sobel_data ) ); //延迟4个时钟 reg [3:0] matrix_vs_r; reg [3:0] matrix_hs_r; reg [3:0] matrix_en_r; always@(posedge clk or negedge rst_n) begin if(!rst_n) begin matrix_vs_r <= 'd0; matrix_hs_r <= 'd0; matrix_en_r <= 'd0; end else begin matrix_vs_r <= {matrix_vs_r[2:0],matrix_vs}; matrix_hs_r <= {matrix_hs_r[2:0],matrix_hs}; matrix_en_r <= {matrix_en_r[2:0],matrix_en}; end end assign post_vs = matrix_vs_r[3]; assign post_hs = matrix_hs_r[3]; assign post_en = matrix_en_r[3]; assign post_img_Y = post_en ? sobel_data : 8'd0; endmodule
//sobel边缘检测算法 /* [ -1 0 +1 ] [ +1 +2 +1 ] Gx = [ -2 0 +2 ]*A Gy = [ 0 0 0 ] * A [ -1 0 +1 ] [ -1 -2 -1 ] G = sqrt(Gx^2 + Gy^2); G = |Gx| + |Gy| ; */ module sobel ( clk , rst_n , Soble_Threshold, //阈值的选取,可以做一个按键调节 matrixp11 , matrixp12 , matrixp13 , matrixp21 , matrixp22 , matrixp23 , matrixp31 , matrixp32 , matrixp33 , sobel_data ); //************************ input and output *******************// input clk; input rst_n; input [7:0] Soble_Threshold; input [7:0] matrixp11 ; input [7:0] matrixp12 ; input [7:0] matrixp13 ; input [7:0] matrixp21 ; input [7:0] matrixp22 ; input [7:0] matrixp23 ; input [7:0] matrixp31 ; input [7:0] matrixp32 ; input [7:0] matrixp33 ; output reg [7:0] sobel_data; //************************ main code **************************// // [ -1 0 +1 ] [ +1 +2 +1 ] //Gx = [ -2 0 +2 ]*A Gy = [ 0 0 0 ] * A // [ -1 0 +1 ] [ -1 -2 -1 ] // matrixp11*(-1)+matrixp12*(0)+matrixp13*(1), //Gx matrixp21*(-2)+matrixp22*(0)+matrixp23*(2), // matrixp31*(1)+matrixp32*(0) +matrixp33*(1), // matrixp11*(1)+matrixp12*(2)+matrixp13*(1), //Gy matrixp21*(0)+matrixp22*(0)+matrixp23*(0), // matrixp31*(-1)+matrixp32*(-2)+matrixp33*(-1), reg [11:0] Gx_data_col1; reg [11:0] Gx_data_col3; reg [11:0] Gy_data_row1; reg [11:0] Gy_data_row3; //求卷积 第一步 always@(posedge clk or negedge rst_n) begin if(!rst_n) begin Gx_data_col1 <= 'd0; Gx_data_col3 <= 'd0; end else begin Gx_data_col1 <= matrixp11 + (matrixp21 << 1) + matrixp31; Gx_data_col3 <= matrixp13 + (matrixp23 << 1) + matrixp33; end end always@(posedge clk or negedge rst_n) begin if(!rst_n) begin Gy_data_row1 <= 'd0; Gy_data_row3 <= 'd0; end else begin Gy_data_row1 <= matrixp11 + (matrixp12 << 1) + matrixp13; Gy_data_row3 <= matrixp31 + (matrixp32 << 1) + matrixp33; end end //判断大小 第二步 reg [11:0] Gx_data; reg [11:0] Gy_data; always@(posedge clk or negedge rst_n) begin if(!rst_n) Gx_data <= 'd0; else if(Gx_data_col1 >= Gx_data_col3) Gx_data <= Gx_data_col1 - Gx_data_col3; else Gx_data <= Gx_data_col3 - Gx_data_col1; end always@(posedge clk or negedge rst_n) begin if(!rst_n) Gy_data <= 'd0; else if(Gy_data_row1 >= Gy_data_row3) Gy_data <= Gy_data_row1 - Gy_data_row3; else Gy_data <= Gy_data_row3 - Gy_data_row1; end //第三步 求平方 reg [20:0] sum_data; always@(posedge clk or negedge rst_n) begin if(!rst_n) sum_data <= 'd0; else sum_data <= Gx_data*Gx_data + Gy_data*Gy_data; end //第四步 开方 wire [10:0] q; sqrt sqrt( .radical (sum_data), .q (q), .remainder () ); //第五步 取阈值 //White: 24'hFF; Black: 24'h00 //实际情况大于Soble_Threshold为黑色,在后期处理需要注意 always@(posedge clk or negedge rst_n) begin if(!rst_n) sobel_data <= 'd0; else if(q >= Soble_Threshold) sobel_data <= 8'd255; else sobel_data <= 8'd0; end endmodule
`timescale 1ns/1ns module sobel_top_tb; //system reg clk ; //像素时钟的同步,coms_clk , vga_clk reg rst_n ; //复位信号 //coms or vga reg pre_vs ; //前行同步 reg pre_hs ; //前场同步 reg pre_en ; //前数据有效 reg [7:0] pre_img_Y ; //数据灰度图像 wire post_vs ; //输出行同步 wire post_hs ; //输出场同步 wire post_en ; //输出数据有效 wire [7:0] post_img_Y ; //输出数据灰度图像 initial clk = 1; always #5 clk = ~clk; initial begin rst_n = 0; pre_vs =0 ; pre_hs = 0; pre_en = 0; pre_img_Y = 0; #51; rst_n = 1; pre_vs = 1; #20; pre_hs = 1; #20; pre_en = 1; #60; pre_en = 0; #20; pre_hs = 0; #20; pre_hs = 1; #20; pre_en = 1; #60; pre_en = 0; #20; pre_hs = 0; #20; pre_hs = 1; #20; pre_en = 1; #60; pre_en = 0; #20; pre_hs = 0; #20; pre_hs = 1; #20; pre_en = 1; #60; pre_en = 0; #20; pre_hs = 0; #20; pre_hs = 1; #20; pre_en = 1; #60; pre_en = 0; #20; pre_hs = 0; $stop; end reg [7:0] shiftin; always@(posedge clk or negedge rst_n ) begin if(!rst_n) shiftin <= 'd1; else if(pre_en) shiftin <= shiftin + 1'b1; else shiftin <= shiftin; end sobel_top sobel_top( //system .clk (clk ), //像素时钟的同步,coms_clk , vga_clk .rst_n (rst_n ), //复位信号 //coms or vga .pre_vs (pre_vs ), //前行同步 .pre_hs (pre_hs ), //前场同步 .pre_en (pre_en ), //前数据有效 .pre_img_Y (shiftin ), //数据灰度图像 //output .post_vs (post_vs ), //输出行同步 .post_hs (post_hs ), //输出场同步 .post_en (post_en ), //输出数据有效 .post_img_Y (post_img_Y ) //输出数据灰度图像 ); endmodule
还有一个开方ip核