一、Canny算法介绍

Canny 的目标是找到一个最优的边缘检测算法,最优边缘检测的含义是:

好的检测- 算法能够尽可能多地标识出图像中的实际边缘。

好的定位- 标识出的边缘要尽可能与实际图像中的实际边缘尽可能接近。

最小响应- 图像中的边缘只能标识一次,并且可能存在的图像噪声不应标识为边缘。

推文:Canny边缘检测算法原理及其VC实现详解(一)

1、canny算法步骤

1.高斯模糊--GaussianBlur  消除噪声。 一般情况下,使用高斯平滑滤波器卷积降噪。,因为canny是对噪声敏感的算法,所以先降噪,但是降噪不要太过,以免丢失
2.灰度转换--cvtColor  
3.计算梯度--Sobel/Scharr
4.非最大信号抑制
5.高低阈值输出二值图像

2、非最大信号抑制

图像梯度幅值矩阵中的元素值越大,说明图像中该点的梯度值越大,但这不不能说明该点就是边缘(这仅仅是属于图像增强的过程)。在Canny算法中,非极大值抑制是进行边缘检测的重要步骤,通俗意义上是指寻找像素点局部最大值,将非极大值点所对应的灰度值置为0,这样可以剔除掉一大部分非边缘的点(这是本人的理解)。

根据图可知,要进行非极大值抑制,就首先要确定像素点C的灰度值在其8值邻域内是否为最大。图中蓝色的线条方向为C点的梯度方向,这样就可以确定其局部的最大值肯定分布在这条线上,也即出了C点外,梯度方向的交点dTmp1和dTmp2这两个点的值也可能会是局部最大值。因此,判断C点灰度与这两个点灰度大小即可判断C点是否为其邻域内的局部最大灰度点。如果经过判断,C点灰度值小于这两个点中的任一个,那就说明C点不是局部极大值,那么则可以排除C点为边缘。这就是非极大值抑制的工作原理。

  注意以下两点:

1)中非最大抑制是回答这样一个问题:“当前的梯度值在梯度方向上是一个局部最大值吗?” 所以,要把当前位置的梯度值与梯度方向上两侧的梯度值进行比较;

2)梯度方向垂直于边缘方向。

但实际上,我们只能得到C点邻域的8个点的值,而dTmp1和dTmp2并不在其中,要得到这两个值就需要对该两个点两端的已知灰度进行线性插值,也即根据图中的g1和g2对dTmp1进行插值,根据g3和g4对dTmp2进行插值,这要用到其梯度方向,这是Canny算法中要求解梯度方向矩阵Thita的原因。

完成非极大值抑制后,会得到一个二值图像,非边缘的点灰度值均为0,可能为边缘的局部灰度极大值点可设置其灰度为128。根据下文的具体测试图像可以看出,这样一个检测结果还是包含了很多由噪声及其他原因造成的假边缘。因此还需要进一步的处理。

3、高低阈值输出二值图像

二、代码实现两种canny方法

1、需要我们求出梯度,这里用sobel计算梯度

Canny(dx, dy, threshold1, threshold2[, edges[, L2gradient]]) -> edges

使用带自定义图像渐变的Canny算法在图像中查找边缘,

dx参数表示输入图像的x导数(x导数满足16位,选择CV_16SC1或CV_16SC3)

dy参数表示输入图像的y导数(y导数满足16位,选择CV_16SC1或CV_16SC3)。

threshold1参数表示设置的低阈值。

threshold2参数表示设置的高阈值,一般设定为低阈值的3倍 (根据Canny算法的推荐)。

edges参数表示输出边缘图像,单通道8位图像。

L2gradient参数表示L2gradient参数表示一个布尔值,如果为真,则使用更精确的L2范数进行计算(即两个方向的倒数的平方和再开方),否则使用L1范数(直接将两个方向导数的绝对值相加)。

代码实现

 import cv2 as cv

 def edge_demo(image):
#1、高斯模糊 去噪声
#arg:输入图像
#arg:高斯核(可以是(0,0),这样会自动根据sigmax计算得来)
#age:sigmax(高斯核函数在X方向的的标准偏差)
gaosiblur = cv.GaussianBlur(image,(3,3),0) #2、灰度转换
gray = cv.cvtColor(gaosiblur,cv.COLOR_BGR2GRAY) #3、计算梯度
xgrad = cv.Sobel(gray,cv.CV_16SC1,1,0) #canny方法API要求不允许使用浮点数
ygrad = cv.Sobel(gray,cv.CV_16SC1,0,1) #4.Canny方法中包含非最大信号抑制和双阈值输出
edge_output = cv.Canny(xgrad,ygrad,50,150) #50是低阈值,150是高阈值
cv.imshow('canny_edge',edge_output) # 相与,获取颜色(掩模就是canny_edge,两个imag先与之后,最后在与mask与,mask的黑色部分用于剔除,白色部分用于保留)
dst = cv.bitwise_and(image,image,mask=edge_output)
cv.imshow('color edge',dst) img = cv.imread('1.jpg')
cv.imshow('input image',img)
edge_demo(img)
cv.waitKey(0)
cv.destroyAllWindows()

2、直接调用Canny算法在单通道灰度图像中查找边缘

def Canny(image, threshold1, threshold2, edges=None, apertureSize=None, L2gradient=None): 

image参数表示8位输入图像。

threshold1参数表示设置的低阈值。

threshold2参数表示设置的高阈值,一般设定为低阈值的3倍 (根据Canny算法的推荐)。

edges参数表示输出边缘图像,单通道8位图像。

apertureSize参数表示Sobel算子的大小。

L2gradient参数表示一个布尔值,如果为真,则使用更精确的L2范数进行计算(即两个方向的倒数的平方和再开方),否则使用L1范数(直接将两个方向导数的绝对值相加)。

代码实现

 import cv2 as cv

 def edge_demo(image):

     #1、高斯模糊 去噪声
#arg:输入图像
#arg:高斯核(可以是(0,0),这样会自动根据sigmax计算得来)
#age:sigmax(高斯核函数在X方向的的标准偏差)
gaosiblur = cv.GaussianBlur(image,(3,3),0) #2、灰度转换
gray = cv.cvtColor(gaosiblur,cv.COLOR_BGR2GRAY) #3、直接传入灰度图像,Canny方法中包含计算梯度,菲最大信号抑制和双阈值输出
edge_output = cv.Canny(gray,50,150) #50是低阈值,150是高阈值
cv.imshow('canny_edge',edge_output)
dst = cv.bitwise_and(image,image,mask=edge_output) #相与,获取颜色
cv.imshow('color edge',dst)
img = cv.imread('1.jpg')
cv.imshow('input image',img)
edge_demo(img)
cv.waitKey(0)
cv.destroyAllWindows()

三、掩膜mask

在有些图像处理的函数中有的参数里面会有mask参数,即此函数支持掩膜操作,首先何为掩膜以及有什么用,如下:

数字图像处理中的掩膜的概念是借鉴于PCB制版的过程,在半导体制造中,许多芯片工艺步骤采用光刻技术,用于这些步骤的图形“底片”称为掩膜(也称作“掩模”),其作用是:在硅片上选定的区域中对一个不透明的图形模板遮盖,继而下面的腐蚀或扩散将只影响选定的区域以外的区域。
图像掩膜与其类似,用选定的图像、图形或物体,对处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程。

数字图像处理中,掩模为二维矩阵数组,有时也用多值图像,图像掩模主要用于:
①提取感兴趣区,用预先制作的感兴趣区掩模与待处理图像相乘,得到感兴趣区图像,感兴趣区内图像值保持不变,而区外图像值都为0。
②屏蔽作用,用掩模对图像上某些区域作屏蔽,使其不参加处理或不参加处理参数的计算,或仅对屏蔽区作处理或统计。
③结构特征提取,用相似性变量或图像匹配方法检测和提取图像中与掩模相似的结构特征。
④特殊形状图像的制作。

在所有图像基本运算的操作函数中,凡是带有掩膜(mask)的处理函数,其掩膜都参与运算(输入图像运算完之后再与掩膜图像或矩阵运算)。
利用掩膜(mask)进行“与”操作,即掩膜图像白色区域是对需要处理图像像素的保留,黑色区域是对需要处理图像像素的剔除,其余按位操作原理类似只是效果不同而已。

