一、边缘检测概念

图像的边缘检测的原理是检测出图像中所有灰度值变化较大的点,而且这些点连接起来就构成了若干线条,这些线条就可以称为图像的边缘。效果如图:

Opencv学习笔记3:边缘检测算子的实现方法-LMLPHP

接下来介绍一下边缘提取的几种算子,具体证明过程可能会比较简单,重点在函数的使用上。

二、算法实现:

1.索贝尔算子

代码注释:

  在边沿检测中,常用的一种模板是Sobel 算子。Sobel 算子有两个,一个是检测水平边沿的;另一个是检测垂直平边沿的 。 由于Sobel算子是滤波算子的形式,用于提取边缘,可以利用快速卷积函数,简单有效,因此应用广泛。美中不足的是,Sobel算子并没有将图像的主体与背景严格地区分开来,换言之就是Sobel算子没有基于图像灰度进行处理,由于Sobel算子没有严格地模拟人的视觉生理特征,所以提取的图像轮廓有时并不能令人满意。在观测一幅图像的时候,我们往往首先注意的是图像与背景不同的部分,正是这个部分将主体突出显示,基于该理论,我们可以给出阈值化轮廓提取算法,该算法已在数学上证明当像素点满足正态分布时所求解是最优的。

//在x方向求图像近似导数
Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT ); //在y方向求图像近似导数
Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );

2.Canny算子

代码注释:

  Canny算子实现起来较为麻烦,Canny算子是一个具有滤波,增强,检测的多阶段的优化算子,在进行处理前,Canny算子先利用高斯平滑滤波器来平滑图像以除去噪声,Canny分割算法采用一阶偏导的有限差分来计算梯度幅值和方向,在处理过程中,Canny算子还将经过一个非极大值抑制的过程,最后Canny算子还采用两个阈值来连接边缘。

  再强调一下Canny算子的两个参数:第一个是低阈值,第二个高阈值。高阈值比较严格,求的边缘很少,认为高阈值的边缘都是有效。低阈值宽松,求的边缘很多(一般包括了高阈值求到的边缘),其中不少是无效的边缘(反正不想要的)。先用高阈值求边缘。canny求得的边缘希望是连在一起的(通常是封闭的),但高阈值求的边缘一般断断续续。断开的地方如果低阈值求的边缘存在,就用低阈值的边缘接上去,目的让边缘尽量都连在一起。其它情况下低阈值的边缘是不用的。两个阈值是有区别的,高的那个阈值是将要提取轮廓的物体与背景区分开来,就像阈值分割的那个参数一样,是决定目标与背景对比度的,低的那个阈值是用来平滑边缘的轮廓,有时高的阈值设置太大了,可能边缘轮廓不连续或者不够平滑,通过低阈值来平滑轮廓线,或者使不连续的部分连接起来

三、代码实现

#include <opencv.hpp>
using namespace cv;
int main()
{
Mat srcImage;
srcImage = imread("d://1.png");
imshow("【原图】", srcImage);
Mat dst=srcImage; // 构造目标类
//Sobel(srcImage, dst, 0, 1, 0);
Canny(srcImage, dst,30,80);
imshow("【处理后】", dst);
waitKey();
return 0;
}

效果图:

Canny算子处理:

Opencv学习笔记3:边缘检测算子的实现方法-LMLPHP

Sobel处理:

Opencv学习笔记3:边缘检测算子的实现方法-LMLPHP

05-11 10:56