Canny边缘检测算法一直是边缘检测的经典算法。下面详细介绍Canny边缘检测算法的原理以及编程实现。

Canny边缘检测基本原理:
(1)图象边缘检测必须满足两个条件:一能有效地抑制噪声;二必须尽量精确确定边缘的位置。
 (2)根据对信噪比与定位乘积进行测度,得到最优化逼近算子。这就是Canny边缘检测算子。
 (3)类似与Marr(LoG)边缘检测方法,也属于先平滑后求导数的方法。

Canny 的目标是找到一个最优的边缘检测算法,最优边缘检测的含义是:
(1)好的检测 - 算法能够尽可能多地标识出图像中的实际边缘。
(2)好的定位 - 标识出的边缘要尽可能与实际图像中的实际边缘尽可能接近。
(3)最小响应 - 图像中的边缘只能标识一次,并且可能存在的图像雜訊不应标识为边缘。

Canny边缘检测算法的步骤:

(1)去噪

任何边缘检测算法都不可能在未经处理的原始数据上很好地處理,所以第一步是对原始数据与高斯 mask 作卷积,得到的图像与原始图像相比有些轻微的模糊(blurred)。这样,单独的一个像素雜訊在经过高斯平滑的图像上变得几乎没有影响。

(2)用一阶偏导的有限差分来计算梯度的幅值和方向。

(3)对梯度幅值进行非极大值抑制。

仅仅得到全局的梯度并不足以确定边缘,因此为确定边缘,必须保留局部梯度最大的点,而抑制非极大值。(non-maxima suppression,NMS)
解决方法:利用梯度的方向。

四个扇区的标号为0到3,对应3*3邻域的四种可能组合。在每一点上,邻域的中心象素M与沿着梯度线的两个象素相比。如果M的梯度值不比沿梯度线的两个相邻象素梯度值大,则令M=0。

(4)用双阈值算法检测和连接边缘。

减少假边缘段数量的典型方法是对N[i,j]使用一个阈值。将低于阈值的所有值赋零值。但问题是如何选取阈值?
 解决方法:双阈值算法。双阈值算法对非极大值抑制图象作用两个阈值τ1和τ2,且2τ1≈τ2,从而可以得到两个阈值边缘图象N1[i,j]和N2[i,j]。由于N2[i,j]使用高阈值得到,因而含有很少的假边缘,但有间断(不闭合)。双阈值法要在N2[i,j]中把边缘连接成轮廓,当到达轮廓的端点时,该算法就在N1[i,j]的8邻点位置寻找可以连接到轮廓上的边缘,这样,算法不断地在N1[i,j]中收集边缘,直到将N2[i,j]连接起来为止。

在连接边缘的时候,用数组模拟队列的实现。以进行8-连通域搜索。

更详细的资料请参考维基百科:http://zh.wikipedia.org/wiki/Canny%E7%AE%97%E5%AD%90

下面是我编程实现的Canny边缘检测代码,如有错误,请大家包涵、指正:

