sobel算法边缘检测
小梅哥书上的教程讲得很好
《小梅哥-FPGA系统设计与验证实战指南_V24》P836 7.11
sobel算法做边缘检测其实也是一种二值化的预操作,在完成sobel处理后,与阈值进行比较,即完成了二值化,但这个阈值可以通过OTSU算法来计算出
简单定义:卷积是分析数学中一种重要的运算。
设:f(x),g(x)是R1上的两个可积函数,作积分:
可以证明,关于几乎所有的实数x,上述积分是存在的。这样,随着x的不同取值,这个积分就定义了一个新函数h(x),称为函数f与g的卷积,记为h(x)=(f*g)(x)。
容易验证,(f * g)(x) = (g * f)(x),并且(f * g)(x)仍为可积函数。这就是说,把卷积代替乘法,L1(R1)空间是一个代数,甚至是巴拿赫代数。
卷积与傅里叶变换有着密切的关系。利用一点性质,即两函数的傅里叶变换的乘积等于它们卷积后的傅里叶变换,能使傅里叶分析中许多问题的处理得到简化。
由卷积得到的函数f*g一般要比f和g都光滑。特别当g为具有紧致集的光滑函数,f为局部可积时,它们的卷积f * g也是光滑函数。利用这一性质,对于任意的可积函数f,都可以简单地构造出一列逼近于f的光滑函数列fs,这种方法称为函数的光滑化或正则化。
Sobel算子的理解
sobel算子主要用于获得数字图像的一阶梯度,常见的应用和物理意义是边缘检测。
原理
算子使用两个33的矩阵(图1)算子使用两个33的矩阵(图1)去和原始图片作卷积,分别得到横向G(x)和纵向G(y)的梯度值,如果梯度值大于某一个阈值,则认为该点为边缘点
Gx方向的相关模板:
Gy方向的相关模板:
看了网上的很多资料,都把卷积和相关的概念给弄糊了,书上给的Sobel的模板不是卷积模板,而是相关模板,因为卷积的话要先将模板旋转180****度以后再与图像做相关的操作。
所以Sobel的卷积模板是:
体计算如下:
图像的每一个像素的横向及纵向灰度值通过以下公式结合,来计算该点灰度的大小:
通常,为了提高效率使用不开平方的近似值:
然后可用以下公式计算梯度方向:
OpenCV还提供了一个scharr函数,比Sobel算子更为精准,也是3x3的模板。
hu/),比Sobel算子更为精准,也是3x3的模板。
因为Sobel算子只是求取了导数的近似值,当内核大小为3时,以上Sobel内核可能产生比较明显的误差。为解决这一问题,OpenCV提供了 Scharr 函数,但该函数仅作用于大小为3的内核,该函数的运算与Sobel函数一样快,但结果却更加精确
4.代码
module sobel (
input rst,
input pclk,
input ycbcr_hs,
input ycbcr_vs,
input ycbcr_de,
input [7:0] fazhi,
output reg data_out,
output sobel_hs,
output sobel_vs,
output sobel_de,
input [7:0] p1,
input [7:0] p3,
input [7:0] p2,
input [1:0] zt,
output reg data_out_pd
);
reg [7:0] p11,p12,p13;
reg [7:0] p21,p22,p23;
reg [7:0] p31,p32,p33;
reg [9:0] x1,x3;
reg [9:0] y1,y3;
reg [9:0] abs_x,abs_y;
reg [10:0] abs_g;
reg [8:0] hs_buf ;
reg [8:0] vs_buf ;
reg [8:0] de_buf ;
reg [7:0] fazhi_;
always fazhi_=fazhi;
always@(posedge pclk)//9个8位reg做移位计算,每次移入3个,并移出3个
begin
p11 <= p1;
p21 <= p2;
p31 <= p3;
p12 <= p11;
p22 <= p21;
p32 <= p31;
p13 <= p12;
p23 <= p22;
p33 <= p32;
end
always@(posedge pclk)//sobel做卷积的核心代码
begin
x1 <= {2'b00,p11} + {2'b00,p31} + {1'b0,p21,1'b0};
x3 <= {2'b00,p13} + {2'b00,p33} + {1'b0,p23,1'b0};
y1 <= {2'b00,p11} + {2'b00,p13} + {1'b0,p12,1'b0};
y3 <= {2'b00,p31} + {2'b00,p33} + {1'b0,p32,1'b0};
end
always@(posedge pclk)
begin
abs_x <= (x1 > x3) ? x1 - x3 : x3 - x1;
abs_y <= (y1 > y3) ? y1 - y3 : y3 - y1;
abs_g <= abs_x + abs_y;
end
always@(posedge pclk)
begin
/*if(zt==2'b11)
data_out <= (abs_g >65)? 1:0;
else
*/
data_out <= (abs_g >fazhi_)? 1:0;
end
//hs vs de delay 9 clock
always@(posedge pclk or negedge rst)
begin
if (!rst)
begin
hs_buf <= 9'd0 ;
vs_buf <= 9'd0 ;
de_buf <= 9'd0 ;
end
else
begin
hs_buf <= {hs_buf[7:0], ycbcr_hs} ;
vs_buf <= {vs_buf[7:0], ycbcr_vs} ;
de_buf <= {de_buf[7:0], ycbcr_de} ;
end
end
assign sobel_hs = hs_buf[8] ;
assign sobel_vs = vs_buf[8] ;
assign sobel_de = de_buf[8] ;
endmodule