OpenCV3入门(八)图像边缘检测
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 = 3, double scale = 1, double delta = 0, 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, 1, 0, 3, 1, 1, BORDER_DEFAULT); convertScaleAbs(imgX, imgX); imshow("X方向Sobel", imgX); //Y方向梯度 Sobel(img, imgY, CV_8U, 0, 1, 3, 1, 1, BORDER_DEFAULT); convertScaleAbs(imgY, imgY); imshow("Y方向Sobel", imgY); //合并梯度(近似) addWeighted(imgX, 0.5, imgY, 0.5, 0, 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(5, 5), 0, 0); imshow("高斯图", img2); Laplacian(img2, img3, CV_8U, 3, 1, 0); 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 = 3, bool L2gradient = false );
示例如下:
img = imread("D:\\WORK\\5.OpenCV\\LeanOpenCV\\pic_src\\pic7.bmp", IMREAD_GRAYSCALE); imshow("原图", img); Canny(img, img2, 3, 9, 3); 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
个人博客,转载请注明。