2018-10-03 15:46:39 u013921430 阅读数 4212

【fishing-pan:https://blog.csdn.net/u013921430 转载请注明出处】

灰度图边缘检测

   在学习图像处理时,首先接触到的就是灰度图像的边缘检测,这是图像处理最基础的也是最重要的一环,熟悉图像边缘检测有助于我们学习其他的数字图像处理方法。由于图像的边缘区域会存在明显的像素值阶跃,因此边缘检测主要是通过获得图像灰度梯度,进而通过梯度大小和变化来判断图像边缘的。
  
在这里插入图片描述
   因此,我们可以通过一阶差分;
Δfx(x,y)=f(x+1,y)f(x,y)Δfy(x,y)=f(x,y+1)f(x,y) \Delta f_{x}(x,y)=f(x+1,y)-f(x,y)\\ \Delta f_{y}(x,y)=f(x,y+1)-f(x,y)
   或者二阶差分对边缘区域进行判断;
Δfxx(x,y)=f(x+1,y)+f(x1,y)2f(x,y)Δfyy(x,y)=f(x,y+1)+f(x,y1)2f(x,y) \Delta f_{xx}(x,y)=f(x+1,y)+f(x-1,y)-2f(x,y)\\ \Delta f_{yy}(x,y)=f(x,y+1)+f(x,y-1)-2f(x,y)
   其中一阶差分可以判断边缘是否存在,二阶差分还可以根据正负号判断像素点在图像边缘亮的一侧还是暗的一侧。
   其他的边缘检测方法还包括一些梯度算子,例如Prewitt算子、Sobel算子,Canny算子,LOG边缘检测算子等,在此不做说明。

彩色图边缘检测

   RGB 图像使用三个通道存储像素信息,我们可以将这三个通道的信息看作是一个矢量,而矢量是不存在梯度的概念的,我们无法直接将上诉方法或算子直接用于RGB 图像,而且RGB图像单个通道的梯度信息又无法反映整体的梯度信息。
   在《数字图像处理》(冈萨雷斯)中提到了一种针对彩色图像的边缘检测方法,这种方法由 Di Zenzo 等人在1986年提出,下面就一起看看这种方法如何得出。

Di Zenzo’s gradient operator

   在图像多通道图像f(x,y)f(x,y) 中的某一点P(x,y)P(x,y) 处,假设其梯度方向为θ\theta
Δf=f(x+εcosθ,y+εsinθ)f(x,y) \Delta f=\left \| f(x+\varepsilon cos\theta,y+\varepsilon sin\theta) -f(x,y)\right \|
   为了便于计算,将计算绝对值换为计算平方,令
Δf2=f(x+εcosθ,y+εsinθ)f(x,y)2 \Delta f^{2}=\left \| f(x+\varepsilon cos\theta,y+\varepsilon sin\theta) -f(x,y)\right \|^{2}
   对f(x+εcosθ,y+εsinθ)f(x+\varepsilon cos\theta,y+\varepsilon sin\theta)进行二元泰勒展开;
f(x+εcosθ,y+εsinθ)=f(x,y)+i=1m(εcosθfi(x,y)x+εsinθfi(x,y)y)+onf(x,y)+i=1m(εcosθfi(x,y)x+εsinθfi(x,y)y) \begin{aligned} f(x+\varepsilon cos\theta,y+\varepsilon sin\theta)&=f(x,y)+\sum_{i=1}^{m}(\varepsilon cos\theta\cdot\frac{\partial f_{i}(x,y)}{\partial x} +\varepsilon sin\theta\cdot\frac{\partial f_{i}(x,y)}{\partial y} )+o^{n}\\ &\approx f(x,y)+\sum_{i=1}^{m}(\varepsilon cos\theta\cdot\frac{\partial f_{i}(x,y)}{\partial x} +\varepsilon\cdot sin\theta\cdot\frac{\partial f_{i}(x,y)}{\partial y} ) \end{aligned}
   其中mm表示图像通道数目,为了方便表述使用fix\frac{\partial f_{i}}{\partial x}代替fi(x,y)x\frac{\partial f_{i}(x,y)}{\partial x},而在求导时各个通道之间是相互独立的,则有;
Δf2i=1m(εcosθfix+εsinθfiy)2 \Delta f^{2}\approx\sum_{i=1}^{m}(\varepsilon cos\theta\cdot\frac{\partial f_{i}}{\partial x} +\varepsilon sin\theta\cdot\frac{\partial f_{i}}{\partial y} )^{2}
  重新定义一个函数G(θ)G(\theta),令
G(θ)=i=1m(εcosθfix+εsinθfiy)2=ε2(cosθ2i=1mfix2+sinθ2i=1mfiy2+2sinθcosθi=1mfixfiy) \begin{aligned} G(\theta)&=\sum_{i=1}^{m}(\varepsilon cos\theta\cdot\frac{\partial f_{i}}{\partial x} +\varepsilon sin\theta\cdot\frac{\partial f_{i}}{\partial y} )^{2}\\ &=\varepsilon ^{2}(cos\theta^{2}\sum_{i=1}^{m}\left \|\frac{\partial f_{i}}{\partial x}\right \|^{2}+sin\theta^{2}\sum_{i=1}^{m}\left \|\frac{\partial f_{i}}{\partial y}\right \|^{2}+2sin\theta cos\theta \sum_{i=1}^{m}\frac{\partial f_{i}}{\partial x}\frac{\partial f_{i}}{\partial y}) \end{aligned}
   进一步舍去式子中的ε\varepsilon 项,令
G(θ)=cosθ2i=1mfix2+sinθ2i=1mfiy2+2sinθcosθi=1mfixfiy G(\theta)=cos\theta^{2}\sum_{i=1}^{m}\left \|\frac{\partial f_{i}}{\partial x}\right \|^{2}+sin\theta^{2}\sum_{i=1}^{m}\left \|\frac{\partial f_{i}}{\partial y}\right \|^{2}+2sin\theta cos\theta \sum_{i=1}^{m}\frac{\partial f_{i}}{\partial x}\frac{\partial f_{i}}{\partial y}
   为了进一步方便表述;令
E=i=1mfix2;F=i=1mfiy2;H=i=1mfixfiy E=\sum_{i=1}^{m}\left \| \frac{\partial f_{i}}{\partial x} \right \|^{2}; F=\sum_{i=1}^{m}\left \|\frac{\partial f_{i}}{\partial y}\right \|^{2}; H=\sum_{i=1}^{m}\frac{\partial f_{i}}{\partial x}\frac{\partial f_{i}}{\partial y}
G(θ)=cosθ2E+sinθ2F+2sinθcosθH G(\theta)=cos\theta^{2}E+sin\theta^{2}F+2sin\theta cos\theta H
   现在θ\theta成为了式子中唯一的变量,再回到边缘的定义上,边缘的方向是图像像素梯度最大的方向。也就是说梯度的方向θmax\theta_{max} 会使G(θ)G(\theta) 取最大值,则;
θmax=G(θ)argmax \theta_{max}=\underset{argmax}{G(\theta )}
   对G(θ)G(\theta) 进行求导;
G(θ)=Esin2θ+Fsin2θ+2Hcos2θ G(\theta )^{'}=-Esin2\theta +F sin2\theta+2 H cos2\theta
   令G(θ)=0G(\theta )^{'}=0,得;
tan 2θmax=2HEFθmax=12arctan(2HEF+kπ) tan ~2\theta_{max} =\frac{2H}{E-F}\\ \theta_{max}=\frac{1}{2}arctan(\frac{2H}{E-F}+k\pi)
   很明显G(θ)G(\theta ) 是一个以π\pi 为周期的周期函数,如果只考虑区间[0,π)\left [ 0 ,\pi\right ),且θmax\theta_{max} 落到该区间内,则会有另一个让G(θ)G(\theta )取极值的解也落在该区域内,这个值是θmax+π2\theta_{max}+ \frac{\pi}{2}或者θmaxπ2\theta_{max}-\frac{\pi}{2}。但是不论如何这两个解有一个让G(θ)G(\theta )取极大值,另一个让其取极小值,两个角度相差 90°。
  
   说到这里大家应该都明白了,两个角度对应的方向是相互垂直的,一个是垂直于边缘的方向,也就是边缘的法向,此时梯度取最大值。另一个是平行于边缘的方向,是边缘的切向,此时梯度取极小值。
  

RGB图像的边缘检测

   在RGB图像中,m=3m=3,再令;
u=Rxr+Gxg+Bxb \overset{\rightarrow }{u}=\frac{\partial R}{\partial x}\overset{\rightarrow }{r}+\frac{\partial G}{\partial x}\overset{\rightarrow }{g}+\frac{\partial B}{\partial x}\overset{\rightarrow }{b}
v=Ryr+Gyg+Byb \overset{\rightarrow }{v}=\frac{\partial R}{\partial y}\overset{\rightarrow }{r}+\frac{\partial G}{\partial y}\overset{\rightarrow }{g}+\frac{\partial B}{\partial y}\overset{\rightarrow }{b}
   其中r\overset{\rightarrow }{r}g\overset{\rightarrow }{g}b\overset{\rightarrow }{b}分别代表不同颜色分量的单位向量,则
gxx=E=uTu=Rx2+Gx2+Bx2 g_{xx}=E=\overset{\rightarrow }{u}^{\tiny{T}}\overset{\rightarrow }{u}=\left \| \frac{\partial R}{\partial x} \right \|^{2}+\left \| \frac{\partial G}{\partial x} \right \|^{2}+\left \| \frac{\partial B}{\partial x} \right \|^{2}
gyy=F=vTv=Ry2+Gy2+By2 g_{yy}=F=\overset{\rightarrow }{v}^{\tiny{T}}\overset{\rightarrow }{v}=\left \| \frac{\partial R}{\partial y} \right \|^{2}+\left \| \frac{\partial G}{\partial y} \right \|^{2}+\left \| \frac{\partial B}{\partial y} \right \|^{2}
gxy=H=uTv=RxRy+GxGy+BxBy g_{xy}=H=\overset{\rightarrow }{u}^{\tiny{T}}\overset{\rightarrow }{v}=\frac{\partial R}{\partial x}\frac{\partial R}{\partial y}+\frac{\partial G}{\partial x}\frac{\partial G}{\partial y}+\frac{\partial B}{\partial x}\frac{\partial B}{\partial y}
   在利用Di Zenzo 提出的方法求得θmax\theta_{max} 后,将以上符号带入到G(θ)G(\theta),可以计算出像素点梯度大小为
G(θ)={12[(gxx+gyy)+(gxxgyy)cos 2θmax+2gxysin 2θmax]}12 G(\theta)=\left \{ \frac{1}{2}\left [ (g_{xx}+g_{yy}) +(g_{xx}-g_{yy})cos~2\theta_{max} +2g_{xy}sin~2\theta_{max} \right ]\right \}^{\frac{1}{2}}
   进而可以根据梯度大小进行边缘检测。

参考资料

  1. S. Di Zenzo, A note on the gradient of a multi-image, Computer Vision, Graphics, and Image Processing 33 (1) (1986) 116–125.
  2. 《数字图像处理》 (冈萨雷斯)
2017-09-22 19:41:43 u011271038 阅读数 531

简介

边缘检测是图像处理中使用频率很高的方法,在进行更复杂的图像处理之前,我们常常先对图像进行边缘检测,以去除图像一些无用的部分,并保留一些对我们有用的部分。

原理

边缘检测意在检测出图像的边缘,那何为边缘?简单的理解是,边缘是图像中明暗变化剧烈的地方。如果从图像的x轴方向抽出一列数据,绘出它的图像,并假设是连续的曲线,则曲线陡升或陡降出就代表边缘。从数学角度看,陡升或陡降意味着该处的斜率比较大。反过来说,斜率大的地方意味着是边缘。而斜率是曲线在该点的导数,因此求边缘的问题可以转换成求导数。
导数往往指二维平面上的曲线变化率,而图像实际是三维空间的。图像的长(x轴),宽(y轴),像素值(z轴)所组成的三维,像素值组成了一个曲面。对曲面在x轴方向求导数,叫做x方向的偏导数,同样的,也存在y方向的偏导数。而有x,y轴所围成的平面有无数个方向,所以存在无数个方向的导数,我们可以通过x,y方向的偏导数求得任意方向的导数。在这些方向的导数中,存在某一个方向,且该方向导数值最大,这个导数称作曲面在该点的梯度。
图像在该点的梯度意味着在该点的某方向灰度值变化最快,这就意味着边缘的存在。
我们用这里写图片描述代表曲面上a点的梯度。这里写图片描述为曲面上a点的方向导数,u代表方向。
则有这里写图片描述,当方向指向梯度方向(梯度方向用m表示)时,这里写图片描述
所以检测图像的边缘问题变成了求图像梯度。由梯度的数学求法可知,这里写图片描述

梯度算子

在计算机中我们常常用差分代替微分,用求和代替求平方,上式子可以简化为:
这里写图片描述其中,
这里写图片描述
这里写图片描述
对应的模板为:
这里写图片描述这里写图片描述

Roberts算子

该算子是另一种近似求梯度法。对应模板为:
这里写图片描述这里写图片描述

Prewitt算子

这里写图片描述这里写图片描述

Sobel算子

这里写图片描述这里写图片描述

这几个算子比较简单,下面看一下Sobel算子检测的结果:
这里写图片描述
这里写图片描述

canny检测

经上面几个算子处理后的图像,已经检测出了边缘,不过边缘显得有些模糊。下面简单说说canny算法:
1)用高斯平滑处理
2)算出梯度和梯度方向
3)对梯度值进行非极大值抑制
4)用双阈值算法检测和连接边缘
下面看看效果
这里写图片描述
这里写图片描述
网上谈canny算法的文章很多,不过大多是用opencv,这对我们从根本上理解该算法并无多大帮助,十分想用c/c++实现canny算法,但限于我的能力和时间,并没有完全实现canny,倒是实现了一小部分。

