十八、Canny边缘检测
1、Canny算法介绍
- Canny是边缘检测算法,1986年提出
- 是一个很好的边缘检测器
- 很常用也很实用的图像处理方法
2、Canny算法介绍—五步
-
高斯模糊去噪
GaussianBlur
-
灰度转换
cvtColor
-
计算梯度
Sobel/Scharr
-
非最大信号抑制
边缘不能很宽,必须选择一个最大值作为边缘
遍历像素值,通过计算其X、Y方向梯度可以求其变化最大的方向 θ \theta θ。将 θ \theta θ分为上图的几个梯度范围,当 θ \theta θ落在某个梯度范围内,判断当前值是否在这个正负梯度范围内为最大值,是则保留,不是则去除。 -
高低阈值输出二值图像
T1、T2为阈值,凡是高于T2的都保留,凡是小于T1的都丢弃,从高于T2的像素出发,凡是大于T1而且相互连接的,都保留。最终得到一个输出二值图像。
推荐的高低阈值比值为T2:T1=3:1或2:1,其中T2为高阈值,T1为低阈值。
3、APICanny
Canny(
InputArray src,//8 bit 的输入图像
OutputArray edges,//输出边缘图像,一般都是二值图像,背景是黑色
double threshold1,//低阈值,常取高阈值的1/2或者1/3
double threshold2,//高阈值
int aptertureSize,//Sobel算子的size,通常是3*3,取值3
bool L2gradient//选择true表示是L2来归一化,否则false表示用L1归一化,L2代表对两个值的平方和开根号,L1是两个数的绝对值相加。默认为L1
)
示例代码:(Canny算子边缘检测)
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
Mat src, dst, gray_src;
int t1_value = 50;
int max_value = 255;
char OUTPUT_WIN[] = "Canny Result";
void canny_demo(int, void*);
int main(int argc, char*argv) {
src = imread("添加图片路径");
if (!src.data) {
cout << "could not load image..." << endl;
return -1;
}
char INPUT_WIN[] = "input image";
namedWindow(INPUT_WIN, WINDOW_AUTOSIZE);
namedWindow(OUTPUT_WIN, WINDOW_AUTOSIZE);
imshow(INPUT_WIN, src);
cvtColor(src, gray_src, COLOR_BGR2GRAY);//转灰度
createTrackbar("Threshold Value:", OUTPUT_WIN, &t1_value, max_value, canny_demo);//创建拖动条,控制阈值
canny_demo(0, 0);
waitKey(0);
return 0;
}
void canny_demo(int, void*) {
Mat edge_output;
GaussianBlur(gray_src, gray_src, Size(3,3), 0, 0);//高斯模糊去噪
Canny(gray_src, edge_output, t1_value, t1_value * 2, 3, false);//Canny边缘检测
//dst.create(src.size(), src.type());//由于创建的dst和src一致是彩色图像,所以当把Canny边缘检测的结果赋给dst时,叠加了原图像的色彩,输出结果为彩色的边缘提取图像
//src.copyTo(dst, edge_output);
imshow(OUTPUT_WIN, ~edge_output); //显示图像,取~可以使图像变成白底黑边,更加美观
}
输出结果显示:
正常输出结果:
取反后输出结果:
叠加彩色值输出结果: