您当前的位置: 首页 >  图像处理

图像处理3:Sobel边缘检测

发布时间:2022-07-22 22:39:45 ,浏览量:9

前言

软件版本 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
关注
打赏
1688896170
查看更多评论

暂无认证

  • 9浏览

    0关注

    108697博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录

0.0575s