空间域图像增强:Canny边缘检测算法
1986年,JOHN CANNY 提出一个很好的边缘检测算法,被称为Canny
边缘检测器。Canny
边缘检测器是一种经典的图像边缘检测与提取算法,应用广泛,这主要是因为Canny
边缘检测具备以下特点:
- 1.有效的噪声抑制,
Canny
边缘检测内带高斯模糊,x方向和y方向梯度和用2个阈值代替一个阈值,高低阈值连接。 - 2.
Canny
边缘检测较之前的边缘检测算法有更强的完整边缘提取能力。
Canny
算法能够做到精准的边缘提取,它内部主要有下面五个步骤:
- 1.对输入图像进行高斯滤波 ,从而抑制噪声。
- 2.对滤波后的图像进行梯度提取,得到候选边缘。在作者的论文里边缘梯度的计算建议使用
sobel
算子或者prewitt
算子。实际上第一步和第二步可以连起来,这样其实就是前面说过的LOG
算子。 - 3.角度计算与非最大信号抑制(
NMS
),只有中心像素点最大的时候才保留,比两边大。 - 4.高低阈值链接,获取完整边缘。但阈值过高边缘就少,过低噪点就多,高于高阈值全保留,低于全去掉,之间的只要通道高阈值的就保留,否则舍弃。
- 5.输出最终计算并留下的边缘。
OpenCV
中Canny
边缘检测的API如下:
void cv::Canny(
InputArray image,
OutputArray edges,
double threshold1,
double threshold2,
int apertureSize = 3,
bool L2gradient = false
)
其中输入图像可以是单、三通道图像,而输出则是二值图形。参数threshold1
是Canny
边缘检测算法第四步中高低阈值链接中低阈值,参数threshold2
是Canny
边缘检测算法第四步中高低阈值链接中高阈值、高低阈值之比,通常在2:1~3:1之间(经验值)。最后一个参数是计算梯度的方法,可选择L1
(绝对值,计算量较小)或者L2
(平方和开根号)。
代码实践:
/*
Canny边缘检测算法
*/
#include<iostream>
#include<cmath>
#include<opencv2\opencv.hpp>
using namespace std;
using namespace cv;
int main(int argc, char**argv)
{
/*
完整的Canny边缘检测算法包括以下步骤:
1. 彩色图像转换为灰度图像
2. 对图像进行高斯模糊
3. 计算图像梯度,根据梯度计算图像边缘幅值与角度
4. 非最大信号压制处理(边缘细化)
5. 双阈值边缘连接处理
6. 二值化图像输出结果
*/
Mat input = imread("./test_images/car.jpg");
if (input.empty())
{
cout << "read image failed!" << endl;
return -1;
}
imshow("input", input);
Mat gray,canny;
//bgr 2 gray
cvtColor(input, gray, CV_BGR2GRAY);
//canny
Canny(gray, canny, 100, 300, 3, false);
imshow("canny", canny);
waitKey(0);
return 0;
}
运行结果: