ImageVerifierCode 换一换
格式:DOC , 页数:14 ,大小:81KB ,
资源ID:7438990      下载积分:10 金币
快捷注册下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

开通VIP
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/7438990.html】到电脑端继续下载(重复下载【60天内】不扣币)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

开通VIP折扣优惠下载文档

            查看会员权益                  [ 下载后找不到文档?]

填表反馈(24小时):  下载求助     关注领币    退款申请

开具发票请登录PC端进行申请

   平台协调中心        【在线客服】        免费申请共赢上传

权利声明

1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。

注意事项

本文(哈夫变换和Canny边缘检测算法及其实现代码.doc)为本站上传会员【xrp****65】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。 服务填表

哈夫变换和Canny边缘检测算法及其实现代码.doc

1、哈夫变换和Canny边缘检测算法 摘 要在图象边缘检测中往往要求所检测到的边缘具有封闭特性,本文详细地分析了目前常用的两种算法:哈夫变换和Canny边缘检测算法,最后,探讨边缘算子应满足的准则。 关键词边缘检测;闭合性;哈夫变换;Canny算子 1引言 图象的边缘是指图象局部区域亮度变化显著的部分,该区域的灰度剖面一般可以看作是一个阶跃,既从一个灰度值在很小的缓冲区域内急剧变化到另一个灰度相差较大的灰度值。图象的边缘部分集中了图象的大部分信息,图象边缘的确定与提取对于整个图象场景的识别与理解是非常重要的,同时也是图象分割所依赖的重要特征,边缘检测主要是图象的灰度变化的

2、度量、检测和定位,自从1959提出边缘检测以来,经过五十多年的发展,已有许多中不同的边缘检测方法。在我们常用的几种用于边缘检测的算子中Laplace算子常常会产生双边界;而其他一些算子如Sobel算子又往往会形成不闭合区域。本文主要讨论了在边缘检测中,获取封闭边界区域的算法。 2 图象边缘检测的基本步骤 (1)滤波。边缘检测主要基于导数计算,但受噪声影响。但滤波器在降低噪声的同时也导致边缘强度的损失。 (2)增强。增强算法将邻域中灰度有显著变化的点突出显示。一般通过计算梯度幅值完成。 (3)检测。但在有些图象中梯度幅值较大的并不是边缘点。最简单的边缘检测是

3、梯度幅值阈值判定。 (4)定位。精确确定边缘的位置。 图1 边缘检测酸法的基本步骤 3 边界闭合的算法 3.1 哈夫变换[3] 由于噪声的存在,用各种算子得到的边缘象素不连续,但是由于边缘象素之间有一定的连续性,我们就可以根据边缘象素在梯度幅度或梯度方向上的连续性把他们连接起来。具体说来,如果象素(s,t)在象素(x,y)的领域且它们的梯度幅度与梯度方向在给定的阈值下满足: T是幅度阈值;A是角度阈值; 那么,如对所有的边缘象素都进行上述的判断和连接就可以得到一个闭合的边界。哈夫变换方法是利用图像得全局特性而对目标轮廓进行直接检测的方法,在

4、已知区域形状的条件下,哈夫变换可以准确地捕获到目标的边界(连续的获不连续的),并最终以连续曲线的形式输出变换结果,该变换可以从强噪声环境中将已知形状的目标准确得分割提取出来。 哈夫变换的核心思想是: 点—线的对偶性(duality)。通过变换将图象从图像控件转换到参数空间,在图像空间中一条过点(x,y)的直线方程为y=px+q,通过代数变换可以转换为另一种形式p=-px+y,即参数空间中过点(p,q)的一条直线,如果在图像空间中保持直线的斜率和截距的不变,其在参数空间必定过点(p,q),这也就说明,在图像空间中共线的点对应参数空间共点的线. 哈夫变换就是根据上述点—线的对偶性把在图

5、象空间中存在的直线检测问题转换为参数空间中存在的点检测问题,后者的处理要比前者简单易行得多,只需简单地累加统计即可实现对边缘的检测. 哈夫变换不仅能检测直线等一阶曲线的目标,对于园、椭圆等高阶的曲线都可以检测出来。如圆的方程为: 其参数空间是一个3D空间A(a,b,r),原理与检测直线上的点相同,只是复杂性增加了。如果圆的半径r己知,则问题又回到了2D空间A(a,b) 哈夫变换对已知目标的检测过程受随机噪声和曲线中断等不利因素的影响很小,而且分割出的目标是直接放到另一个“干净”的缓存中的,因此可以做到零噪声,是相当有优势的。常规的哈夫变换在理论上能对所有可以写出具体