I = imread('rice.png');
I = double(I);
[height,width] = size(I);
J = I;conv = zeros(5,5);%高斯卷积核
sigma = 1;%方差
sigma_2 = sigma * sigma;%临时变量
sum = 0;
for i = 1:5for j = 1:5conv(i,j) = exp((-(i - 3) * (i - 3) - (j - 3) * (j - 3)) / (2 * sigma_2)) / (2 * 3.14 * sigma_2);%高斯公式sum = sum + conv(i,j);end
end
conv = conv./sum;%标准化%对图像实施高斯滤波
for i = 1:heightfor j = 1:widthsum = 0;%临时变量for k = 1:5for m = 1:5if (i - 3 + k) > 0 && (i - 3 + k) <= height && (j - 3 + m) > 0 && (j - 3 + m) < widthsum = sum + conv(k,m) * I(i - 3 + k,j - 3 + m);endendendJ(i,j) = sum;end
end
figure,imshow(J,[])
title('高斯滤波后的结果')
%求梯度
dx = zeros(height,width);%x方向梯度
dy = zeros(height,width);%y方向梯度
d = zeros(height,width);
for i = 1:height - 1for j = 1:width - 1dx(i,j) = J(i,j + 1) - J(i,j);dy(i,j) = J(i + 1,j) - J(i,j);d(i,j) = sqrt(dx(i,j) * dx(i,j) + dy(i,j) * dy(i,j));end
end
figure,imshow(d,[])
title('求梯度后的结果')%局部非极大值抑制
K = d;%记录进行非极大值抑制后的梯度
%设置图像边缘为不可能的边缘点
for j = 1:widthK(1,j) = 0;
end
for j = 1:widthK(height,j) = 0;
end
for i = 2:width - 1K(i,1) = 0;
end
for i = 2:width - 1K(i,width) = 0;
endfor i = 2:height - 1for j = 2:width - 1%当前像素点的梯度值为0,则一定不是边缘点if d(i,j) == 0K(i,j) = 0;elsegradX = dx(i,j);%当前点x方向导数gradY = dy(i,j);%当前点y方向导数gradTemp = d(i,j);%当前点梯度%如果Y方向幅度值较大if abs(gradY) > abs(gradX)weight = abs(gradX) / abs(gradY);%权重grad2 = d(i - 1,j);grad4 = d(i + 1,j);%如果x、y方向导数符号相同%像素点位置关系%g1 g2%   C%   g4 g3if gradX * gradY > 0grad1 = d(i - 1,j - 1);grad3 = d(i + 1,j + 1);else%如果x、y方向导数符号反%像素点位置关系%   g2 g1%   C%g3 g4grad1 = d(i - 1,j + 1);grad3 = d(i + 1,j - 1);end%如果X方向幅度值较大elseweight = abs(gradY) / abs(gradX);%权重grad2 = d(i,j - 1);grad4 = d(i,j + 1);%如果x、y方向导数符号相同%像素点位置关系%g3%g4 C g2%     g1if gradX * gradY > 0grad1 = d(i + 1,j + 1);grad3 = d(i - 1,j - 1);else%如果x、y方向导数符号反%像素点位置关系%     g1%g4 C g2%g3grad1 = d(i - 1,j + 1);grad3 = d(i + 1,j - 1);endend%利用grad1-grad4对梯度进行插值gradTemp1 = weight * grad1 + (1 - weight) * grad2;gradTemp2 = weight * grad3 + (1 - weight) * grad4;%当前像素的梯度是局部的最大值,可能是边缘点if gradTemp >= gradTemp1 && gradTemp >= gradTemp2K(i,j) = gradTemp;else%不可能是边缘点K(i,j) = 0;endendend
end
figure,imshow(K,[])
title('非极大值抑制后的结果')%定义双阈值:EP_MIN、EP_MAX,且EP_MAX = 2 * EP_MIN
EP_MIN = 12;
EP_MAX = EP_MIN * 2;
EdgeLarge = zeros(height,width);%记录真边缘
EdgeBetween = zeros(height,width);%记录可能的边缘点
for i = 1:heightfor j = 1:widthif K(i,j) >= EP_MAX%小于小阈值,不可能为边缘点EdgeLarge(i,j) = K(i,j);else if K(i,j) >= EP_MINEdgeBetween(i,j) = K(i,j);endendend
end
%把EdgeLarge的边缘连成连续的轮廓
MAXSIZE = 999999;
Queue = zeros(MAXSIZE,2);%用数组模拟队列
front = 1;%队头
rear = 1;%队尾
edge = zeros(height,width);
for i = 1:heightfor j = 1:widthif EdgeLarge(i,j) > 0%强点入队Queue(rear,1) = i;Queue(rear,2) = j;rear = rear + 1;edge(i,j) = EdgeLarge(i,j);EdgeLarge(i,j) = 0;%避免重复计算endwhile front ~= rear%队不空%队头出队temp_i = Queue(front,1);temp_j = Queue(front,2);front = front + 1;%8-连通域寻找可能的边缘点%左上方if EdgeBetween(temp_i - 1,temp_j - 1) > 0%把在强点周围的弱点变为强点EdgeLarge(temp_i - 1,temp_j - 1) = K(temp_i - 1,temp_j - 1);EdgeBetween(temp_i - 1,temp_j - 1) = 0;%避免重复计算%入队Queue(rear,1) = temp_i - 1;Queue(rear,2) = temp_j - 1;rear = rear + 1;end%正上方if EdgeBetween(temp_i - 1,temp_j) > 0%把在强点周围的弱点变为强点EdgeLarge(temp_i - 1,temp_j) = K(temp_i - 1,temp_j);EdgeBetween(temp_i - 1,temp_j) = 0;%入队Queue(rear,1) = temp_i - 1;Queue(rear,2) = temp_j;rear = rear + 1;end%右上方if EdgeBetween(temp_i - 1,temp_j + 1) > 0%把在强点周围的弱点变为强点EdgeLarge(temp_i - 1,temp_j + 1) = K(temp_i - 1,temp_j + 1);EdgeBetween(temp_i - 1,temp_j + 1) = 0;%入队Queue(rear,1) = temp_i - 1;Queue(rear,2) = temp_j + 1;rear = rear + 1;end%正左方if EdgeBetween(temp_i,temp_j - 1) > 0%把在强点周围的弱点变为强点EdgeLarge(temp_i,temp_j - 1) = K(temp_i,temp_j - 1);EdgeBetween(temp_i,temp_j - 1) = 0;%入队Queue(rear,1) = temp_i;Queue(rear,2) = temp_j - 1;rear = rear + 1;end%正右方if EdgeBetween(temp_i,temp_j + 1) > 0%把在强点周围的弱点变为强点EdgeLarge(temp_i,temp_j + 1) = K(temp_i,temp_j + 1);EdgeBetween(temp_i,temp_j + 1) = 0;%入队Queue(rear,1) = temp_i;Queue(rear,2) = temp_j + 1;rear = rear + 1;end%左下方if EdgeBetween(temp_i + 1,temp_j - 1) > 0%把在强点周围的弱点变为强点EdgeLarge(temp_i + 1,temp_j - 1) = K(temp_i + 1,temp_j - 1);EdgeBetween(temp_i + 1,temp_j - 1) = 0;%入队Queue(rear,1) = temp_i + 1;Queue(rear,2) = temp_j - 1;rear = rear + 1;end%正下方if EdgeBetween(temp_i + 1,temp_j) > 0%把在强点周围的弱点变为强点EdgeLarge(temp_i + 1,temp_j) = K(temp_i + 1,temp_j);EdgeBetween(temp_i + 1,temp_j) = 0;%入队Queue(rear,1) = temp_i + 1;Queue(rear,2) = temp_j;rear = rear + 1;end%右下方if EdgeBetween(temp_i + 1,temp_j + 1) > 0%把在强点周围的弱点变为强点EdgeLarge(temp_i + 1,temp_j + 1) = K(temp_i + 1,temp_j + 1);EdgeBetween(temp_i + 1,temp_j + 1) = 0;%入队Queue(rear,1) = temp_i + 1;Queue(rear,2) = temp_j + 1;rear = rear + 1;endend%下面2行用于观察程序运行的状况ijend
endfigure,imshow(edge,[])
title('双阈值后的结果')

