边缘检测Word文档下载推荐.docx

上传人:b****4 文档编号:6232652 上传时间:2023-05-06 格式:DOCX 页数:19 大小:20.99KB
下载 相关 举报
边缘检测Word文档下载推荐.docx_第1页
第1页 / 共19页
边缘检测Word文档下载推荐.docx_第2页
第2页 / 共19页
边缘检测Word文档下载推荐.docx_第3页
第3页 / 共19页
边缘检测Word文档下载推荐.docx_第4页
第4页 / 共19页
边缘检测Word文档下载推荐.docx_第5页
第5页 / 共19页
边缘检测Word文档下载推荐.docx_第6页
第6页 / 共19页
边缘检测Word文档下载推荐.docx_第7页
第7页 / 共19页
边缘检测Word文档下载推荐.docx_第8页
第8页 / 共19页
边缘检测Word文档下载推荐.docx_第9页
第9页 / 共19页
边缘检测Word文档下载推荐.docx_第10页
第10页 / 共19页
边缘检测Word文档下载推荐.docx_第11页
第11页 / 共19页
边缘检测Word文档下载推荐.docx_第12页
第12页 / 共19页
边缘检测Word文档下载推荐.docx_第13页
第13页 / 共19页
边缘检测Word文档下载推荐.docx_第14页
第14页 / 共19页
边缘检测Word文档下载推荐.docx_第15页
第15页 / 共19页
边缘检测Word文档下载推荐.docx_第16页
第16页 / 共19页
边缘检测Word文档下载推荐.docx_第17页
第17页 / 共19页
边缘检测Word文档下载推荐.docx_第18页
第18页 / 共19页
边缘检测Word文档下载推荐.docx_第19页
第19页 / 共19页
亲,该文档总共19页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

边缘检测Word文档下载推荐.docx

《边缘检测Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《边缘检测Word文档下载推荐.docx(19页珍藏版)》请在冰点文库上搜索。

边缘检测Word文档下载推荐.docx

由于建筑物图像的特殊性,我们可以发现,处理该类型图像轮廓时,并不需要对梯度方向进行运算,所以程序并没有给出各向同性Sobel算子的处理方法。

由于Sobel算子是滤波算子的形式,用于提取边缘,可以利用快速卷积函数,简单有效,因此应用广泛。

美中不足的是,Sobel算子并没有将图像的主体与背景严格地区分开来,换言之就是Sobel算子没有基于图像灰度进行处理,由于Sobel算子没有严格地模拟人的视觉生理特征,所以提取的图像轮廓有时并不能令人满意。

在观测一幅图像的时候,我们往往首先注意的是图像与背景不同的部分,正是这个部分将主体突出显示,基于该理论,我们可以给出阈值化轮廓提取算法,该算法已在数学上证明当像素点满足正态分布时所求解是最优的。

上面的算子是利用一阶导数的信息,属于梯度算子范畴。

Laplacian算子:

这是二阶微分算子。

其具有各向同性,即与坐标轴方向无关,坐标轴旋转后梯度结果不变。

但是,其对噪声比较敏感,所以,图像一般先经过平滑处理,因为平滑处理也是用模板进行的,所以,通常的分割算法都是把Laplacian算子和平滑算子结合起来生成一个新的模板。

Laplacian算子一般不以其原始形式用于边缘检测,因为其作为一个二阶导数,Laplacian算子对噪声具有无法接受的敏感性;

同时其幅值产生算边缘,这是复杂的分割不希望有的结果;

最后Laplacian算子不能检测边缘的方向;

所以Laplacian在分割中所起的作用包括:

(1)利用它的零交叉性质进行边缘定位;

(2)确定一个像素是在一条边缘暗的一面还是亮的一面;

一般使用的是高斯型拉普拉斯算子(LaplacianofaGaussian,LoG),由于二阶导数是线性运算,利用LoG卷积一幅图像与首先使用高斯型平滑函数卷积改图像,然后计算所得结果的拉普拉斯是一样的。

所以在LoG公式中使用高斯函数的目的就是对图像进行平滑处理,使用Laplacian算子的目的是提供一幅用零交叉确定边缘位置的图像;

图像的平滑处理减少了噪声的影响并且它的主要作用还是抵消由Laplacian算子的二阶导数引起的逐渐增加的噪声影响。

微分算子在图像处理中扮演重要的角色,其算法实现简单,而且边缘检测的效果又较好,因此这些基本的微分算子是学习图像处理过程中的必备方法,下面着重讨论几种常见的微分算子。

1.Sobel

其主要用于边缘检测,在技术上它是以离散型的差分算子,用来运算图像亮度函数的梯度的近似值,缺点是Sobel算子并没有将图像的主题与背景严格地区分开来,换言之就是Sobel算子并没有基于图像灰度进行处理,由于Sobel算子并没有严格地模拟人的视觉生理特征,所以提取的图像轮廓有时并不能令人满意,算法具体实现很简单,就是3*3的两个不同方向上的模板运算,这里不再写出。

