边缘检测的各种算子和滤波器有 Canny算子,Sobel算子,Laplacian算子以及scharr滤波器。
最优边缘检测的三个主要评价标准
低错误率:标识出尽可能多的实际边缘,同时尽可能地减少噪声产生的误报。
高定位性:标识出的边缘要与图像中的实际边缘尽可能接近。
最小响应:图像中的边缘只能标识一次,并且可能存在的图像噪声不应标识为边缘
1.Canny算子
Canny的目标就是找到一个最优的边缘检测算法。Canny使用了变分法,这是一种寻找满足特定功能的函数的方法。最优检测用四个指数函数项的和表示,但是它非常近似于高斯函数的一阶导数。
Canny边缘检测的步骤
第一步 消除噪声 一般情况下,使用高斯平滑滤波器卷积降噪。
第二步 计算梯度幅值和方向 此处按照Sobel滤波器的步骤进行
第三步 非极大值抑制,这一步排除非边缘像素,仅仅保留一些细线条。
第四步 滞后阈值 Canny使用了滞后阈值,滞后阈值需要两个阈值(高阈值和低阈值)
高于高阈值保留为边缘像素 低于低像素排除,在两阈值中间时,若连接到到阈值的像素保留。
CV_EXPORTS_W void Canny( InputArray image, OutputArray edges,
double threshold1, double threshold2,
int apertureSize = 3, bool L2gradient = false );
第三个参数是第一个滞后性阈值,第四个参数是第二个滞后性阈值
一般来说,这个函数阈值1和阈值2两者中较小的值用于边缘连接,而较大的值用来控制强边缘的初始段,
推荐的高低阈值比在2:1到3:1之间
第五个参数表示引用Sobel算子的孔径大小,其有默认值3
第六个参数选择True用L2来归一化,否则用L1化 通常使用false
Mat img11;
img11 = Img1.clone();
//转为灰度图像
cvtColor(Img1, GrayImg, COLOR_BGR2GRAY);
imshow("InputImg", GrayImg);
//进行降噪
blur(GrayImg, GrayImg, Size(3, 3));
//运行Canny算子
Canny(GrayImg, GrayImg, 10, 30);
imshow("out Img", GrayImg); //显示出来的就是边缘图像
Mat dst = Mat::zeros(GrayImg.size(), GrayImg.type());
// 将边缘图GrayImg做为掩膜,来将原图的Img11拷贝到dst中,此时可以输出彩色边缘
img11.copyTo(dst, GrayImg);
imshow("Colr Img", dst);
2.Sobel算子
Sobel算子是一个主要用于边缘检测的离散微分算子。它结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。在图像的任何一点使用此算子,都将会产生对应的梯度矢量或是其法矢量。
CV_EXPORTS_W void Sobel( InputArray src, OutputArray dst, int ddepth,
int dx, int dy, int ksize = 3,
double scale = 1, double delta = 0,
int borderType = BORDER_DEFAULT );
Sobel(GrayImg, Img_x, CV_16S, 1, 0, 3, 1, 0, BORDER_DEFAULT);
convertScaleAbs(Img_x, Img_x); //计算绝对值 将结果转化为8位
imshow("Input Img_x", Img_x);
Sobel(GrayImg, Img_y, CV_16S, 0, 1, 3, 1, 0, BORDER_DEFAULT);
convertScaleAbs(Img_y, Img_y); //计算绝对值 将结果转化为8位
imshow("Input Img_y", Img_y);
addWeighted(Img_x, 0.5, Img_y, 0.5, 0, Img_all);
imshow("Input Img_all", Img_all);
3.laplacian算子
这是一个二阶微分算子,二阶导数可以用来进行边缘检测,因为图像是二维的,需要在两个方向进行求导。
使用laplacian算子将会使求导过程变得简单。
让一幅图像减去他的laplacion算子可以增强对比度
CV_EXPORTS_W void Laplacian( InputArray src, OutputArray dst, int ddepth,
int ksize = 1, double scale = 1, double delta = 0,
int borderType = BORDER_DEFAULT );
// Ksize代表滤波器孔径大小, scale代表计算拉普拉斯值的时候可选的比例因子,
cvtColor(Img1, GrayImg, COLOR_BGR2GRAY);
Mat LaplaceImg;
Laplacian(GrayImg, LaplaceImg,CV_16S,3);
//使用了CV_16S 就必须使用转化绝对值,将值限定在8位输出
convertScaleAbs(LaplaceImg, LaplaceImg);
imshow("laplace Img", LaplaceImg);
4.scharr滤波器
一般直接称scharr为滤波器,而不是算子。他主要是配合Sobel算子的运算而存在的。
CV_EXPORTS_W void Scharr( InputArray src, OutputArray dst, int ddepth,
int dx, int dy, double scale = 1, double delta = 0,
int borderType = BORDER_DEFAULT );
它的参数变量和Sobel基本上是一样的,除了没有ksize核的大小。
Mat Img_x, Img_y, Img_all;
cvtColor(Img1, GrayImg, COLOR_BGR2GRAY);
Scharr(GrayImg, Img_x, CV_16S, 1, 0);
convertScaleAbs(Img_x, Img_x);
imshow("img_x", Img_x);
Scharr(GrayImg, Img_y, CV_16S, 0, 1);
convertScaleAbs(Img_y, Img_y);
imshow("img_y", Img_y);
addWeighted(Img_x, 0.5, Img_y, 0.5,0,Img_all);
imshow("img_all", Img_all);