对图片rice.png进行处理后的 结果如下:

【数字图像处理】Canny边缘检测详解及编程实现相关推荐

  1. 【MATLAB图像处理实用案例详解】目录

    未来一个月的任务主要是GAN生成对抗网络理论部分+代码实战和MATLAB图像处理实用案例详解. 做生成对抗网络主要是因为我的研究方向涉及到这个部分,因此将其作为主要研究内容,但由于研究方向的私密性问题 ...

  2. [转]Hadoop集群_WordCount运行详解--MapReduce编程模型

    Hadoop集群_WordCount运行详解--MapReduce编程模型 下面这篇文章写得非常好,有利于初学mapreduce的入门 http://www.nosqldb.cn/1369099810 ...

  3. 基于多相滤波器的数字信道化算法详解(Python, Verilog代码已开源)

    基于多相滤波器的数字信道化算法详解 推导过程 总结 仿真 本文详细介绍了基于多相滤波器的数字信道化算法的推导过程, 如果您在阅读的过程中发现算法推导过程中有任何错误, 请不吝指出. 此外, 进入我的G ...

  4. 【卷积神经网络CNN 实战案例 GoogleNet 实现手写数字识别 源码详解 深度学习 Pytorch笔记 B站刘二大人 (9.5/10)】

    卷积神经网络CNN 实战案例 GoogleNet 实现手写数字识别 源码详解 深度学习 Pytorch笔记 B站刘二大人 (9.5/10) 在上一章已经完成了卷积神经网络的结构分析,并通过各个模块理解 ...

  5. 90分钟详解网络编程相关的细节处理丨 reactor丨网络io丨epoll丨C/C++丨Linux服务器开发丨后端开发丨Linux后台开发

    90分钟搞懂网络编程相关细节处理 1. 网络编程四要素 2. io多路复用 3. reactor三种基础封装方式 视频讲解如下,点击观看: 90分钟详解网络编程相关的细节处理丨 reactor丨网络i ...

  6. OpenCV-Python图像处理:仿射变换详解及案例

    仿射变换博文传送门(带星号的为付费专栏文章): *图像仿射变换原理1:齐次坐标来龙去脉详解 *图像仿射变换原理2:矩阵变换.线性变换和图像线性变换矩阵 *图像仿射变换原理3:仿射变换类型及变换矩阵详解 ...

  7. python神经网络算法pdf_Python与机器学习实战 决策树、集成学习、支持向量机与神经网络算法详解及编程实现.pdf...

    作 者 :何宇健 出版发行 : 北京:电子工业出版社 , 2017.06 ISBN号 :978-7-121-31720-0 页 数 : 315 原书定价 : 69.00 主题词 : 软件工具-程序设计 ...

  8. OpenGL粒子系统详解及编程实现

    OpenGL粒子系统详解及编程实现 标签: opengl编程 2016-08-23 14:23  1114人阅读  评论(0)  收藏  举报   分类: OSG(6)  版权声明:本文为博主原创文章 ...

  9. 图像处理 | 最常用的边缘检测详解与代码(Robert, Sober, Prewitt, Canny, Kirsch, Laplacian, LOG, DOG算子)

    边缘检测 一阶 Roberts Cross 罗伯茨交叉算子 Sobel 索贝尔算子 Prewitt 普利维特算子 Canny 算子 Kirsch 算子 二阶 Laplacian 拉普拉斯算子 LoG ...