2.Robert算子

根据任一相互垂直方向上的差分都用来估计梯度,Robert算子采用对角方向相邻像素只差

3.Prewitt算子

该算子与Sobel算子类似,只是权值有所变化,但两者实现起来功能还是有差距的,据经验得知Sobel要比Prewitt更能准确检测图像边缘。

4.Laplacian算子

拉普拉斯算子是一种二阶微分算子,若只考虑边缘点的位置而不考虑周围的灰度差时可用该算子进行检测。

对于阶跃状边缘,其二阶导数在边缘点出现零交叉,并且边缘点两旁的像素的二阶导数异号。

5.Canny算子

该算子功能比前面几种都要好,但是它实现起来较为麻烦,Canny算子是一个具有滤波,增强,检测的多阶段的优化算子,在进行处理前,Canny算子先利用高斯平滑滤波器来平滑图像以除去噪声,Canny分割算法采用一阶偏导的有限差分来计算梯度幅值和方向,在处理过程中,Canny算子还将经过一个非极大值抑制的过程,最后Canny算子还采用两个阈值来连接边缘。

下面算法是基于的算法不可能直接运行,只是我把Canny的具体实现步骤写了出来,若需用还要自己写。

该算子具体实现方法:

//anny.cpp:

implementationoftheCannyclass.

//

//////////////////////////////////////////////////////////////////////

#include"

anny.h"

math.h"

//#include"

algorithms.h"

algorithm.h"

stdlib.h"

maths.h"

//usingnamespacestd;

//Construction/Destruction

Canny:

:

Canny(intPicHeight,intPicWidth,double**PicData,doublePicSigma,doublePicRatioLow,doublePicRatioHigh)

{

iHeight=PicHeight;

iWidth=PicWidth;

iData=PicData;

sigma=PicSigma;

dRatioLow=PicRatioLow;

dRatioHigh=PicRatioHigh;

}

~Canny()

voidCanny:

CannyArith(int**iEdgePoint)

inti;

int**iGradX;

//指向x方向导数的指针

int**iGradY;

//指向y方向导数的指针

int**iExtent;

//梯度的幅度

iGradX=newint*[iHeight];

for(i=0;

i&

lt;

iHeight;

i++)

iGradX[i]=newint[iWidth];

iGradY=newint*[iHeight];

iGradY[i]=newint[iWidth];

iExtent=newint*[iHeight];

iExtent[i]=newint[iWidth];

//对原图象进行滤波

GaussionSmooth();

//计算X,Y方向上的方向导数

DirGrad(iGradX,iGradY);

//计算梯度的幅度

GradExtent(iGradX,iGradY,iExtent);

//应用non-maximum抑制

NonMaxSuppress(iExtent,iGradX,iGradY,iEdgePoint);

//应用Hysteresis,找到所有的边界

Hysteresis(iExtent,iEdgePoint);

//释放内存

delete[]*(iGradX+i);

deleteiGradX;

delete[]*(iGradY+i);

deleteiGradY;

delete[]*(iExtent+i);

deleteiExtent;

GaussionSmooth()

inti,j,k;

//循环变量

intiWindowSize;

//记录模板大小的变量

intiHalfLen;

//模板大小的一半

double*pdKernel;

//模板各点的权值

doubledDotMul;

//模板与对应像素点的卷积和

doubledWeightSum;

//模板的权值累加和

double**dTemp;

//记录图像数据的中间变量

//开辟空间

dTemp=newdouble*[iHeight];

i++)

dTemp[i]=newdouble[iWidth];

//获得模板长度和模板的各个权值

MakeGauss(&

amp;

pdKernel,&

iWindowSize);

//得到模板的一半长度

iHalfLen=iWindowSize/2;

//对图像对水方向根据模板进行平滑

{

for(j=0;

j&

iWidth;

j++)

dDotMul=0;

dWeightSum=0;

for(k=(-iHalfLen);

k&

=iHalfLen;

k++)

if((k+j&

gt;

=0)&

&

(k+j&

iWidth))

dDotMul+=iData[i][j+k]*pdKernel[k+iHalfLen];

dWeightSum+=pdKernel[k+iHalfLen];

}

dTemp[i][j]=dDotMul/dWeightSum;

//对图像垂直方向上根据模板的转置进行平滑(注意图像数据是在水平平滑之后进行的)

iHeight))

dDotMul+=dTemp[j+k][i]*pdKernel[k+iHalfLen];

iData[j][i]=dDotMul/dWeightSum;

//空间释放

delete[]pdKernel;

pdKernel=NULL;

delete[]*(dTemp+i);

deletedTemp;

MakeGauss(double**pdKernel,int*iWindowSize)

intnCenter;

//确定高斯模板的一半长度

doubledDistance;

//一维高斯模板各点离中心点的距离

doublePI=3.1415926;

//圆周率

doubledValue;

//中间变量,记录高斯模板各点的权值(未经归一化)

doubledSum=0;

//中间变量,记录高斯模板各点权值的总和

*iWindowSize=int(1+2*int(3*sigma+0.5));

//确定一维高斯模板长度,根据概率论的知识,选取[-3*sigma,3*sigma]以内的数据。

nCenter=(*iWindowSize)/2;

//得到一半长度

*pdKernel=newdouble[*iWindowSize];

//开辟记录各点权值的空间

//利用高斯分布函数(正太分布)确定各点的权值,主要是根据高斯分布离中心点的距离越远,所取的值就越小,这与图像有些

//相似,离中心点越远,对中心点的影响就越小。

(*iWindowSize);

dDistance=double(i-nCenter);

//高斯分布函数求值

dValue=exp((-1/2)*dDistance*dDistance/(sigma*sigma))/(sqrt(2*PI)*sigma);

(*pdKernel)[i]=dValue;

dSum+=dValue;

//归一化(因为要不改变原图像的灰度区域,就必须保证各权值之和为1

(*pdKernel)[i]/=dSum;

DirGrad(int**iGradX,int**iGradY)

inti,j,temp1,temp2;

//水平方向的方向导数(下面都是用min和max对边界值做了相应的处理)

if(iWidth-1&

j+1)

temp1=iWidth-1;

else

temp1=j+1;

if(0&

j-1)

temp2=j-1;

temp2=0;

iGradX[i][j]=int(iData[i][temp1]-iData[i][temp2]);

//垂直方向的方向导数

if(iHeight-1&

temp1=iHeight-1;

iGradY[j][i]=int(iData[temp1][i]-iData[temp2][i]);

GradExtent(int**iGradX,int**iGradY,int**iExtent)

inti,j;

doubleiTemp1,iTemp2;

iTemp1=iGradX[i][j]*iGradX[i][j];

iTemp2=iGradY[i][j]*iGradY[i][j];

iExtent[i][j]=int(sqrt(iTemp1+iTemp2)+0.5);

NonMaxSuppress(int**iExtent,int**iGradX,int**iGradY,int**dUnchRst)

intgx,gy;

//记录像素点X,Y方向的方向导数值

intg1,g2,g3,g4;

//各个领域的梯度值

doubleweight;

//比重

doubledTemp1,dTemp2,dTemp;

//中间变量

//处理边缘值(边缘点不可能是边界点

dUnchRst[i][0]=0;

dUnchRst[i][iWidth-1]=0;

dUnchRst[0][j]=0;

dUnchRst[iHeight-1][j]=0;

//标记有可能是边界点的像素点

for(i=1;

iHeight-1;

for(j=1;

iWidth-1;

//梯度值是0的像素点不可能是边界点

if(iExtent[i][j]==0)

dUnchRst[i][j]=0;

dTemp=iExtent[i][j];

gx=iGradX[i][j];

gy=iGradY[i][j];

//下面都是判断当前像素点的梯度值和其领域像素点的梯度值,如大于就有可能是边界点,如小于就不可能是边界点

if(abs(gy)&

abs(gx))

weight=double(abs(gx)/abs(gy));

g2=iExtent[i-1][j];

g4=iExtent[i+1][j];

if(gx*gy&

0)

g1=iExtent[i-1][j-1];

g3=iExtent[i+1][j+1];

g1=iExtent[i-1][j+1];

g3=iExtent[i+1][j-1];

weight=double(abs(gy)/abs(gx));

g2=iExtent[i][j+1];

g4=iExtent[i][j-1];

g1=iExtent[i+1][j+1];

g3=iExtent[i-1][j-1];

dTemp1=weight*g1+(1-weight)*g2;

dTemp2=weight*g3+(1-weight)*g4;

//当大于的时候就有可能是边界点

if(dTemp&

=dTemp1&

dTemp&

=dTemp2)

dUnchRst[i][j]=128;

dUnchRst[i][j]=0;

}

Hysteresis(int**iExtent,int**iEdgePoint)

intiThreHigh;

intiThreLow;

SetThreshold(iExtent,&

iThreHigh,&

iThreLow,iEdgePoint);

if((iEdgePoint[i][j]==128)&

(iExtent[i][j]&

=iThreHigh))

iEdgePoint[i][j]=255;

TraceEdge(i,j,iThreLow,iEdgePoint,iExtent);

//那些还没有被设置为边界点的象素已经不可能成为边界点

if(iEdgePoint[i][j]!

=255)

//设置为非边界点

iEdgePoint[i][j]=0;

SetThreshold(int**iExtent,int*iThreHigh,int*iThreLow,int**iEdgePoint)

intGradHist[1024];

//统计梯度直方图的数据,梯度最大值不可能超过1024

intiEdgeNum;

//边界点的数量

intiGradMax=0;

//边界点的梯度最大值

intiHighCount;

//根据iRatioHigh小于高阈值像素的个数

//初始化

1024;

GradHist[i]=0;

//梯度直方图统计

if(iEdgePoint[i][j]==128)

GradHist[iExtent[i][j]]++;

iEdgeNum=0;

//找出最大梯度和统计边界点的个数

if(Gr

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2