前言
软件版本 vivado:2020.1 Quartus:17.1
正文边缘检测需要用到的IP核在两款软件中是不一样的
因此,下面分别在两款软件中进行实现
一、在vivado中实现1.算法流程: 1)、将3×3的窗口和Gx、Gy分别相乘,Gx、Gy均已知 2)、将相乘得到的2个结果各自平方 3)、将平方得到的2个数相加 4)、将相加的结果放入求根的IP核猴子那个开根号 5)、开完根号后和阈值比较,大于阈值的部分置1
2.sobel算子
Gx:x方向的边缘 Gy:y方向的边缘 Pixel [ -1 0 +1 ] [ +1 +2 +1 ] [ P11 P12 P13 ] [ -2 0 +2 ] [ 0 0 0 ] [ P21 P22 P23 ] [ -1 0 +1 ] [ -1 -2 -1 ] [ P31 P32 P33 ]
`timescale 1ns / 1ps // // 1.算法流程: // 1)、将3×3的窗口和Gx、Gy分别相乘,Gx、Gy均已知 // 2)、将相乘得到的2个结果各自平方 // 3)、将平方得到的2个数相加 // 4)、将相加的结果放入求根的IP核猴子那个开根号 // 5)、开完根号后和阈值比较,大于阈值的部分置1 // // // `timescale 1ns/1ns module Sobel_Edge_Detector ( //global clock input clk, //cmos video pixel clock input rst_n, //global reset //Image data prepred to be processd input per_frame_vsync, //Prepared Image data vsync valid signal input per_frame_href, //Prepared Image data href vaild signal input per_frame_clken, //Prepared Image data output/capture enable clock input [7:0] per_img_Y, //Prepared Image brightness input //Image data has been processd output post_frame_vsync, //Processed Image data vsync valid signal output post_frame_href, //Processed Image data href vaild signal output post_frame_clken, //Processed Image data output/capture enable clock output post_img_Bit, //Processed Image Bit flag outout(1: Value, 0:inValid) //user interface input [7:0] Sobel_Threshold //Sobel Threshold for image edge detect ); //---------------------------------------------------- //Generate 8Bit 3X3 Matrix for Video Image Processor. //Image data has been processd wire matrix_frame_vsync; //Prepared Image data vsync valid signal wire matrix_frame_href; //Prepared Image data href vaild signal wire matrix_frame_clken; //Prepared Image data output/capture enable clock wire [7:0] matrix_p11, matrix_p12, matrix_p13; //3X3 Matrix output wire [7:0] matrix_p21, matrix_p22, matrix_p23; wire [7:0] matrix_p31, matrix_p32, matrix_p33; Shift_RAM_3X3 Shift_RAM_3X3_inst ( //global clock .clk (clk), //cmos video pixel clock .rst_n (rst_n), //global reset .per_frame_vsync (per_frame_vsync), //Prepared Image data vsync valid signal .per_frame_href (per_frame_href), //Prepared Image data href vaild signal .per_frame_clken (per_frame_clken), //Prepared Image data output/capture enable clock .per_img_Y (per_img_Y), //Prepared Image brightness input //Image data has been processd .matrix_frame_vsync (matrix_frame_vsync), //Prepared Image data vsync valid signal .matrix_frame_href (matrix_frame_href), //Prepared Image data href vaild signal .matrix_frame_clken (matrix_frame_clken), //Prepared Image data output/capture enable clock .matrix_p11(matrix_p11), .matrix_p12(matrix_p12), .matrix_p13(matrix_p13), //3X3 Matrix output .matrix_p21(matrix_p21), .matrix_p22(matrix_p22), .matrix_p23(matrix_p23), .matrix_p31(matrix_p31), .matrix_p32(matrix_p32), .matrix_p33(matrix_p33) ); //Sobel Parameter // Gx:x方向的边缘 Gy:y方向的边缘 Pixel // [ -1 0 +1 ] [ +1 +2 +1 ] [ P11 P12 P13 ] // [ -2 0 +2 ] [ 0 0 0 ] [ P21 P22 P23 ] // [ -1 0 +1 ] [ -1 -2 -1 ] [ P31 P32 P33 ] // localparam P11 = 8'd15, P12 = 8'd94, P13 = 8'd136; // localparam P21 = 8'd31, P22 = 8'd127, P23 = 8'd231; // localparam P31 = 8'd44, P32 = 8'd181, P33 = 8'd249; //Caculate horizontal Grade with |abs| //Step 1-2 reg [9:0] Gx_temp1; //postive result reg [9:0] Gx_temp2; //negetive result reg [9:0] Gx_data; //Horizontal grade data //======================================================================== //矩阵相乘 //======================================================================== always@(posedge clk or negedge rst_n)begin if(!rst_n) begin Gx_temp1 <= 0; Gx_temp2 <= 0; Gx_data <= 0; end else begin Gx_temp1 <= matrix_p13 + (matrix_p23 << 1) + matrix_p33; //postive result Gx_temp2 <= matrix_p11 + (matrix_p21 << 1) + matrix_p31; //negetive result Gx_data <= (Gx_temp1 >= Gx_temp2) ? Gx_temp1 - Gx_temp2 : Gx_temp2 - Gx_temp1; end end //--------------------------------------- //Caculate vertical Grade with |abs| //Step 1-2 reg [9:0] Gy_temp1; //postive result reg [9:0] Gy_temp2; //negetive result reg [9:0] Gy_data; //Vertical grade data always@(posedge clk or negedge rst_n)begin if(!rst_n) begin Gy_temp1 <= 0; Gy_temp2 <= 0; Gy_data <= 0; end else begin Gy_temp1 <= matrix_p11 + (matrix_p12 << 1) + matrix_p13; //postive result Gy_temp2 <= matrix_p31 + (matrix_p32 << 1) + matrix_p33; //negetive result Gy_data <= (Gy_temp1 >= Gy_temp2) ? Gy_temp1 - Gy_temp2 : Gy_temp2 - Gy_temp1; end end //=================================================================== //--------------------------------------- //Caculate the square of distance = (Gx^2 + Gy^2) //Step 3 reg [20:0] Gxy_square; always@(posedge clk or negedge rst_n)begin if(!rst_n) Gxy_square <= 0; else Gxy_square <= Gx_data * Gx_data + Gy_data * Gy_data; end //--------------------------------------- //Caculate the distance of P5 = (Gx^2 + Gy^2)^0.5 //Step 4 wire [15:0] result_root; Square_root Square_root_inst( .aclk(clk), // input wire aclk .s_axis_cartesian_tvalid(1'b1), // input wire s_axis_cartesian_tvalid .s_axis_cartesian_tdata({3'b0,Gxy_square}), // input wire [23 : 0] s_axis_cartesian_tdata .m_axis_dout_tvalid(), // output wire m_axis_dout_tvalid .m_axis_dout_tdata(result_root) // output wire [15 : 0] m_axis_dout_tdata ); //--------------------------------------- //Compare and get the Sobel_data //Step 5 reg post_img_Bit_r; always@(posedge clk or negedge rst_n)begin if(!rst_n) post_img_Bit_r <= 1'b0; //Default None else if(result_root >= Sobel_Threshold) post_img_Bit_r <= 1'b1; //Edge Flag else post_img_Bit_r <= 1'b0; //Not Edge end //------------------------------------------ //lag 5 clocks signal sync reg [4:0] per_frame_vsync_r; reg [4:0] per_frame_href_r; reg [4:0] per_frame_clken_r; always@(posedge clk or negedge rst_n)begin if(!rst_n) begin per_frame_vsync_r <= 0; per_frame_href_r <= 0; per_frame_clken_r <= 0; end else begin per_frame_vsync_r <= {per_frame_vsync_r[3:0], matrix_frame_vsync}; per_frame_href_r <= {per_frame_href_r [3:0], matrix_frame_href}; per_frame_clken_r <= {per_frame_clken_r[3:0], matrix_frame_clken}; end end assign post_frame_vsync = per_frame_vsync_r[4]; assign post_frame_href = per_frame_href_r [4]; assign post_frame_clken = per_frame_clken_r[4]; assign post_img_Bit = post_frame_href ? post_img_Bit_r : 1'b0; endmodule二、在Quartus中实现
推荐阅读:图像高斯滤波的FPGA实现
/* Filename : Sobel.v Compiler : Quartus II 13.0 Description : implement Sobel Edge Detector */ module sobel ( input iCLK, input iRST_N, input [7:0] iTHRESHOLD,//阈值 input iDVAL, input [9:0] iDATA, output reg oDVAL, output reg [9:0] oDATA ); //==========================================parameter=========================================================== // mask x parameter X1 = 8'hff, X2 = 8'h00, X3 = 8'h01; parameter X4 = 8'hfe, X5 = 8'h00, X6 = 8'h02; parameter X7 = 8'hff, X8 = 8'h00, X9 = 8'h01; // mask y parameter Y1 = 8'h01, Y2 = 8'h02, Y3 = 8'h01; parameter Y4 = 8'h00, Y5 = 8'h00, Y6 = 8'h00; parameter Y7 = 8'hff, Y8 = 8'hfe, Y9 = 8'hff; //==========================================reg================================================================= //==========================================wire================================================================= wire [7:0] Line0; wire [7:0] Line1; wire [7:0] Line2; wire [17:0] Mac_x0; wire [17:0] Mac_x1; wire [17:0] Mac_x2; wire [17:0] Mac_y0; wire [17:0] Mac_y1; wire [17:0] Mac_y2; wire [19:0] Pa_x; wire [19:0] Pa_y; wire [15:0] Abs_mag; //==========================================always================================================================= always@(posedge iCLK, negedge iRST_N) begin if (!iRST_N) oDVAL <= 0; else begin oDVAL <= iDVAL; if (iDVAL) oDATA <= (Abs_mag > iTHRESHOLD) ? 0 : 1023; else oDATA <= 0;//输出的10位图像数据 end end //==========================================状态机================================================================= //==========================================模块例化================================================================= LineBuffer LineBuffer_inst ( .clken(iDVAL), .clock(iCLK), .shiftin(iDATA[9:2]), .taps0x(Line0), .taps1x(Line1), .taps2x(Line2) ); // X MAC_3 x0 ( .aclr3(!iRST_N), .clock0(iCLK), .dataa_0(Line0), .datab_0(X9), .datab_1(X8), .datab_2(X7), .result(Mac_x0) ); MAC_3 x1 ( .aclr3(!iRST_N), .clock0(iCLK), .dataa_0(Line1), .datab_0(X6), .datab_1(X5), .datab_2(X4), .result(Mac_x1) ); MAC_3 x2 ( .aclr3(!iRST_N), .clock0(iCLK), .dataa_0(Line2), .datab_0(X3), .datab_1(X2), .datab_2(X1), .result(Mac_x2) ); // Y MAC_3 y0 ( .aclr3(!iRST_N), .clock0(iCLK), .dataa_0(Line0), .datab_0(Y9), .datab_1(Y8), .datab_2(Y7), .result(Mac_y0) ); MAC_3 y1 ( .aclr3(!iRST_N), .clock0(iCLK), .dataa_0(Line1), .datab_0(Y6), .datab_1(Y5), .datab_2(Y4), .result(Mac_y1) ); MAC_3 y2 ( .aclr3(!iRST_N), .clock0(iCLK), .dataa_0(Line2), .datab_0(Y3), .datab_1(Y2), .datab_2(Y1), .result(Mac_y2) ); PA_3 pa0 ( .clock(iCLK), .data0x(Mac_x0), .data1x(Mac_x1), .data2x(Mac_x2), .result(Pa_x) ); PA_3 pa1 ( .clock(iCLK), .data0x(Mac_y0), .data1x(Mac_y1), .data2x(Mac_y2), .result(Pa_y) ); SQRT sqrt0 ( .clk(iCLK), .radical(Pa_x * Pa_x + Pa_y * Pa_y), .q(Abs_mag) ); endmodule