也许也不能称之为我的这个算法是未完成的canny,因为这是按照我的理解写的,也许并不符合canny的本意。但是先看看我的处理结果:
这里写图片描述

再来对比一下sobel算法的结果:
这里写图片描述

我的算法比canny保留了更多细节,同时比sobel的算法更加突出细节。这种结果对寻找图像中的小细节十分合适。

这里写图片描述

这里写图片描述

2018-04-26 22:56:53 qq_31804159 阅读数 7298

我的程序效果:

 

边缘检测算法是图像处理中最为基本的问题。其目的是标志图像出亮度变化明显的点,从而反映出图像中重要变化。

 

先介绍一下Sobel算子

Sobel 算子是像素图像边缘检测中最重要的算子之一,该算子包含两组3x3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。如下图,Gx和Gy分别是在横向及纵向的灰度偏导的近似值。(:对于一个彩色图要先把它转换为灰度图)

关于卷积可以看一下这个博客:https://blog.csdn.net/chaipp0607/article/details/72236892?locationNum=9&fps=1

 

对于每一个点我们可以获得两个方向的梯度,我们可以通过下面这个公式算出梯度的估计值。

我们定义一个阈值Gmax(这里定义Gmax = 150),如果G比Gmax大可以认为该点是一个边界值.则设置这个点为白色否则该店为黑色。这样我们就得到了通过边缘检测的图像。

 

代码实现:

1.彩色图转为灰度图


QImage LeadToGrey(const QImage &source)
{

    int w = source.width();
    int h = source.height();
    QImage gray(w,h,QImage::Format_RGB32);

    for( int i = 0; i< h; i++){

        for(int j = 0; j < w; j++){
            QRgb pixel = source.pixel(j,i);

            int grey = qGray(pixel);
            QRgb graypixel = qRgb(grey,grey,grey);
            gray.setPixel(j,i,graypixel);

        }
    }
    return gray;
}


2.边缘检测代码:


Image LeadToEdge(QImage source)
{
    int w = source.width();
    int h = source.height();

    QImage Edge(w,h,QImage::Format_RGB32);

    for( int i = 0; i< h; i++){
   //卷积操作
        for(int j = 0; j < w; j++){
            double Gx =  (-1)* QColor(source.pixel(getIndex(j-1,w),getIndex(i-1,h))).red()
                        +(-2)*QColor(source.pixel(getIndex(j,w),getIndex(i-1,h))).red()
                        +(-1)*QColor(source.pixel(getIndex(j+1,w),getIndex(i-1,h))).red()
                        +QColor(source.pixel(getIndex(j-1,w),getIndex(i+1,h))).red()
                        +2*QColor(source.pixel(getIndex(j,w),getIndex(i+1,h))).red()
                        +QColor(source.pixel(getIndex(j+1,w),getIndex(i+1,h))).red();

            double Gy =  QColor(source.pixel(getIndex(j-1,w),getIndex(i-1,h))).red()
                    +(2)*QColor(source.pixel(getIndex(j-1,w),getIndex(i,h))).red()
                    +(1)*QColor(source.pixel(getIndex(j-1,w),getIndex(i+1,h))).red()
                    +(-1)*QColor(source.pixel(getIndex(j+1,w),getIndex(i-1,h))).red()
                    +(-2)*QColor(source.pixel(getIndex(j+1,w),getIndex(i,h))).red()
                    +(-1)*QColor(source.pixel(getIndex(j+1,w),getIndex(i+1,h))).red();

           double G = sqrt(Gx*Gx+Gy*Gy);

            QRgb pixel;
            if(G>Gmax)
              pixel = qRgb(255,255,255);
            else
              pixel = qRgb(0,0,0);
            Edge.setPixel(j,i,pixel);
        }
    }
    return Edge;
}

 

2019-12-09 10:24:40 LLeetion 阅读数 42

1.边缘检测函数

1.1Sobel算子边缘检测

function OutImage = SobelOperate(InputImage,Direction)
%================================================================
% 功能:Sobel边缘检测
% 参数:InputImage为输入单通道图像,Dirction为模板方向,
% Direction=1水平,Direction=1垂直,Direction=1综合
% 返回值:OutImage为InputImage同维数组
% 主要思路:利用Sobel算子,计算相关
% 备注:如果图像为多通道则需要重复调用
% 调用方法:OutImage = FilterGauss(InputImage)
% 日期:2019.12.02
% 作者:Leetion
[iLimit,jLimit] = size(InputImage);
OutImage = double(InputImage);
switch(Direction)
    case 1
        ConvAarray =double([1 2 1;0 0 0;-1 -2 -1]);
        for yIndex = 2:iLimit-1
            for xIndex = 2:jLimit-1
                NeighbourArray = [InputImage(yIndex-1,xIndex-1) InputImage(yIndex-1,xIndex) InputImage(yIndex-1,xIndex+1);...
                    InputImage(yIndex,xIndex-1) InputImage(yIndex,xIndex) InputImage(yIndex,xIndex+1);...
                    InputImage(yIndex+1,xIndex-1) InputImage(yIndex+1,xIndex) InputImage(yIndex+1,xIndex+1)];
                OutImage(yIndex,xIndex) = abs(sum(sum(ConvAarray.*double(NeighbourArray))));
            end
        end
    case 2
        ConvAarray  =double([1 0 -1;2 0 -2;1 0 -1]);
        for yIndex = 2:iLimit-1
            for xIndex = 2:jLimit-1
                NeighbourArray = [InputImage(yIndex-1,xIndex-1) InputImage(yIndex-1,xIndex) InputImage(yIndex-1,xIndex+1);...
                    InputImage(yIndex,xIndex-1) InputImage(yIndex,xIndex) InputImage(yIndex,xIndex+1);...
                    InputImage(yIndex+1,xIndex-1) InputImage(yIndex+1,xIndex) InputImage(yIndex+1,xIndex+1)];
                OutImage(yIndex,xIndex) = abs(sum(sum(ConvAarray.*double(NeighbourArray))));
            end
        end
    case 0
        ConvAarray1 =double([1 2 1;0 0 0;-1 -2 -1]);
        ConvAarray2 = double([1 0 -1;2 0 -2;1 0 -1]);
        OutImage1 = double(InputImage);
        OutImage2 = double(InputImage);
        for yIndex = 2:iLimit-1
            for xIndex = 2:jLimit-1
                NeighbourArray = [InputImage(yIndex-1,xIndex-1) InputImage(yIndex-1,xIndex) InputImage(yIndex-1,xIndex+1);...
                    InputImage(yIndex,xIndex-1) InputImage(yIndex,xIndex) InputImage(yIndex,xIndex+1);...
                    InputImage(yIndex+1,xIndex-1) InputImage(yIndex+1,xIndex) InputImage(yIndex+1,xIndex+1)];
                OutImage1(yIndex,xIndex) = sum(sum(ConvAarray1.*double(NeighbourArray)));
                OutImage2(yIndex,xIndex) = sum(sum(ConvAarray2.*double(NeighbourArray)));
                OutImage(yIndex,xIndex) = (abs(OutImage1(yIndex,xIndex))+abs(OutImage2(yIndex,xIndex)));
                %                 OutImage(yIndex,xIndex) = uint8(sqrt(double((OutImage1(yIndex,xIndex))^2+abs(OutImage2(yIndex,xIndex))^2)));
            end
        end
end
OutImage = mat2gray(OutImage);
end

1.2Prewitt算子边缘检测

