图像处理3:Sobel边缘检测

本文详细介绍了如何在Vivado 2020.1和Quartus 17.1中实现Sobel边缘检测算法。在Vivado中,通过3x3矩阵相乘、平方、求和、开方及阈值比较步骤实现;在Quartus中,利用MAC单元和平方根模块完成相同过程。
摘要由CSDN通过智能技术生成

前言

软件版本
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 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值