基于FPGA的sobel算法仿真验证
一、 算法原理介绍
索贝尔算子(Sobeloperator)主要用作边缘检测,在技术上,它是一离散性差分算子,用来运算图像亮度函数的灰度之近似值,在图像的任何一点使用此算子,将会产生对应的灰度矢量或是其法矢量 。其目的是能够精确的测量和定位,那么,就意味着实际的物体能够被定位和测量,包括物体的面积、物体的直径、物体的形状等就能被测量。在数字图像中,边缘是指图像局部变化最显著的部分,边缘主要存在于目标与目标,目标与背景之间,是图像局部特性的不连续性,如灰度的突变、纹理结构的图标、颜色的图标等。尽管图像的边缘点产生的原因各不相同,但他们都是图形上灰度不连续或灰度几句辩护的点,图像边缘分为阶跃状、斜坡状和屋顶状。需要理解以下三个定义:
边缘:灰度或结构等信息的突变处,边缘是一个区域的结束,也是另一个区域的开始,利用该特征可以分割图像。
边缘点:图像中具有坐标[x,y],且处在强度显著变化的位置上的点。
边缘段:对应于边缘点坐标[x,y]及其方位 ,边缘的方位可能是梯度角。
二、 实现算法的流程
这是一种离散的卷积算法。由于数字图像是以离散的像素形式体现图像,故数字图像处理的实质就是离散数字的处理。
所谓卷积是对所关心像素进行的离散处理,不仅根据卷积点原图像的数值,而且根据其周期像素的数值。平面卷积按照模板的大小和类型分类,典型的数字图像平面卷积模板采用33模板(即课程讨论的计算阵列)
采用卷积模板计算对应的图像处理结果(这里是sobel)时,将33模板在原数字图像上移动,每次一个像素(或横向,或纵向),以此得到全部图像像素的卷积计算结果,作为图像处理的结果。
采用3*3模板卷积时,必定有第1行,最后行,最左列和最右列的像素计算无法得到有效数值,称为卷积计算的边界处理,现代文献中,有将边界值填零,有将边界值填镜像,有将边界值做特定的逻辑运算的各种方案,至芯教材中采用填零的做法有了算法,如何将算法转变成电路,则是EDA的算法工程师的主要任务。在夏老师的代码中,采用了如下方式的结构以支持算法:
像素是8比特,数据总线是32比特。即一次存储器的读写访问一个字,可以访问四个像素。
基于verilog的算法流程如下所示,图片输入数据端口为串行数据,首先需要完成串行数据到并行数据的转换,这里采用9个移位寄存器的方法实现,然后是进行矩阵运算,分别与sobel算子Gx和Gy完成3×3矩阵的运算,其次将两个矩阵运算的结果进行先平方再求和的运算,再其次将得到结果开算术平方根,最后完成阈值大小的比较,最终得到sobel算法后的数据。
三、 结果展示
··························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