Canny算法介绍
- Canny是边缘检测算法,在1986年提出的。
- 是一个很好的边缘检测器
- 很常用也很实用的图像处理方法
Canny算法介绍 - 非最大信号抑制
Canny算法介绍-高低阈值输出二值图像
- T1, T2为阈值,凡是高于T2的都保留,凡是小于T1都丢弃,从高于T2的像素出发,凡是大于T1而且相互连接的,都保留。最终得到一个输出二值图像。
也就是说:- 如果像素梯度高于上阈值,则该像素被接受为边缘
- 如果像素梯度值低于下阈值,则拒绝它
- 如果像素梯度在两个阈值之间,则仅当它连接到高于上阈值的像素时才接受它。
- 推荐的高低阈值比值为 T2: T1 = 3:1/2:1其中T2为高阈值,T1为低阈值
API – cv::Canny
Canny(
InputArray src, // 8-bit的输入图像,可以是单通道,也可以是多通道
OutputArray edges,// 输出边缘图像,单通道 8-bit, 一般都是二值图像,背景是黑色
double threshold1,// 低阈值,常取高阈值的1/2或者1/3
double threshold2,// 高阈值
int aptertureSize,// Soble算子的size,通常3x3,取值3
bool L2gradient // 选择 true表示是L2来归一化,否则用L1归一化
)
默认情况一般选择是L1,参数设置为false
Canny算法介绍 – 五步 in cv::Canny
- 高斯模糊 - GaussianBlur
- 灰度转换 - cvtColor
- 计算梯度 – Sobel/Scharr
- 非最大信号抑制
- 高低阈值输出二值图像
程序代码
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
Mat src,gray_src,dst;
char* windows_name="Canny Demo Windows";
int value=50,max_value=255;
void Canny_Demo(int, void*);
int main(){
// 1. 加载图像
src=imread("E:/Experiment/OpenCV/Pictures/girl.jpg");
if(!src.data){
printf("Could not load ... ");
return -1;
}
namedWindow(windows_name,CV_WINDOW_AUTOSIZE);
imshow("src",src);
// 2. 转成灰度图像
cvtColor(src, gray_src, CV_BGR2BGRA);
// 3. 创建滚动条,拖动阈值
createTrackbar("低阈值:", windows_name, &value, max_value, Canny_Demo);
Canny_Demo(0,0);
waitKey(0);
return 0;
}
void Canny_Demo(int, void*){
Mat blur_src;
//这里的 blur 仅仅只是对原始图像去干扰,可有可无,Canny 函数内部已经实现了其算法的五个步骤
blur(gray_src, blur_src, Size(3,3), Point(-1,-1),BORDER_DEFAULT);
//输入图像的颜色数据类型要求是8bit , 输入图像可以是 gray ,也可以是 src ,src的干扰线比gray多很多
Canny(blur_src, dst, value, value * 2, 3, false);//边缘检测提取,t1_value越大,检测到的边缘越少
imshow(windows_name, dst); //如果使用 ~dst 表示将图像黑白反过来
Mat result;
result.create(src.size(), src.type());//创建一个相同类型,相同大小的Mat对象
//如果mask.at(i,j)为1,则把src.at(i,j)赋给dst.at(i,j),如果mask.at(i,j)为0,则dst.at(i,j)设为0
src.copyTo(result, dst);
imshow("copyTo", result);
}