1、边缘检测基础

图像的边缘是图像的基本特征,边缘点是灰度阶跃变化的像素点,即灰度值的导数较大或极大的地方,边缘检测是图像识别的第一步。用图像的一阶微分和二阶微分来增强图像的灰度跳变,而边缘也就是灰度变化的地方。因此,这些传统的一阶微分算子如Robert、Sobel、prewitt等,以及二阶微分算子Laplacian等等本质上都是可以用于检测边缘的。这些算子都可以称为边缘检测算子。

边缘检测可以大幅度的减少数据量,剔除那些不相关的信息,保留图像重要的结构属性,一般的边缘检测的步骤有:

1)滤波

边缘检测主要基于图像的一阶和二阶微分,但是导数、微分对噪声很敏感,梯度计算容易受噪声影响,因此需要用滤波来抑制噪声。

2)增强

为了检测边界,需要确定邻域中灰度变化,增强边缘的基础是确定图像各点邻域强度的变化值,利用锐化突出了灰度变化的区域。

3)检测

经过增强的图像,邻域中很多点的梯度值比较大,但是并不是所有点都是边缘点,需要采用某种方法来取舍,一般使用阈值来划分图像各点。

2、边缘检测算子

2.1一阶微分算子

1)原理

图像的边缘就是图像灰度发生快速变化的地方。对于f(t),其导数f'(t)反映了每一处的变化趋势,在变化最快的位置其导数最大,sobel算子的思路就是模拟求一阶导数。

其中:

梯度的方向就是函数f(x,y)最大变化率的方向。梯度的幅值作为最大变化率大小的度量,值为:

离散的二维函数f(i,j),可以用有限差分作为梯度的一个近似值。

为了简化计算,可以用绝对值来近似。

|▽f(i,j)|= |f(i+1,j)-f(i,j)| +|f(i,j+1)-f(i,j)|

2)Sobel算子

Sobel算子是离散微分算子(discrete differentiation operator),用来计算图像灰度的近似梯度,梯度越大越有可能是边缘,Sobel集合了高斯平滑和微分求导,又被称为一阶微分算子、求导算子,在水平和垂直两个方向上求导,得到的是图像在X方法与Y方向梯度图像。

函数原型:

CV_EXPORTS_W void Sobel( InputArray src, OutputArray dst, int ddepth,
int dx, int dy, int ksize = ,
double scale = , double delta = ,
int borderType = BORDER_DEFAULT );

示例代码:

img = imread("D:\\WORK\\5.OpenCV\\LeanOpenCV\\pic_src\\pic7.bmp", IMREAD_GRAYSCALE);
imshow("原图", img); //X方向梯度
Sobel(img, imgX, CV_8U, , , , , , BORDER_DEFAULT);
convertScaleAbs(imgX, imgX);
imshow("X方向Sobel", imgX); //Y方向梯度
Sobel(img, imgY, CV_8U, , , , , , BORDER_DEFAULT);
convertScaleAbs(imgY, imgY);
imshow("Y方向Sobel", imgY); //合并梯度(近似)
addWeighted(imgX, 0.5, imgY, 0.5, , img2);
imshow("整体方向Sobel", img2);

输出结果为:

2.2二阶微分算子

1)原理

二维函数f(x,y)在二阶微分(拉普拉斯算子)的定义为:

将上式相加后就得到拉普拉斯算子:

对应的滤波模板如下:

考虑到求绝对值计算梯度,正负系数图形的响应一样,上面的模板也可以表示为:

上面的模板具有对称性,所以求一次滤波就可以,不需要像一阶微分那样计算2次。

2)应用

拉普拉斯算子是二阶微分算子,对噪声敏感,Laplace算子对孤立象素的响应要比对边缘或线的响应要更强烈,因此只适用于无噪声图象。存在噪声情况下,使用Laplacian算子检测边缘之前需要先进行低通滤波。高斯-拉普拉斯算子,又称LoG算子,就是为了补充这种缺陷被创立的,它先进行高斯低通滤波,然后再进行拉普拉斯二阶微分锐化。

示例如下。

img = imread("D:\\WORK\\5.OpenCV\\LeanOpenCV\\pic_src\\pic7.bmp", IMREAD_GRAYSCALE);
imshow("原图", img);
GaussianBlur(img, img2, Size(, ), , );
imshow("高斯图", img2);
Laplacian(img2, img3, CV_8U, , , );
imshow("Laplacian图", img3);

输出结果为:

2.3 Canny算子

1)原理

在图像边缘检测中,抑制噪声和边缘精准定位是无法同时满足的,一些边缘检测算法通过平滑滤波去除噪声的同时,也增加了边缘检测的不确定性,而提高边缘检测算子对边缘的敏感性的同时,也提高了对噪声的敏感性。Canny算子力图在抗噪声干扰和精准定位之间寻求最佳折中方案。

Canny算法主要有4个步骤:

  • 用高斯滤波器来平滑图像;
  • 用一介偏导的有限差分来计算梯度的幅值和方向;
  • 对梯度进行非极大值抑制,保留极大值,抑制其他值;
  • 用双阈值算法检测和连接边缘。

2)应用

函数原型为:

CV_EXPORTS_W void Canny( InputArray image, OutputArray edges,
double threshold1, double threshold2,
int apertureSize = , bool L2gradient = false );

示例如下:

img = imread("D:\\WORK\\5.OpenCV\\LeanOpenCV\\pic_src\\pic7.bmp", IMREAD_GRAYSCALE);
imshow("原图", img);
Canny(img, img2, , , );
imshow("canny", img2);

输出效果如下图。

