Canny算法
边缘检测算法:Canny算法
该算法不容易受到噪声的影响,能够识别图像中的弱边缘和强边缘,并结合强弱边缘的位置关系,综合给出图像整体的边缘信息
Canny边缘检测算法目前是最优越的边缘检测算法之一,该方法的检测过程分为以下5步
第一步:使用高斯滤波平滑图像,减少图像中噪声,在一般情况下,使用5x5的高斯滤波器
第二步:计算图像中每个像素的梯度方向和幅值,首先通过Sobel算子分别检测图像X方向的边缘和Y方向的边缘
为了简便,梯度方向常取值0°、45°、90°和135°这4个角度之一
第三步:应用非极大值抑制算法消除边缘检测带来的杂散响应,首先,将当前像素的梯度强度与沿正负梯度方向上的两个像素
进行比较,如果当前像素的梯度强度与另外两个像素梯度强度相比最大,那么该像素点保留位边缘点,否则被抑制
第四步:应用双阈值法划分强边缘和弱边缘,将边缘处的梯度值与两个阈值进行比较,如果某像素的梯度幅值小于较小的阈值
那么会被去除;如果某像素的梯度幅值大于较小幅值、小于较大阈值,那么将该像素标记为弱边缘;如果某像素的梯度
幅值大于较大阈值,那么将该像素标记为强边缘
第五步:消除孤立的弱边缘。在弱边缘的8邻域范围寻找强边缘,如果8领域内存在强边缘,就保留该弱边缘, 否则将删除弱边缘
最终输出边缘检测结果
OpenCV4提供了Canny()函数实现Canny算法检测图像中的边缘
Canny()函数原型:
void Canny(InputArray image,
OuputArray edges,
double threshold1,
double threshold2,
int apertureSize = 3,
bool L2gradient = false
)
- image:输入图像,必须是CV_8U的单通道或者三通道图像
- edges:输出图像,与输入图像具有相同的单通道图像,且数据类型为CV_8U
- threshold1:第一个滞后阈值
- threshold2:第二个滞后阈值
- apertureSize:Sobel算子的直径
- L2gradient:计算图像梯度幅方法的标志(两种)
该函数利用Canny算法提取图像中的边缘信息,第一个参数是需要提取边缘的输入图像,目前只支持数据类型为CV_8U的图像
输入图像可以是灰度图像或者彩色图像,第二个参数是边缘检测结果的输出图像,图像是数据类型为CV_8U的单通道灰度图像
第三、四个参数是Canny算法中用于区分强边缘和弱边缘的两个阈值,两个参数不区分较大阈值和较小阈值,函数自动区分大小
一般情况下较大阈值与较小阈值的比值在2:1到3:1之间
示例:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
//读取图像,黑白图像边缘检测结果较为明显
Mat img = imread("E:\\CLion\\opencv_xin\\SG\\SG_0.jpg",IMREAD_ANYDEPTH);
if (img.empty())
{
cout << "error" << endl;
return -1;
}
Mat resultHigh,resultLow,resultG;
//高阈值检测图像边缘
Canny(img,resultHigh,100,200,3);
//低阈值检测图像边缘
Canny(img,resultLow,20,40,3);
//高斯模糊后检测图像边缘
GaussianBlur(img,resultG,Size(3,3),5);
Canny(resultG,resultG,100,200,3);
//显示图像
imshow("resultHigh",resultHigh);
imshow("resultLow",resultLow);
imshow("resultG",resultG);
waitKey(0);
return 0;
}
注:较高的阈值会降低噪声信息对图像提取边缘结果的影响,但是同时也会减少结果种的边缘结果