最新文章

  1. SQL Server 将指定的数据库中的所有表都列出来
  2. 使用 Pandas, Jinja 和 WeasyPrint,轻松创建一个 PDF 报表
  3. 宏信建发IT信息部门-大数据-HR面试
  4. 《左手MongoDB右手Redis》第3章笔记-robo3t上进行增删改查
  5. [html] 使用div+css进行布局有什么好处?
  6. 分布式事务最终一致性mysql_分布式事务最终一致性方案案例
  7. 10年Java老鸟忠告:技术人这4个错别再犯了!
  8. matlab正反馈系统根轨迹,正反馈回路和非最小相位系统根轨迹
  9. impala优化 COMPUTE STATS 与COMPUTE INCREMENTAL STATS
  10. MATLAB无法直接打开M文件
  11. Miscellaneous | 恭喜本人博客进入2万名以内,多谢各位支持!
  12. 解决远程桌面背景变黑的问题
  13. 计算机dns怎么设置方法,dns设置_dns怎么设置【步骤|图文教程】-太平洋IT百科
  14. 小程序和html5开发的差异
  15. JavaScript:在一段时间不连续的数据中获取某一段时间段内相同时间间隔的数据
  16. BP神经网络解决什么问题
  17. ctfshow_pwn03
  18. NIST Big Data Interoperability
  19. 013 Rust死灵书之类型转换
  20. 谁不喜欢《长安十二时辰》? | Alfred数据室

热门文章

  1. 期望E==>加权均值(每个元素×它们各自的概率)
  2. 4-2 VGGNet
  3. 0x00000116
  4. ROS学习—opencv使用之图片传输
  5. 程序设计实验与上机考试教程 全国计算机等级考试二级vb模拟试题,程序设计基础实验与上机考试教程...
  6. WordPress多用途电子商务博客新闻主题betheme 21.5.6版本
  7. RiPro主题-子主题huzao-child V4.0简洁大气集成后台美化包
  8. linux 网络瘫痪,Linux内核发现TCP漏洞,小流量也能DoS瘫痪设备
  9. wangeditor上传html,自定义上传事件
  10. 升级版授权系统+盗版追踪+域名IP双授权+在线加密系统