#include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<opencv2/objdetect.hpp> #include<iostream> using namespace std; using namespace cv; int main(int argc, char **argv) { //加载图片并显示 Mat src = imread("D://XR//JZ//building1.jpg"); imshow("原图",src); //灰度化 Mat grey; cvtColor(src,grey,COLOR_BGR2GRAY); //调用canny函数 Mat edge; Canny(grey,edge,3,9,3); //显示图片 imshow("结果", edge); waitKey(0); }
小编这周又要给小伙伴们讲课啦,学长给我安排的任务是边缘检测。小编翻了翻书,一共有70页。哇!!!范围好大,不过再多还是要讲的,只能跟中秋节说再见了,(╥╯^╰╥)。
小编还是先做个笔记吧,现在能写清楚,到时候就能说清楚。以下内容是我看了许多的博客,自己整合得来的,至于图都是盗来的。
首先,什么是边缘检测呢?
图像的边缘指的是灰度值发生急剧变化的位置。在小编看来,边缘检测是检测出物体的边缘并描绘出来形成一个线图。一般边缘检测都是通过计算梯度幅值,凸显出灰度强度有显著变化的点。
一般边缘检测的有3个步骤:先滤波消除噪声,再计算梯度找出灰度变化强烈的位置,最后阈值化检测找出物体边缘。
梯度:本意是一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模)。梯度反映的是空间变量变化趋势的最大值和方向
梯度方向:是指局部增长最快的方向。以此类推,负梯度方向是指局部下降最快的方向。
边缘检测有很多方法,小编还是先讲一下常用的吧。
1.canny边缘检测
最优的边缘检测算法,先平滑后求导数的方法。
(1)高斯平滑滤波器(消除噪声)
图像矩阵I分别与水平方向上的卷积核sobel(x)和垂直方向上的卷积核sobel(y)卷积得到dx和dy。通常卷积矩阵为奇数。
待处理图像数据(5*5): 卷积核:(3*3)
A = [17 24 01 08 15 H = [8 1 6
23 05 07 14 16 3 5 7
04 06 13 20 22 4 9 2]
10 12 19 21 03
11 18 25 02 09]
步骤:
①将算子围绕中心旋转180度
H’=[2 9 4
7 5 3
6 1 8]
②滑动算子,每个像素相乘相加得到一个数,放入矩阵中间的位置。
例如:(2,4)元素值= 1* 2+ 8* 9+15* 4+ 7* 7+14* 5+16* 3+13* 6+20* 1+22* 8=575
遇到边界则赋值为0。
③重复①②的操作得到dx和dy。
(2)计算梯度幅值和方向(找出灰度变化强烈的地方)
利用高斯滤波得到卷积矩阵dx和dy,利用以下公式来计算:
(3)非极大值抑制(保留了极大值,抑制了非极大值,排除非边缘像素,仅保留了一些细线条)
对图像进行梯度计算后,仅仅基于梯度值提取的边缘仍然很模糊,所以要进行非极大值抑制。解决方法:利用梯度方向。
算法:①将当前像素的梯度强度与沿正负梯度方向上的两个像素进行比较。
②如果当前像素的梯度强度与另外两个像素相比最大,则该像素点保留为边缘点,否则该像素点将被抑制为0。
通常为了更加精确的计算,在跨越梯度方向的两个相邻像素之间使用线性插值来得到要比较的像素梯度,现举例如下:
如图3-2所示,将梯度分为8个方向,分别为E、NE、N、NW、W、SW、S、SE,其中0代表00~45o,1代表450~90o,2代表-900~-45o,3代表-450~0o。像素点P的梯度方向为theta,则像素点P1和P2的梯度线性插值为:
其中E、NE、W等表示该方向上的像素值。
因此非极大值抑制的伪代码描写如下:
(4)滞后阈值(还是有噪声,更准确的找出边缘。)
一般用双阈值检测,设置两个阈值,高阈值TH和低阈值TL。一般比率为2:1或3:1。
如果边缘像素的梯度值高于高阈值,则将其标记为1;如果边缘像素的梯度值小于高阈值并且大于低阈值,则使用8连通域确定,只有与TH像素连接时才会被接受标记成1;如果边缘像素的梯度值小于低阈值,则会被抑制为0。阈值的选择取决于给定输入图像的内容。
双阈值检测的伪代码描写如下:
4连通和8连通域:
所谓四连通区域或四邻域,是指对应像素位置的上、下、左、右,是紧邻的位置。共4个方向,所以称之为四连通区域,又叫四邻域。
所谓八连通区域或八邻域,是指对应位置的上、下、左、右、左上、右上、左下、右下,是紧邻的位置和斜向相邻的位置。共8个方向,所以称之为8连通区域或八邻域。
八连通则定义为:
即点(x,y)的8连通域指的是这个点周围的8个点,例如(x,y)的8联通区域为 (x-1,y-1);(x-1,y);(x-1,y+1); (x,y-1) ;(x,y+1); (x+1,y-1) ;(x+1,y);(x+1,y+1)。
将一个点a带入式子,若得出的坐标与b相同则两个点连通。
对每一个值为1的点若其八连通有一个点的值也为1,那么这两个点就归为一个物体。 从8连通的定义公式可以看到,其为N4四连通并上右下、右上、左下、左上四点,即四连通是八连通的子集。也就是说在图像处理中四连通的区域,一定是八连通。
从上图可以看到,4连通意义上,可以分成独立的三个区域。
在8连通意义上,同样的一个图像,只有一个区域。
原始图像:
边缘检测图像:
相关推荐
Canny边缘检测算法可以分为以下5个步骤: 1) 使用高斯滤波器,以平滑图像,滤除噪声。 2) 计算图像中每个像素点的梯度强度和方向。 3) 应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应...
博文《【OpenCV入门教程之十二】OpenCV边缘检测:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑》的配套详细注释源代码。 博文链接: http://blog.csdn.net/poem_qianmo/article/details/25560901 1.已将dll...
可直接使用
利用Opencv在VS2015平台上对图片进行Canny边缘检测,压缩包中包含整个工程文件
边缘是一幅图像最重要的特征之一,图像边缘部分集中了图像的大部分信息。因此,边缘的确定对于图像场景的识别与理解非常重要;同时在图像分割中也有重要应用。可以利用边缘对图像进行区域分析。边缘在图像体现为局部...
图像的边缘检测的原理是检测出图像中所有灰度...Canny 边缘检测的数学原理和算法实现这里就不再了,有兴趣的读者可以查阅专业书籍,本文主要介绍如何在OpenCV中对图像进行Canny 边缘检测,下面就来看看这个函数的原型。
opencv 边缘检测 canny,sobel等的综合示例
VC++ Opencv Canny 图像处理边缘检测
opencv的canny检测功能,Canny边缘检测于1986年由JOHN CANNY首次在论文《A Computational Approach to Edge Detection》中提出,就此拉开了Canny边缘检测算法的序幕。
opencv 实现的数字图像边缘检测的源代码。非常详细
opencv opencv_基于c++实现的opencv图像处理算法之Canny边缘检测
opencv中的canny边缘检测,可实现边缘发现,比prewitt和sobel算子更细
Canny边缘检测器是一种被广泛使用的算法,并被认为是边缘检测最优的算法,该方法使用了比高斯差分算法更复杂的技巧,如多向灰度梯度和滞后阈值化。Canny边缘检测器算法基本步骤:平滑图像:通过使用合适的模糊半径...
基于opencv的图像识别,canny边缘检测,识别图片中物体边缘
基于OPENCV编程,边缘检测的canny检测算子实现方法,详细的代码,并且本人已经运行,实现成功了的,可以参考!!
使用opecv对图像的边缘进行检测,边缘检测算子canny
OpenCV边缘检测Canny算子sobel算子scharr滤波等代码例子 ide环境VS2015,OpenCV3.4.9,编程语言C++
python+opencv Canny边缘检测的程序实现
包含canny算子的边缘检测源代码,以及在不同噪声下的响应。 自己编写的canny检测各种参数和步骤,可以与opencv自带的canny算子进行比较