基于FPGA的sobel算法仿真验证

基于FPGA的sobel算法仿真验证

一、 算法原理介绍
索贝尔算子(Sobeloperator)主要用作边缘检测,在技术上,它是一离散性差分算子,用来运算图像亮度函数的灰度之近似值,在图像的任何一点使用此算子,将会产生对应的灰度矢量或是其法矢量 。其目的是能够精确的测量和定位,那么,就意味着实际的物体能够被定位和测量,包括物体的面积、物体的直径、物体的形状等就能被测量。在数字图像中,边缘是指图像局部变化最显著的部分,边缘主要存在于目标与目标,目标与背景之间,是图像局部特性的不连续性,如灰度的突变、纹理结构的图标、颜色的图标等。尽管图像的边缘点产生的原因各不相同,但他们都是图形上灰度不连续或灰度几句辩护的点,图像边缘分为阶跃状、斜坡状和屋顶状。需要理解以下三个定义:
边缘:灰度或结构等信息的突变处,边缘是一个区域的结束,也是另一个区域的开始,利用该特征可以分割图像。

 边缘点:图像中具有坐标[x,y],且处在强度显著变化的位置上的点。

 边缘段:对应于边缘点坐标[x,y]及其方位 ,边缘的方位可能是梯度角。

二、 实现算法的流程
这是一种离散的卷积算法。由于数字图像是以离散的像素形式体现图像,故数字图像处理的实质就是离散数字的处理。
所谓卷积是对所关心像素进行的离散处理,不仅根据卷积点原图像的数值,而且根据其周期像素的数值。平面卷积按照模板的大小和类型分类,典型的数字图像平面卷积模板采用33模板(即课程讨论的计算阵列)
采用卷积模板计算对应的图像处理结果(这里是sobel)时,将3
3模板在原数字图像上移动,每次一个像素(或横向,或纵向),以此得到全部图像像素的卷积计算结果,作为图像处理的结果。
采用3*3模板卷积时,必定有第1行,最后行,最左列和最右列的像素计算无法得到有效数值,称为卷积计算的边界处理,现代文献中,有将边界值填零,有将边界值填镜像,有将边界值做特定的逻辑运算的各种方案,至芯教材中采用填零的做法有了算法,如何将算法转变成电路,则是EDA的算法工程师的主要任务。在夏老师的代码中,采用了如下方式的结构以支持算法:
像素是8比特,数据总线是32比特。即一次存储器的读写访问一个字,可以访问四个像素。
基于verilog的算法流程如下所示,图片输入数据端口为串行数据,首先需要完成串行数据到并行数据的转换,这里采用9个移位寄存器的方法实现,然后是进行矩阵运算,分别与sobel算子Gx和Gy完成3×3矩阵的运算,其次将两个矩阵运算的结果进行先平方再求和的运算,再其次将得到结果开算术平方根,最后完成阈值大小的比较,最终得到sobel算法后的数据。
在这里插入图片描述

三、 结果展示
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
quartus编译结果 ··························quartus编译结果··························

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码下载连接戳这里

**

四、仿真代码

**

