【步骤】
1、滤波:减少噪声,主要使用高斯滤波
2、增强:增强算法可以将图像灰度点邻域强度值有显著变化的点凸显出来,在具体编程实现时,可通过计算梯度幅值来确定。
3、检测:经过增强的图像,往往邻域中有很多点的梯度值比较大,而在特定的应用中,这些点并不是我们要找的边缘点,所以应该采用某种方法来对这些点进行取舍。通常用阈值
【cannny算子】
Canny 的目标是找到一个最优的边缘检测算法(低错误率、高定位性、最小时间响应)
步骤1、 Canny算法通常处理的图像为灰度图,首先将图像变为灰度图
步骤2、对图像进行高斯滤波,可以用两个一维高斯核分别两次加权实现,也可以通过一个二维高斯核一次卷积实现。
1)高斯核实现
上式为离散化的一维高斯函数,确定参数就可以得到一维核向量。
上式为离散化的二维高斯函数,确定参数就可以得到二维核向量。
步骤3:用一阶有限差分来计算梯度的幅值和方向,canny梯度算子:
其x向、y向的一阶偏导数矩阵,梯度幅值以及梯度方向的数学表达式为:
步骤4、对梯度幅值进行非极大值抑制
通俗意义上是指寻找像素点局部最大值,将非极大值点所对应的灰度值置为0
步骤5、用双阈值算法检测和连接边缘
Canny算法中减少假边缘数量的方法是采用双阈值法。选择两个阈值,根据高阈值得到一个边缘图像,这样一个图像含有很少的假边缘,但是由于阈值较高,产生的图像边缘可能不闭合,未解决这样一个问题采用了另外一个低阈值。
【原型】
C++: void Canny(InputArray image,OutputArray edges, double threshold1, double threshold2, int apertureSize=3,bool L2gradient=false )
参数1:InputArray类型的image,输入图像,填Mat类的对象即可。
参数2:OutputArray类型的edges,输出的边缘图,需要和源图片有一样的尺寸和类型。
参数3:double类型的threshold1,第一个滞后性阈值。
参数4:double类型的threshold2,第二个滞后性阈值。
参数5:int类型的apertureSize,表示应用Sobel算子的孔径大小,其有默认值3。
参数6:bool类型的L2gradient,一个计算图像梯度幅值的标识,有默认值false。
注:阈值1和阈值2两者的小者用于边缘连接,而大者用来控制强边缘的初始段,推荐的高低阈值比在2:1到3:1之间。
【实例】
#include<opencv2/opencv.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main(int argc, char ** argv) {
Mat srcImage = imread("D:\\study\\picture\\a.jpg");
Mat dstImage, edge, grayImage;
//创建与src大小、类型相同的矩阵 dst
dstImage.create(srcImage.size(), srcImage.type());
//将原图像转换为灰度图像
cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
//使用3*3内核降噪
blur(grayImage, edge, Size(3,3));
//运行Canny算子
Canny(edge, edge, 3, 9, 3);
//显示效果图
imshow("【原图】边缘检测", srcImage);
imshow("【效果图】边缘检测", edge);
waitKey(0);
return 0;
}