十五 Canny边缘检测算法的更多相关文章

  1. Opencv笔记(十四)——边缘检测算法canny

    简介 Canny 边缘检测算法 是 John F. Canny 于 1986年开发出来的一个多级边缘检测算法,也被很多人认为是边缘检测的 最优算法,它是由很多步构成的算法. 最优边缘检测的三个主要评价 ...

  2. OpenCV: Canny边缘检测算法原理及其VC实现详解(转载)

    原文地址:http://blog.csdn.net/likezhaobin/article/details/6892176 原文地址:http://blog.csdn.net/likezhaobin/ ...

  3. Canny边缘检测算法原理及其VC实现详解(一)

    转自:http://blog.csdn.net/likezhaobin/article/details/6892176 图象的边缘是指图象局部区域亮度变化显著的部分,该区域的灰度剖面一般可以看作是一个 ...

  4. 【算法随记】Canny边缘检测算法实现和优化分析。

    以前的博文大部分都写的非常详细,有很多分析过程,不过写起来确实很累人,一般一篇好的文章要整理个三四天,但是,时间越来越紧张,后续的一些算法可能就以随记的方式,把实现过程的一些比较容易出错和有价值的细节 ...

  5. 一些关于Canny边缘检测算法的改进

    传统的Canny边缘检测算法是一种有效而又相对简单的算法,可以得到很好的结果(可以参考上一篇Canny边缘检测算法的实现).但是Canny算法本身也有一些缺陷,可以有改进的地方. 1. Canny边缘 ...

  6. Canny边缘检测算法的一些改进

    传统的Canny边缘检测算法是一种有效而又相对简单的算法,可以得到很好的结果(可以参考上一篇Canny边缘检测算法的实现).但是Canny算法本身也有一些缺陷,可以有改进的地方. 1. Canny边缘 ...

  7. 【数字图像分析】基于Python实现 Canny Edge Detection(Canny 边缘检测算法)

    Canny 边缘检测算法 Steps: 高斯滤波平滑 计算梯度大小和方向 非极大值抑制 双阈值检测和连接 代码结构: Canny Edge Detection | Gaussian_Smoothing ...

  8. Canny边缘检测算法(基于OpenCV的Java实现)

    目录 Canny边缘检测算法(基于OpenCV的Java实现) 绪论 Canny边缘检测算法的发展历史 Canny边缘检测算法的处理流程 用高斯滤波器平滑图像 彩色RGB图像转换为灰度图像 一维,二维 ...

  9. Canny边缘检测算法原理及其VC实现详解(二)

    转自:http://blog.csdn.net/likezhaobin/article/details/6892629 3.  Canny算法的实现流程 由于本文主要目的在于学习和实现算法,而对于图像 ...

随机推荐

  1. 使用dispatch_once实现单例

    很多人实现单例会这样写: @implementation XXClass + (id)sharedInstance { static XXClass *sharedInstance = nil; @s ...

  2. 固比固布局 圣杯布局 css实现传统手机app布局

    手机app的布局大致上都是头部.内容.底部三部分: 我们需要实现的是头部.底部高度固定:中间内容区域自适应且可以滚动:直接贴代码: css: html,body { width: 100%; heig ...

  3. 2.QT字符串及一些基本操作

    mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> namespace Ui { c ...

  4. PowerDesigner 16.5 安装及破解步骤

     安装: 1.双击运行PowerDesigner16.5_Evaluation.exe,进入安装界面,点击(Next)下一步按钮: 2.下拉菜单选择HongKong,选中 I agree to the ...

  5. AndroidStudio EventBus报错解决方法its super classes have no public methods with the @Subscribe

    首先说明,以前我用eventBus的jar包写得项目demo,前几天就写了一个EventBus的实例,这次我没用jar包,直接用gradle引用的,可是demo写完了,报错: its super cl ...

  6. QT笔记 -- (1) .ui文件

    刚开始写QT,designer用的不习惯,打开.ui文件看了一下,很容易读的xml文件,记录一下. 大体框架如下 <?xml version="1.0" encoding=& ...

  7. oracle11g-rac安装部署

    网上11g rac安装文档大多不详细,今天来一个详细的! 纯操作文档,不喜勿喷!! 环境: 系统:rhel5.5 oracle:11.2.03 双网卡 共享磁盘 ip地址和主机名规划: #节点1 主机 ...

  8. RocketMQ学习笔记(3)----RocketMQ物理结构和逻辑部署结构

    1. RocketMQ的物理结构 RecketMQ网络部署的特点: Name Server是一个几乎无状态特点,可集群部署,节点之间无任何信息同步的(相对于zookeeper是较为轻量级的). Bro ...

  9. Zabbix分布式配置

    Zabbix是一个分布式监控系统,它可以以一个中心点.多个分节点的模式运行,使用Proxy能大大的降低Zabbix Server的压力,Zabbix Proxy可以运行在独立的服务器上,安装Zabbi ...

  10. Vue组件使用基础

    这篇博文用来记录 .vue 组件的使用方法. 可以把组件代码按照 template.style.script 的拆分方式,放置到对应的 .vue 文件中. 模板(template).初始数据(data ...