function OutImage = PrewittOperate(InputImage,Direction)
%================================================================
% 功能:Prewitt边缘检测
% 参数:InputImage为输入单通道图像,Dirction为模板方向,
% Direction=1水平,Direction=1垂直,Direction=1综合
% 返回值:OutImage为InputImage同维数组
% 主要思路:利用Prewitt算子,计算相关
% 备注:如果图像为多通道则需要重复调用
% 调用方法:OutImage = FilterGauss(InputImage)
% 日期:2019.12.02
% 作者:Leetion
[iLimit,jLimit] = size(InputImage);
OutImage = double(InputImage);
switch(Direction)
    case 1
        ConvAarray = double([1 1 1;0 0 0;-1 -1 -1]);
        for yIndex = 2:iLimit-1
            for xIndex = 2:jLimit-1
                NeighbourArray = [InputImage(yIndex-1,xIndex-1) InputImage(yIndex-1,xIndex) InputImage(yIndex-1,xIndex+1);...
                    InputImage(yIndex,xIndex-1) InputImage(yIndex,xIndex) InputImage(yIndex,xIndex+1);...
                    InputImage(yIndex+1,xIndex-1) InputImage(yIndex+1,xIndex) InputImage(yIndex+1,xIndex+1)];
                OutImage(yIndex,xIndex) = abs(sum(sum(ConvAarray.*double(NeighbourArray))));
            end
        end
    case 2
        ConvAarray  = double([1 0 -1;1 0 -1;1 0 -1]);
        for yIndex = 2:iLimit-1
            for xIndex = 2:jLimit-1
                NeighbourArray = [InputImage(yIndex-1,xIndex-1) InputImage(yIndex-1,xIndex) InputImage(yIndex-1,xIndex+1);...
                    InputImage(yIndex,xIndex-1) InputImage(yIndex,xIndex) InputImage(yIndex,xIndex+1);...
                    InputImage(yIndex+1,xIndex-1) InputImage(yIndex+1,xIndex) InputImage(yIndex+1,xIndex+1)];
                OutImage(yIndex,xIndex) = abs(sum(sum(ConvAarray.*double(NeighbourArray))));
            end
        end
    case 0
        ConvAarray1 = double([1 1 1;0 0 0;-1 -1 -1]);
        ConvAarray2 = double([1 0 -1;1 0 -1;1 0 -1]);
        OutImage1 = double(InputImage);
        OutImage2 = double(InputImage);
        for yIndex = 2:iLimit-1
            for xIndex = 2:jLimit-1
                NeighbourArray = [InputImage(yIndex-1,xIndex-1) InputImage(yIndex-1,xIndex) InputImage(yIndex-1,xIndex+1);...
                    InputImage(yIndex,xIndex-1) InputImage(yIndex,xIndex) InputImage(yIndex,xIndex+1);...
                    InputImage(yIndex+1,xIndex-1) InputImage(yIndex+1,xIndex) InputImage(yIndex+1,xIndex+1)];
                OutImage1(yIndex,xIndex) = sum(sum(ConvAarray1.*double(NeighbourArray)));
                OutImage2(yIndex,xIndex) = sum(sum(ConvAarray2.*double(NeighbourArray)));
                OutImage(yIndex,xIndex) = abs(OutImage1(yIndex,xIndex))+abs(OutImage2(yIndex,xIndex));
%                 OutImage(yIndex,xIndex) = uint8(sqrt(double((OutImage1(yIndex,xIndex))^2+abs(OutImage2(yIndex,xIndex))^2)));
            end
        end
end
OutImage = mat2gray(OutImage);
end

1.3Roberts算子边缘检测