修改阈值之后,Canny(img, img2, 45, 90, 3);效果如下图。

3、参考文献

1、《OpenCV3 编程入门》,电子工业出版社,毛星雨著

2、《学习OpenCV》,清华大学出版社,Gary Bradski, Adrian kaehler著

3、Sobel边缘检测

https://www.cnblogs.com/yibeimingyue/p/10878514.html

4、学习笔记-canny边缘检测

https://www.cnblgs.com/mmmmc/p/10524640.html

个人博客,转载请注明。

https://www.cnblogs.com/pingwen/p/12324348.html

OpenCV3入门(八)图像边缘检测的更多相关文章

  1. 图像边缘检测——几种图像边缘检测算子的学习及python 实现

    本文学习利用python学习边缘检测的滤波器,首先读入的图片代码如下: import cv2 from pylab import * saber = cv2.imread("construc ...

  2. CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能

    CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能 效果图 这是红宝书里的例子,在这个例子中,下述功能全部登场,因此这个例子可作为使用Compute Shader的典型 ...

  3. 图像边缘检测--OpenCV之cvCanny函数

    图像边缘检测--OpenCV之cvCanny函数 分类: C/C++ void cvCanny( const CvArr* image, CvArr* edges, double threshold1 ...

  4. Python实现图像边缘检测算法

    title: "Python实现图像边缘检测算法" date: 2018-06-12T17:06:53+08:00 tags: ["图形学"] categori ...

  5. 网络编程懒人入门(八):手把手教你写基于TCP的Socket长连接

    本文原作者:“水晶虾饺”,原文由“玉刚说”写作平台提供写作赞助,原文版权归“玉刚说”微信公众号所有,即时通讯网收录时有改动. 1.引言 好多小白初次接触即时通讯(比如:IM或者消息推送应用)时,总是不 ...

  6. C#基础入门 八

    C#基础入门 八 泛型 C#中的泛型能够将类型作为参数来传递,即在创建类型时用一个特定的符号,如"T"来作为一个占位符,代替实际的类型,等待实例化时用一个实际的类型来代替. pub ...

  7. cesium编程入门(八)设置材质

    cesium编程入门(八)设置材质 Cesium中为几何形状设置材质有多种方法 第一种方法 Material 直接构建Cesium.Material对象,通过设置Material的属性来进行控制,官方 ...

  8. 14图像边缘检测的sobel_ctrl控制模块

    一设计功能 计算得到的dxy,再通过和阈值比较大小,输出po_sum作为VGA的输入,在显示器器上显示图像的轮廓. 二设计思路 根据前一篇博客对sobel算法的介绍,先通过FIFO的双流水线操作采集到 ...

  9. OpenCV3入门(十)图像轮廓

    1.图像轮廓 1.1图像轮廓与API函数 轮廓是一系列相连的点组成的曲线,代表了物体的基本外形,相对于边缘,轮廓是连续的,边缘并不全部连续.一般地,获取图像轮廓要经过下面几个步骤: 1)     读取 ...

随机推荐

  1. .Net Core Linux 下面的操作

       这里以 Ubuntu  8.04版本为例: 1. 注册 Microsoft 密钥 注册产品存储库 安装必需的依赖项 wget -q https://packages.microsoft.com/ ...

  2. C# 调用R语言

    在.net项目中需要调用Matlab生成的DLL,但是在调用过程中报错,截图如下: 在网上搜索一下资料,看到该博客:https://cn.mathworks.com/matlabcentral/new ...

  3. floj 2264

    2.公路建设(highway.c/cpp/pas) 在滨海市一共有n 个城市,编号依次为1到n,它们之间计划修建m条双向道路,其中修建第i条道路的费用为ci. 海霸王作为滨海市公路建设项目的总工程师, ...

  4. Spring Boot2 系列教程 (十一) | 整合数据缓存 Cache

    如题,今天介绍 SpringBoot 的数据缓存.做过开发的都知道程序的瓶颈在于数据库,我们也知道内存的速度是大大快于硬盘的,当需要重复获取相同数据时,一次又一次的请求数据库或者远程服务,导致大量时间 ...

  5. hdu6638 线段树求最大子段和

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6638 Problem Description There are n pirate chests bu ...

  6. 史上最简约的vi教程,复制和粘贴

    上一篇博客,讲了"新手"如何"入门"vi,解决了"两眼一抹黑"的情况.知道在vi下如何进行基本的操作,如部署在Linux下的项目,修改配置文 ...

  7. springboot的yml不显示的原因

    首先排除插件原因 1 安装好插件Ctrl+Alt+S 2 查看修改的application.yml是什么格 在yaml格式中添加*.yaml和*.yml 3 查看maven是否配置完善

  8. 【5min+】帮我排个队,谢谢。await Task.Yield()

    系列介绍 [五分钟的dotnet]是一个利用您的碎片化时间来学习和丰富.net知识的博文系列.它所包含了.net体系中可能会涉及到的方方面面,比如C#的小细节,AspnetCore,微服务中的.net ...

  9. MySQL多表联查以及以及架构

    多表之间关联查询:      据库操作中,多表联合查询是后台开发者常用到的查询语句. JOIN SQL JOIN 子句用于把来自两个或多个表的行结合起来,最常见的 JOIN 类型:SQL INNER ...

  10. java小心机(2)| 重载和构造器的小细节

    每天进步一点点,距离大腿又近一步! 阅读本文大概需要10分钟 java小心机,为你诉说java鲜为人知的一面 涉及基本数据类型的重载 基本类型能从一个"较小"的类型自动提升到&qu ...