`timescale 1 ns/ 1 ns
module Sobel_Edge_Detector_tb();
// constants                                           
// general purpose registers


// test vector input registers
integer w_file,w_file1,w_file2; 
reg clk=1'b0;
reg rst_n=1'b0;
// wires                                               
reg  [7:0]  Sobel_Threshold;
wire [7:0]  o_Sobel_data,o_level_data,o_vertic_data;
 
                  
Sobel_Edge_Detector i1 (
// port map - connection between master ports and signals/registers   
	.Sobel_Threshold(Sobel_Threshold),
	.clk(clk),
	.rst_n(rst_n),
	.o_level_data (o_level_data ),
	.o_vertic_data(o_vertic_data),
	.o_Sobel_data (o_Sobel_data )
);

initial                                                
begin    
	while(1)
		#10 clk =~clk;
			$display("Sobel_data = %2d",o_Sobel_data);                       
end

initial                                                
begin    
	rst_n <=1'b0;
	Sobel_Threshold<=8'd100;
    #20 rst_n <=1'b1;  		
    #1290320;//根据元素设置
	#80;
    $stop;	
end 
 
initial
begin
	#100
    w_file  = $fopen("C:/Users/Administrator/Desktop/sobel2_rom_vrlV0.1/SRC/lena_gray_out.txt"); 
	w_file1 = $fopen("C:/Users/Administrator/Desktop/sobel2_rom_vrlV0.1/SRC/level_out.txt");
	w_file2 = $fopen("C:/Users/Administrator/Desktop/sobel2_rom_vrlV0.1/SRC/vertic_out.txt");	 
end	  

always@(posedge clk or negedge rst_n) 
 begin
    if(rst_n)
		begin
			$fdisplay(w_file ,"%2d",o_Sobel_data );
			$fdisplay(w_file1,"%2d",o_level_data );
			$fdisplay(w_file2,"%2d",o_vertic_data);
		end		
 end                                                

 
endmodule  

	//欢迎交流//-欢迎交流-欢迎交流欢迎交流//
	
	
	
	
	
	
	
	//作  者:VincentQing
	//Q   Q:2692377302
	//微信号:Science-Technology
	//版  本:20200020812

五、sobel算法代码


module Sobel_Edge_Detector
(  //global clock
input clk,             			 //cmos video pixel clock
input rst_n,                	 //global reset
input [7:0]Sobel_Threshold, 	 //Sobel Threshold for image edge detect
output [7:0]o_level_data ,
output [7:0]o_vertic_data,
output [7:0]o_Sobel_data
);

//Sobel Parameter

//         Gx                  Gy               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 ]


wire [7:0]Sobel_data;
reg  [15:0]row,col;
reg  [15:0]address1;
reg  [15:0]address2;
reg  [15:0]address3;
reg  [15:0]address4;
reg  [15:0]address5;
reg  [15:0]address6;
reg  [15:0]address7;
reg  [15:0]address8;
reg  [15:0]address9;

///
wire  [7:0]matrix_p11,matrix_p12,matrix_p13,matrix_p21,matrix_p22,matrix_p23,matrix_p31,matrix_p32,matrix_p33;

//acqurie  3x3 martix
//Step 1.0
always@(posedge clk or negedge rst_n)
begin

  if(!rst_n)
      begin
	  address1 <=16'd0;
	  address2 <=16'd0;
	  address3 <=16'd0;
	  address4 <=16'd0;
	  address5 <=16'd0;
	  address6 <=16'd0;
	  address7 <=16'd0;
	  address8 <=16'd0;
	  address9 <=16'd0;

	  row<=16'd0;
	  col<=16'd0;  
      end
  else
      begin
		
		address1 <= col  +256*(row+0);
		address2 <= col  +256*(row+1);
		address3 <= col  +256*(row+2);
		address4 <= col+1+256*(row+0);
		address5 <= col+1+256*(row+1);
		address6 <= col+1+256*(row+2);
		address7 <= col+2+256*(row+0);
		address8 <= col+2+256*(row+1);
		address9 <= col+2+256*(row+2); 
		
		if (row==16'd253 )
			begin
			
			if (col==16'd253)
				col<=16'd0;
			else
				col<=col+1'b1;
				
			row<=16'd0;
			end
		else
			row<=row+1'b1;
      end
end


MyRom MyRom1(
	.address(address1),
	.clock  (clk  ),
	.q      (matrix_p11)
	);
MyRom MyRom2(
	.address(address2),
	.clock  (clk  ),
	.q      (matrix_p12)
	);
MyRom MyRom3(
	.address(address3),
	.clock  (clk  ),
	.q      (matrix_p13)
	);
MyRom MyRom4(
	.address(address4),
	.clock  (clk  ),
	.q      (matrix_p21)
	);
MyRom MyRom5(
	.address(address5),
	.clock  (clk  ),
	.q      (matrix_p22)
	);
MyRom MyRom6(
	.address(address6),
	.clock  (clk  ),
	.q      (matrix_p23)
	);
MyRom MyRom7(
	.address(address7),
	.clock  (clk  ),
	.q      (matrix_p31)
	);
MyRom MyRom8(
	.address(address8),
	.clock  (clk  ),
	.q      (matrix_p32)
	);	
MyRom MyRom9(
	.address(address9),
	.clock  (clk  ),
	.q      (matrix_p33)
	);	


//Caculate horizontal Grade with |abs|
//Step 1.1
reg   [9:0]   Gx_reg1;   //postive result
reg   [9:0]   Gx_reg2;   //negetive result
reg   [9:0]   Gx_data;   //Horizontal grade data
always@(posedge clk or negedge rst_n)
begin

  if(!rst_n)
      begin
      Gx_reg1 <= 0;
      Gx_reg2 <= 0;
      Gx_data <= 0;
      end
  else //if(cnt==4'd0)
      begin	  
      Gx_reg1 <= matrix_p11 + (matrix_p21<<1) + matrix_p31;    //postive result
      Gx_reg2 <= matrix_p13 + (matrix_p23<<1) + matrix_p33;    //negetive result
      Gx_data <= (Gx_reg1 >= Gx_reg2) ? Gx_reg1 - Gx_reg2 : Gx_reg2 - Gx_reg1;
      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 //if(cnt==4'd0)
      begin
      Gy_temp1 <= matrix_p11 + (matrix_p21<<1) + matrix_p31;    //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
wire   [31:0]   Gxy_square = Gx_data * Gx_data + Gy_data * Gy_data;


-
//Caculate the distance of P5 = (Gx^2 + Gy^2)^0.5
//Step 4
wire  [15:0]div_data;
My_SQRT  U1
(
.q(div_data),
.radical(Gxy_square),
.remainder()
);


-
//Compare and get the Sobel_data_r
//Step 5

assign Sobel_data=(div_data[7:0]>= Sobel_Threshold)?div_data[7:0]:8'd0;
assign o_Sobel_data=Sobel_data;
assign o_level_data =(Gx_data>= Sobel_Threshold)?Gx_data:8'd0;
assign o_vertic_data=(Gy_data>= Sobel_Threshold)?Gy_data:8'd0;

endmodule

	//欢迎交流//-欢迎交流-欢迎交流欢迎交流//
	
	
	
	
	
	
	
	//作  者:VincentQing
	//Q   Q:2692377302
	//微信号:Science-Technology
	//版  本:20200020812
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VincentRunning

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值