function OutImage = RobertsOperate(InputImage,Direction)
%================================================================
% 功能:Roberts边缘检测
% 参数:InputImage为输入单通道图像,Dirction为模板方向,
% Direction=1水平,Direction=1垂直,Direction=1综合
% 返回值:OutImage为InputImage同维数组
% 主要思路:利用Roberts算子,计算相关
% 备注:如果图像为多通道则需要重复调用
% 调用方法:OutImage = FilterGauss(InputImage)
% 日期:2019.12.02
% 作者:Leetion
[iLimit,jLimit] = size(InputImage);
OutImage = double(InputImage);
switch(Direction)
    case 1
        ConvAarray = double([-1 0;0 1]);
        for yIndex = 1:iLimit-1
            for xIndex = 1:jLimit-1
                NeighbourArray = [ InputImage(yIndex,xIndex) InputImage(yIndex,xIndex+1);...
                    InputImage(yIndex+1,xIndex) InputImage(yIndex+1,xIndex+1)];
                OutImage(yIndex,xIndex) = abs(sum(sum(ConvAarray.*double(NeighbourArray))));
            end
        end
    case 2
        ConvAarray  = double([0 -1;1 0]);
        for yIndex = 1:iLimit-1
            for xIndex = 1:jLimit-1
                NeighbourArray = [ InputImage(yIndex,xIndex) InputImage(yIndex,xIndex+1);...
                    InputImage(yIndex+1,xIndex) InputImage(yIndex+1,xIndex+1)];
                OutImage(yIndex,xIndex) = abs(sum(sum(ConvAarray.*double(NeighbourArray))));
            end
        end
    case 0
        ConvAarray1 = double([-1 0;0 1]);
        ConvAarray2 = double([0 -1;1 0]);
        OutImage1 = double(InputImage);
        OutImage2 = double(InputImage);
        for yIndex = 1:iLimit-1
            for xIndex = 1:jLimit-1
               NeighbourArray = [ InputImage(yIndex,xIndex) InputImage(yIndex,xIndex+1);...
                    InputImage(yIndex+1,xIndex) InputImage(yIndex+1,xIndex+1)];
                OutImage1(yIndex,xIndex) = double(sum(sum(ConvAarray1.*double(NeighbourArray))));
                OutImage2(yIndex,xIndex) = double(sum(sum(ConvAarray2.*double(NeighbourArray))));
                OutImage(yIndex,xIndex) = (abs(OutImage1(yIndex,xIndex))+abs(OutImage2(yIndex,xIndex)));
                %                 OutImage(yIndex,xIndex) = uint8(sqrt(double((OutImage1(yIndex,xIndex))^2+abs(OutImage2(yIndex,xIndex))^2)));
            end
        end
end
OutImage = mat2gray(OutImage);
end

1.4LoG算子边缘检测

function OutImage = LogOperate(InputImage)
% 功能:LoG边缘检测
% 参数:InputImage为输入单通道图像
% 返回值:OutImage为InputImage同维数组
% 主要思路:利用LoG算子,计算相关
% 备注:如果图像为多通道则需要重复调用
% 调用方法:OutImage = LogOperate(InputImage)
% 日期:2019.12.02
% 作者:Leetion
[iLimit,jLimit] = size(InputImage);
OutImage = double(InputImage);
ConvAarray = [0 0 -1 0 0;0 -1 -2 -1 0;-1 -2 16 -2 -1;0 -1 -2 -1 0; 0 0 -1 0 0];
for yIndex = 3:iLimit-2
    for xIndex = 3:jLimit-2
        NeighbourArray = [InputImage(yIndex-2,xIndex-2) InputImage(yIndex-2,xIndex-1) InputImage(yIndex-2,xIndex) InputImage(yIndex-2,xIndex+1) InputImage(yIndex-2,xIndex+2);...
            InputImage(yIndex-1,xIndex-2) InputImage(yIndex-1,xIndex-1) InputImage(yIndex-1,xIndex) InputImage(yIndex-1,xIndex+1) InputImage(yIndex-1,xIndex+2);...
            InputImage(yIndex,xIndex-2) InputImage(yIndex,xIndex-1) InputImage(yIndex,xIndex) InputImage(yIndex,xIndex+1) InputImage(yIndex,xIndex+2);...
            InputImage(yIndex+1,xIndex-2) InputImage(yIndex+1,xIndex-1) InputImage(yIndex+1,xIndex) InputImage(yIndex+1,xIndex+1) InputImage(yIndex+1,xIndex+2);...
            InputImage(yIndex+2,xIndex-2) InputImage(yIndex+2,xIndex-1) InputImage(yIndex+2,xIndex) InputImage(yIndex+2,xIndex+1) InputImage(yIndex+2,xIndex+2)];
        OutImage(yIndex,xIndex) = abs(sum(sum(ConvAarray.*double(NeighbourArray))));
    end
end
OutImage  = mat2gray(OutImage);
end


2.边缘检测测试脚本测试脚本

2.1Sobel算子边缘检测测试脚本

%================================================================
% 功能:Sobel边缘测试
% 主要思路:
% 备注:
% 日期:2019.12.02
% 作者:Leetion
clc,clear
close all 
InputImage = imread("rec1.bmp");
InputImage=double(InputImage);
% InputImage = imnoise(InputImage,'salt & pepper');
subplot(2,2,1)
imshow(InputImage);
title("原图");
subplot(2,2,2)
OutImage = SobelOperate(InputImage,1);
imshow(OutImage);
title("横向");
subplot(2,2,3)
OutImage = SobelOperate(InputImage,2);
imshow(OutImage);
title("纵向");
subplot(2,2,4)
OutImage = SobelOperate(InputImage,0);
imshow(OutImage);
title("综合");