6、解析表达式的曲线进行目标检测,但是在实际处理时,经常待检测的目标不规则或是很难获取甚至根本没有解析式,此时就要采取广义上的哈夫变换来检测目标, 3.2最优的阶梯型边缘检测算法(canny边缘检测) 1.Canny边缘检测基本原理 (1)图象边缘检测必须满足两个条件:一能有效地抑制噪声;二必须尽量精确确定边缘的位置。 (2)根据对信噪比与定位乘积进行测度,得到最优化逼近算子。这就是Canny边缘检测算子。 (3)类似与Marr(LoG)边缘检测方法,也属于先平滑后求导数的方法。 2.Canny边缘检测算法: step1:用

7、高斯滤波器平滑图象; step2:用一阶偏导的有限差分来计算梯度的幅值和方向; step3:对梯度幅值进行非极大值抑制; step4:用双阈值算法检测和连接边缘。 step1:高斯平滑函数 step3:非极大值抑制 仅仅得到全局的梯度并不足以确定边缘,因此为确定边缘,必须保留局部梯度最大的点,而抑制非极大值。(non-maxima suppression,NMS) 解决方法:利用梯度的方向。 图2非极大值抑制 四个扇区的标号为0到3,对应3*3邻域的四种可能组合。 在每一点上,邻域的中心象素M与沿着梯度线的两个象

8、素相比。如果M的梯度值不比沿梯度线的两个相邻象素梯度值大,则令M=0。 即: step4:阈值化 减少假边缘段数量的典型方法是对N[i,j]使用一个阈值。将低于阈值的所有值赋零值。但问题是如何选取阈值? 解决方法:双阈值算法。双阈值算法对非极大值抑制图象作用两个阈值τ1和τ2,且2τ1≈τ2,从而可以得到两个阈值边缘图象N1[i,j]和N2[i,j]。由于N2[i,j]使用高阈值得到,因而含有很少的假边缘,但有间断(不闭合)。双阈值法要在N2[i,j]中把边缘连接成轮廓,当到达轮廓的端点时,该算法就在N1[i,j]的8邻点位置寻找可以连接到轮廓上的边缘

9、这样,算法不断地在N1[i,j]中收集边缘,直到将N2[i,j]连接起来为止。 4 边缘算子应满足的准则 若满足此准则,就能保证单边缘只有一个响应。 对一个算法的性能评价可分为两个阶段进行:计算假边缘与丢失边缘的数目;测量用于估计位置和方向的误差(或误差分布)。边缘检测算法的优劣也可用品质因数( Figure of Merit)来描述。Pratt品质因数是其中一种,它着重考虑了丢失了有效的边缘、边缘定位误差和将噪声判断为边缘等三种误差。 5 结束语 边缘检测在图象分割、模式识别、机器视觉等中都有重要作用,人们已研究出很多种边缘检测算法,而哈夫变换和can

10、ny边缘算子等是最经典的算法,人们已在这些经典算法基础上提出一些新的改进算法。 canny算子代码 void CreatGauss(double sigma, double **pdKernel, int *pnWidowSize); void GaussianSmooth(SIZE sz, LPBYTE pGray, LPBYTE pResult, double sigma); void Grad(SIZE sz, LPBYTE pGray, int *pGradX, int *pGradY, int *pMag); void NonmaxSuppress(int *pMag,

11、 int *pGradX, int *pGradY, SIZE sz, LPBYTE pNSRst); void EstimateThreshold(int *pMag, SIZE sz, int *pThrHigh, int *pThrLow, LPBYTE pGray, double dRatHigh, double dRatLow); void Hysteresis(int *pMag, SIZE sz, double dRatLow, double dRatHigh, LPBYTE pResult); void TraceEdge(int y, int x,

12、 int nThrLow, LPBYTE pResult, int *pMag, SIZE sz); void Canny(LPBYTE pGray, SIZE sz, double sigma, double dRatLow, double dRatHigh, LPBYTE pResult); #include "afx.h" #include "math.h" #include "canny.h" // 一维高斯分布函数,用于平滑函数中生成的高斯滤波系数 void CreatGauss(double sigma, double **pdKernel, int *

13、pnWidowSize) { LONG i; //数组中心点 int nCenter; //数组中一点到中心点距离 double dDis; //中间变量 double dValue; double dSum; dSum = 0; // [-3*sigma,3*sigma] 以内数据,会覆盖绝大部分滤波系数 *pnWidowSize = 1+ 2*ceil(3*sigma); nCenter = (*pnWidowSize)/2; *pdKernel = new double[*pnWidowSize]; //生成高斯数据 for(i=0;i<(*pnWidow

14、Size);i++) { dDis = double(i - nCenter); dValue = exp(-(1/2)*dDis*dDis/(sigma*sigma))/(sqrt(2*3.1415926)*sigma); (*pdKernel)[i] = dValue; dSum+=dValue; } //归一化 for(i=0;i<(*pnWidowSize);i++) { (*pdKernel)[i]/=dSum; } } //用高斯滤波器平滑原图像 void GaussianSmooth(SIZE sz, LPBYTE pGr

15、ay, LPBYTE pResult, double sigma) { LONG x, y; LONG i; //高斯滤波器长度 int nWindowSize; //窗口长度 int nLen; //一维高斯滤波器 double *pdKernel; //高斯系数与图像数据的点乘 double dDotMul; //滤波系数总和 double dWeightSum; double *pdTemp; pdTemp = new double[sz.cx*sz.cy]; //产生一维高斯数据 CreatGauss(sigma, &pdKernel, &nW

16、indowSize); nLen = nWindowSize/2; //x方向滤波 for(y=0;y=0 && (i+x)

17、i]; dWeightSum += pdKernel[nLen+i]; } } pdTemp[y*sz.cx+x] = dDotMul/dWeightSum; } } //y方向滤波 for(x=0; x=0 && (i+y)< sz.cy)

18、{ dDotMul += (double)pdTemp[(y+i)*sz.cx+x]*pdKernel[nLen+i]; dWeightSum += pdKernel[nLen+i]; } } pResult[y*sz.cx+x] = (unsigned char)dDotMul/dWeightSum; } } delete []pdKernel; pdKernel = NULL; delete []pdTemp; pdTemp = NULL; } // 方向导数,求梯度 void Grad(SIZE sz,

19、LPBYTE pGray,int *pGradX, int *pGradY, int *pMag) { LONG y,x; //x方向的方向导数 for(y=1;y

20、dY[y*sz.cx +x] = (int)(pGray[(y+1)*sz.cx +x] - pGray[(y-1)*sz.cx +x]); } } //求梯度 //中间变量 double dSqt1; double dSqt2; for(y=0; y

21、x + x]; pMag[y*sz.cx+x] = (int)(sqrt(dSqt1+dSqt2)+0.5); } } } //非最大抑制 void NonmaxSuppress(int *pMag, int *pGradX, int *pGradY, SIZE sz, LPBYTE pNSRst) { LONG y,x; int nPos; //梯度分量 int gx; int gy; //中间变量 int g1,g2,g3,g4; double weight; double dTmp,dTmp1,dTmp2; //设置图像边缘为不可能的分界点

22、 for(x=0;x

23、f(pMag[nPos] == 0) { pNSRst[nPos] = 0; } else { //当前点的梯度幅度 dTmp = pMag[nPos]; //x,y方向导数 gx = pGradX[nPos]; gy = pGradY[nPos]; //如果方向导数y分量比x分量大,说明导数方向趋向于y分量 if(abs(gy) > abs(gx)) { //计算插值比例 weight = fabs(gx)/fabs(

24、gy); g2 = pMag[nPos-sz.cx]; g4 = pMag[nPos+sz.cx]; //如果x,y两个方向导数的符号相同 //C 为当前像素,与g1-g4 的位置关系为: //g1 g2 // C // g4 g3 if(gx*gy>0) { g1 = pMag[nPos-sz.cx-1]; g3 = pMag[nPos+sz.cx+1]; } //如果x,y两个方向的方

25、向导数方向相反 //C是当前像素,与g1-g4的关系为: // g2 g1 // C // g3 g4 else { g1 = pMag[nPos-sz.cx+1]; g3 = pMag[nPos+sz.cx-1]; } } //如果方向导数x分量比y分量大,说明导数的方向趋向于x分量 else { //插值比例 weight = fabs(gy)/fabs(g

26、x); g2 = pMag[nPos+1]; g4 = pMag[nPos-1]; //如果x,y两个方向的方向导数符号相同 //当前像素C与 g1-g4的关系为 // g3 // g4 C g2 // g1 if(gx * gy > 0) { g1 = pMag[nPos+sz.cx+1]; g3 = pMag[nPos-sz.cx-1]; } //如果x,y两个方向导数的方

27、向相反 // C与g1-g4的关系为 // g1 // g4 C g2 // g3 else { g1 = pMag[nPos-sz.cx+1]; g3 = pMag[nPos+sz.cx-1]; } } //利用 g1-g4 对梯度进行插值 { dTmp1 = weight*g1 + (1-weight)*g2; dTmp2 = weight*g3 + (1-weight)*g4;

28、 //当前像素的梯度是局部的最大值 //该点可能是边界点 if(dTmp>=dTmp1 && dTmp>=dTmp2) { pNSRst[nPos] = 128; } else { //不可能是边界点 pNSRst[nPos] = 0; } } } } } } // 统计pMag的直方图,判定阈值 void EstimateThreshold(int *pMag, SIZE sz, int *pTh