2.2Prewitt算子边缘检测测试脚本测试脚本

%================================================================
% 功能:Prewitt边缘测试
% 主要思路:
% 备注:
% 日期:2019.12.02
% 作者:Leetion
clear all
close all 
InputImage = imread("rec1.bmp");
subplot(2,2,1)
imshow(InputImage);
title("原图");
subplot(2,2,2)
OutImage = PrewittOperate(InputImage,1);
imshow(OutImage);
title("横向");
subplot(2,2,3)
OutImage = PrewittOperate(InputImage,2);
imshow(OutImage);
title("纵向");
subplot(2,2,4)
OutImage = PrewittOperate(InputImage,0);
imshow(OutImage);
title("综合");

2.3Roberts算子边缘检测测试脚本

%================================================================
% 功能:Roberts边缘测试
% 主要思路:
% 备注:
% 日期:2019.12.02
% 作者: Leetion
clear all
close all 
InputImage = imread("rec2.bmp");
% InputImage = imnoise(InputImage,'salt & pepper');
subplot(2,2,1)
imshow(InputImage);
title("原图");
subplot(2,2,2)
OutImage = RobertsOperate(InputImage,1);
imshow(OutImage);
title("45°");
subplot(2,2,3)
OutImage = RobertsOperate(InputImage,2);
imshow(OutImage);
title("135°");
subplot(2,2,4)
OutImage = RobertsOperate(InputImage,0);
imshow(OutImage);
title("综合");

2.4LoG算子边缘检测测试脚本

%================================================================
% 功能:LoG算子测试
% 主要思路:
% 备注:
% 日期:2019.12.02
% 作者:Leeton
clc,clear
close all 
InputImage = imread("rec1.bmp");
% InputImage = imnoise(InputImage,'salt & pepper');
subplot(1,2,1)
imshow(InputImage);
title("原图");
subplot(1,2,2)
OutImage = LogOperate(InputImage);
imshow(OutImage);
title("LoG边缘检测");

3.边缘检测结果

3.1Sobel算子边缘检测结果

Fig1.Sobel算子边缘检测

3.2Prewitt算子边缘检测结果

Fig2.Prewitt算子边缘检测

3.3Roberts算子边缘检测结果

Fig3.Roberts算子边缘检测

3.4LoG算子边缘检测结果

Fig4.LoG算子边缘检测

4.探究噪声对边缘检测的影响

4.1噪声对Sobel算子的影响

Fig5.Sobel加噪

4.2噪声对Prewitt的影响

Fig6.Prewitt加噪

4.3噪声对Roberts的影响

Fig7.Roberts加噪

4.4噪声对LoG的影响

Fig8.LoG加噪

 

2018-08-26 21:46:04 qq_40261818 阅读数 3157

项目:【基于FPGA verilog 边缘检测图像处理sobel算子实现

项目介绍:Sobel 边缘检测算子是一阶导数,Sobel边缘检测算法的实现是利用3*3个上下左右相邻的像素点进行计算的,根据上下左右像素点的值计算出图像的水平和垂直的梯度,然后将水平和垂直梯度根据对应的算法计算出梯度值,如果这个梯度值大于设定的阀值,那么这个像素点就是边缘部分,否则就认为该像素点不是图像的边缘部分。如图1为3×3区域相邻的像素点,图2为Sobel水平梯度算子,图3为Sobel垂直梯度算子。

GX = (G3+2 *G6 + G9 ) - (G1 +2 *G4 + G7 )

GY = (G7+2* G8 + G9 ) - (G1 +2* G2 + G3 )

| G | =(GX^2+ GY^2)^1/2

判断| G |是否大于阈值,若大于阈值让他为FF否则为00.

项目构架:

RTL图:

结果展示:

                 原图

 

 

 

                 结果图

因为阈值不同,所以显示的效果不一样,有兴趣的同学可以调一下阈值自己实现一下。

 

本文为原创博客,未经允许请勿盗用谢谢!  转载请标注地址:https://blog.csdn.net/qq_40261818/article/details/82084701

彩色图像边缘检测

博文 来自: lpsl1882
没有更多推荐了,返回首页