29、rHigh, int *pThrLow, LPBYTE pGray, double dRatHigh, double dRatLow) { LONG y,x,k; //该数组的大小和梯度值的范围有关,如果采用本程序的算法 //那么梯度的范围不会超过pow(2,10) int nHist[256]; //可能边界数 int nEdgeNum; //最大梯度数 int nMaxMag; int nHighCount; nMaxMag = 0; //初始化 for(k=0;k<256;k++) { nHist[k] = 0; } //统计

30、直方图,利用直方图计算阈值 for(y=0;y

31、点是不可能为边界点的 //经过non-maximum suppression后有多少像素 nEdgeNum += nHist[k]; } //梯度比高阈值*pThrHigh 小的像素点总书目 nHighCount = (int)(dRatHigh * nEdgeNum + 0.5); k=1; nEdgeNum = nHist[1]; //计算高阈值 while((k<(nMaxMag-1)) && (nEdgeNum < nHighCount)) { k++; nEdgeNum += nHist[k]; } *pThrHigh = k;

32、//低阈值 *pThrLow = (int)((*pThrHigh) * dRatLow + 0.5); } //利用函数寻找边界起点 void Hysteresis(int *pMag, SIZE sz, double dRatLow, double dRatHigh, LPBYTE pResult) { LONG y,x; int nThrHigh,nThrLow; int nPos; //估计TraceEdge 函数需要的低阈值,以及Hysteresis函数使用的高阈值 EstimateThreshold(pMag, sz,&nThrHigh,&nThrLow,pRe

33、sult,dRatHigh,dRatLow); //寻找大于dThrHigh的点,这些点用来当作边界点, //然后用TraceEdge函数跟踪该点对应的边界 for(y=0;y= nThrHigh)) { //设置该点为边界点

34、 pResult[nPos] = 255; TraceEdge(y,x,nThrLow,pResult,pMag,sz); } } } //其他点已经不可能为边界点 for(y=0;y

35、素点为边界起点的一条边界的 //一条边界的所有边界点,函数采用了递归算法 // 从(x,y)坐标出发,进行边界点的跟踪,跟踪只考虑pResult中没有处理并且可能是边界 // 点的像素(=128),像素值为0表明该点不可能是边界点,像素值为255表明该点已经是边界点 void TraceEdge(int y, int x, int nThrLow, LPBYTE pResult, int *pMag, SIZE sz) { //对8邻域像素进行查询 int xNum[8] = {1,1,0,-1,-1,-1,0,1}; int yNum[8] = {0,1,1,

36、1,0,-1,-1,-1}; LONG yy,xx,k; for(k=0;k<8;k++) { yy = y+yNum[k]; xx = x+xNum[k]; if(pResult[yy*sz.cx+xx]==128 && pMag[yy*sz.cx+xx]>=nThrLow ) { //该点设为边界点 pResult[yy*sz.cx+xx] = 255; //以该点为中心再进行跟踪 TraceEdge(yy,xx,nThrLow,pResult,pMag,sz); } } } // Canny算

37、子 void Canny(LPBYTE pGray, SIZE sz, double sigma, double dRatLow, double dRatHigh, LPBYTE pResult) { //经过高斯滤波后的图像 LPBYTE pGaussSmooth; pGaussSmooth = new unsigned char[sz.cx*sz.cy]; //x方向导数的指针 int *pGradX; pGradX = new int[sz.cx*sz.cy]; //y方向 int *pGradY; pGradY = new int[sz.cx*

38、sz.cy]; //梯度的幅度 int *pGradMag; pGradMag = new int[sz.cx*sz.cy]; //对原图高斯滤波 GaussianSmooth(sz,pGray,pGaussSmooth,sigma); //计算方向导数和梯度的幅度 Grad(sz,pGaussSmooth,pGradX,pGradY,pGradMag); //应用非最大抑制 NonmaxSuppress(pGradMag,pGradX,pGradY,sz,pResult); //应用Hysteresis,找到所有边界 Hysteresis(pGradMag,sz,d

39、RatLow,dRatHigh,pResult); delete[] pGradX; pGradX = NULL; delete[] pGradY; pGradY = NULL; delete[] pGradMag; pGradMag = NULL; delete[] pGaussSmooth; pGaussSmooth = NULL; } /* void CChildWnd::OnCanny() { if (! m_fOpenFile) { return; } m_fDone = TRUE; RGBToGray(szImg, aRGB, aGray, BPP); Canny(aGray,szImg,0.1,0.9,0.76,aBinImg); ShowGrayImage("l",szImg,aBinImg); } //*/

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服